diff options
author | Silenio Quarti <silenio> | 2008-07-10 22:04:50 +0000 |
---|---|---|
committer | Silenio Quarti <silenio> | 2008-07-10 22:04:50 +0000 |
commit | e771e3576d1e1ba57ba12fa501dc8174c6ca74e8 (patch) | |
tree | 2f7ad5b5efd2d5b121c654c8d5130bf507d25c7a | |
parent | fe01df1082b5613213a59b03292c02660626087d (diff) | |
download | eclipse.platform.swt-e771e3576d1e1ba57ba12fa501dc8174c6ca74e8.tar.gz eclipse.platform.swt-e771e3576d1e1ba57ba12fa501dc8174c6ca74e8.tar.xz eclipse.platform.swt-e771e3576d1e1ba57ba12fa501dc8174c6ca74e8.zip |
key events and IME
12 files changed, 925 insertions, 182 deletions
diff --git a/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/org.eclipse.swt.internal.cocoa.OS.properties b/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/org.eclipse.swt.internal.cocoa.OS.properties index 6207acd300..8122fd68e9 100755 --- a/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/org.eclipse.swt.internal.cocoa.OS.properties +++ b/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/org.eclipse.swt.internal.cocoa.OS.properties @@ -782,6 +782,8 @@ OS_NSBaselineOffsetAttributeName=flags=const OS_NSBitsPerPixelFromDepth= OS_NSBitsPerPixelFromDepth_0= +OS_NSCalibratedRGBColorSpace=flags=const + OS_NSDefaultRunLoopMode=flags=const OS_NSDeviceRGBColorSpace=flags=const @@ -878,6 +880,12 @@ OS_UnionRgn_0= OS_UnionRgn_1= OS_UnionRgn_2= +OS_attributedSubstringFromRange_CALLBACK=flags=no_gen +OS_attributedSubstringFromRange_CALLBACK_0= + +OS_characterIndexForPoint_CALLBACK=flags=no_gen +OS_characterIndexForPoint_CALLBACK_0= + OS_class_addIvar= OS_class_addIvar_0=cast=(Class) OS_class_addIvar_1=cast=(const char *) @@ -891,12 +899,27 @@ OS_class_addMethod_1=cast=(SEL) OS_class_addMethod_2=cast=(IMP) OS_class_addMethod_3=cast=(const char *) +OS_class_addProtocol= +OS_class_addProtocol_0=cast=Class +OS_class_addProtocol_1=cast=Protocol * + OS_drawRect_CALLBACK=flags=no_gen OS_drawRect_CALLBACK_0= +OS_firstRectForCharacterRange_CALLBACK=flags=no_gen +OS_firstRectForCharacterRange_CALLBACK_0= + OS_hitTest_CALLBACK=flags=no_gen OS_hitTest_CALLBACK_0= +OS_markedRange_CALLBACK=flags=no_gen +OS_markedRange_CALLBACK_0= + +OS_memmove__ILorg_eclipse_swt_internal_cocoa_NSRange_2I= +OS_memmove__ILorg_eclipse_swt_internal_cocoa_NSRange_2I_0=cast=(void *) +OS_memmove__ILorg_eclipse_swt_internal_cocoa_NSRange_2I_1=cast=(void *) +OS_memmove__ILorg_eclipse_swt_internal_cocoa_NSRange_2I_2= + OS_memmove__ILorg_eclipse_swt_internal_cocoa_NSRect_2I= OS_memmove__ILorg_eclipse_swt_internal_cocoa_NSRect_2I_0=cast=(void *) OS_memmove__ILorg_eclipse_swt_internal_cocoa_NSRect_2I_1=cast=(void *) @@ -930,6 +953,9 @@ OS_objc_allocateClassPair_2=cast=(size_t) OS_objc_getClass= OS_objc_getClass_0=cast=(const char *) +OS_objc_getProtocol= +OS_objc_getProtocol_0= + OS_objc_lookUpClass= OS_objc_lookUpClass_0=cast=(const char *) @@ -2875,6 +2901,10 @@ OS_object_getInstanceVariable_0=cast=(id) OS_object_getInstanceVariable_1=cast=(const char *) OS_object_getInstanceVariable_2=cast=(void **) +OS_object_setClass= +OS_object_setClass_0=cast=(id) +OS_object_setClass_1=cast=(Class) + OS_object_setInstanceVariable= OS_object_setInstanceVariable_0=cast=(id) OS_object_setInstanceVariable_1=cast=(const char *) @@ -2883,6 +2913,9 @@ OS_object_setInstanceVariable_2=cast=(void *) OS_sel_registerName= OS_sel_registerName_0=cast=(const char *) +OS_selectedRange_CALLBACK=flags=no_gen +OS_selectedRange_CALLBACK_0= + OS_setFrameOrigin_CALLBACK=flags=no_gen OS_setFrameOrigin_CALLBACK_0= @@ -2892,6 +2925,9 @@ OS_setFrameSize_CALLBACK_0= OS_setFrame_CALLBACK=flags=no_gen OS_setFrame_CALLBACK_0= +OS_setMarkedText_selectedRange_CALLBACK=flags=no_gen +OS_setMarkedText_selectedRange_CALLBACK_0= + OS_webView_setFrame_CALLBACK=flags=no_gen OS_webView_setFrame_CALLBACK_0= diff --git a/bundles/org.eclipse.swt/.classpath_cocoa b/bundles/org.eclipse.swt/.classpath_cocoa index fcd363fe7a..1dbf5d95e7 100755 --- a/bundles/org.eclipse.swt/.classpath_cocoa +++ b/bundles/org.eclipse.swt/.classpath_cocoa @@ -7,7 +7,6 @@ <classpathentry kind="src" path="Eclipse SWT/emulated/bidi"/> <classpathentry kind="src" path="Eclipse SWT/emulated/coolbar"/> <classpathentry kind="src" path="Eclipse SWT/emulated/expand"/> - <classpathentry kind="src" path="Eclipse SWT/emulated/ime"/> <classpathentry kind="src" path="Eclipse SWT/emulated/tooltip"/> <classpathentry kind="src" path="Eclipse SWT PI/common"/> <classpathentry kind="src" path="Eclipse SWT PI/cocoa"> diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/TextLayout.java index 9e3a1acf39..668b74bb6d 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/TextLayout.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/TextLayout.java @@ -50,6 +50,8 @@ public final class TextLayout extends Resource { int[] lineOffsets; NSRect[] lineBounds; + + static final int UNDERLINE_THICK = 1 << 16; static class StyleItem { TextStyle style; @@ -169,7 +171,6 @@ void computeRuns() { } } if (style.underline) { - //TODO - IME - thick int underlineStyle = 0; switch (style.underlineStyle) { case SWT.UNDERLINE_SINGLE: @@ -178,6 +179,9 @@ void computeRuns() { case SWT.UNDERLINE_DOUBLE: underlineStyle = OS.NSUnderlineStyleDouble; break; + case UNDERLINE_THICK: + underlineStyle = OS.NSUnderlineStyleThick; + break; } if (underlineStyle != 0) { textStorage.addAttribute(OS.NSUnderlineStyleAttributeName(), NSNumber.numberWithInt(underlineStyle), range); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Canvas.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Canvas.java index ac6348e913..f474047fab 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Canvas.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Canvas.java @@ -45,6 +45,11 @@ Canvas () { /* Do nothing */ } +int attributedSubstringFromRange (int id, int sel, int range) { + if (ime != null) return ime.attributedSubstringFromRange (id, sel, range); + return super.attributedSubstringFromRange(id, sel, range); +} + boolean becomeFirstResponder (int id, int sel) { if (caret != null) caret.setFocus (); return super.becomeFirstResponder(id, sel); @@ -87,6 +92,11 @@ public Canvas (Composite parent, int style) { super (parent, style); } +int characterIndexForPoint (int id, int sel, int point) { + if (ime != null) return ime.characterIndexForPoint (id, sel, point); + return super.characterIndexForPoint (id, sel, point); +} + /** * Fills the interior of the rectangle specified by the arguments, * with the receiver's background. @@ -158,6 +168,11 @@ void drawRect(int id, NSRect rect) { } } +NSRect firstRectForCharacterRange (int id, int sel, int range) { + if (ime != null) return ime.firstRectForCharacterRange (id, sel, range); + return super.firstRectForCharacterRange (id, sel, range); +} + /** * Returns the caret. * <p> @@ -198,6 +213,23 @@ public IME getIME () { return ime; } +boolean hasMarkedText (int id, int sel) { + if (ime != null) return ime.hasMarkedText (id, sel); + return super.hasMarkedText (id, sel); +} + +boolean insertText (int id, int sel, int string) { + if (ime != null) { + if (!ime.insertText (id, sel, string)) return false; + } + return super.insertText (id, sel, string); +} + +NSRange markedRange (int id, int sel) { + if (ime != null) return ime.markedRange (id, sel); + return super.markedRange (id, sel); +} + //void redrawWidget (int control, boolean children) { // boolean isFocus = OS.VERSION < 0x1040 && caret != null && caret.isFocusCaret (); // if (isFocus) caret.killFocus (); @@ -291,9 +323,14 @@ public void scroll (int destX, int destY, int x, int y, int width, int height, b if (isFocus) caret.setFocus (); } -boolean sendKeyEvent(NSEvent nsEvent, int type) { - if (caret != null) NSCursor.setHiddenUntilMouseMoves(true); - return super.sendKeyEvent(nsEvent, type); +NSRange selectedRange (int id, int sel) { + if (ime != null) return ime.selectedRange (id, sel); + return super.selectedRange (id, sel); +} + +boolean sendKeyEvent (NSEvent nsEvent, int type) { + if (caret != null) NSCursor.setHiddenUntilMouseMoves (true); + return super.sendKeyEvent (nsEvent, type); } /** @@ -357,4 +394,16 @@ public void setIME (IME ime) { this.ime = ime; } +boolean setMarkedText_selectedRange (int id, int sel, int string, int range) { + if (ime != null) { + if (!ime.setMarkedText_selectedRange (id, sel, string, range)) return false; + } + return super.setMarkedText_selectedRange (id, sel, string, range); +} + +int validAttributesForMarkedText (int id, int sel) { + if (ime != null) return ime.validAttributesForMarkedText (id, sel); + return super.validAttributesForMarkedText(id, sel); +} + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Composite.java index bd2a060876..dada57388a 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Composite.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Composite.java @@ -475,12 +475,13 @@ boolean isTabGroup () { return super.isTabGroup (); } -void keyDown(int id, int sel, int theEvent) { - /* needed to avoid bells */ - if (hasFocus () && (state & CANVAS) != 0) { +void keyDown (int id, int sel, int theEvent) { + if ((state & CANVAS) != 0) { + NSArray array = NSArray.arrayWithObject (new NSEvent (theEvent)); + view.interpretKeyEvents (array); return; } - super.keyDown(id, sel, theEvent); + super.keyDown (id, sel, theEvent); } /** diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Control.java index 59ac92648e..748a4b02f8 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Control.java @@ -644,6 +644,21 @@ void destroyWidget () { releaseHandle (); } +boolean doCommandBySelector (int id, int sel, int selector) { + NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent (); + if (nsEvent != null && nsEvent.type () == OS.NSKeyDown) { + boolean [] consume = new boolean [1]; + if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return false; + if (isDisposed ()) return false; + if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return false; + if (consume [0]) return false; + } + if ((state & CANVAS) == 0) { + return super.doCommandBySelector (id, sel, selector); + } + return true; +} + /** * Detects a drag and drop gesture. This method is used * to detect a drag gesture when called from within a mouse @@ -839,6 +854,39 @@ void fixFocus (Control focusControl) { // OS.ClearKeyboardFocus (window); } +void flagsChanged (int id, int sel, int theEvent) { + if (view.window ().firstResponder ().id == id) { + if ((state & SAFARI_EVENTS_FIX) == 0) { + int mask = 0; + NSEvent nsEvent = new NSEvent (theEvent); + int modifiers = nsEvent.modifierFlags (); + int keyCode = Display.translateKey (nsEvent.keyCode ()); + switch (keyCode) { + case SWT.ALT: mask = OS.NSAlternateKeyMask; break; + case SWT.CONTROL: mask = OS.NSControlKeyMask; break; + case SWT.COMMAND: mask = OS.NSCommandKeyMask; break; + case SWT.SHIFT: mask = OS.NSShiftKeyMask; break; + case SWT.CAPS_LOCK: + Event event = new Event(); + event.keyCode = keyCode; + setInputState (event, nsEvent, SWT.KeyDown); + sendKeyEvent (SWT.KeyDown, event); + setInputState (event, nsEvent, SWT.KeyUp); + sendKeyEvent (SWT.KeyUp, event); + break; + } + if (mask != 0) { + int type = (mask & modifiers) != 0 ? SWT.KeyDown : SWT.KeyUp; + Event event = new Event(); + event.keyCode = keyCode; + setInputState (event, nsEvent, type); + if (!sendKeyEvent (type, event)) return; + } + } + } + super.flagsChanged (id, sel, theEvent); +} + NSView focusView () { return view; } @@ -1300,6 +1348,29 @@ int hitTest (int id, int sel, NSPoint point) { return super.hitTest(id, sel, point); } +boolean insertText (int id, int sel, int string) { + NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent (); + if (nsEvent != null && nsEvent.type () == OS.NSKeyDown) { + NSString str = new NSString (string); + if (str.isKindOfClass (OS.objc_getClass ("NSAttributedString"))) { + str = new NSAttributedString (string).string (); + } + int length = str.length (); + char[] buffer = new char [length]; + str.getCharacters_ (buffer); + for (int i = 0; i < buffer.length; i++) { + Event event = new Event (); + if (length == 1) setKeyState (event, SWT.KeyDown, nsEvent); + event.character = buffer [i]; + sendKeyEvent (SWT.KeyDown, event); + } + } + if ((state & CANVAS) == 0) { + return super.insertText (id, sel, string); + } + return true; +} + /** * Invokes platform specific functionality to allocate a new GC handle. * <p> @@ -1493,7 +1564,34 @@ public boolean isVisible () { return getVisible () && parent.isVisible (); } -int menuForEvent (int nsEvent) { +void keyDown (int id, int sel, int theEvent) { + if (view.window ().firstResponder ().id == id) { + boolean textInput = OS.objc_msgSend (id, OS.sel_conformsToProtocol_1, OS.objc_getProtocol ("NSTextInput")) != 0; + if (!textInput) { + NSEvent nsEvent = new NSEvent (theEvent); + boolean [] consume = new boolean [1]; + if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return; + if (isDisposed ()) return; + if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return; + if (consume [0]) return; + } + } + super.keyDown (id, sel, theEvent); +} + +void keyUp (int id, int sel, int theEvent) { + if (view.window ().firstResponder ().id == id) { + NSEvent nsEvent = new NSEvent (theEvent); + if (!sendKeyEvent (nsEvent, SWT.KeyUp)) return; + } + super.keyUp (id, sel, theEvent); +} + +void markLayout (boolean changed, boolean all) { + /* Do nothing */ +} + +int menuForEvent (int id, int sel, int theEvent) { NSPoint pt = NSEvent.mouseLocation(); pt.y = (int) (display.getPrimaryFrame().height - pt.y); int x = (int) pt.x; @@ -1510,10 +1608,7 @@ int menuForEvent (int nsEvent) { } return menu.nsMenu.id; } - objc_super super_struct = new objc_super(); - super_struct.receiver = view.id; - super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass); - return OS.objc_msgSendSuper(super_struct, OS.sel_menuForEvent_1, nsEvent); + return super.menuForEvent (id, sel, theEvent); } Decorations menuShell () { @@ -1545,10 +1640,6 @@ void moved () { sendEvent (SWT.Move); } -void markLayout (boolean changed, boolean all) { - /* Do nothing */ -} - /** * Moves the receiver above the specified control in the * drawing order. If the argument is null, then the receiver @@ -2146,6 +2237,12 @@ void sendFocusEvent (int type, boolean post) { } boolean sendMouseEvent (NSEvent nsEvent, int type, boolean send) { + NSInputManager manager = NSInputManager.currentInputManager (); + if (manager != null && manager.wantsToHandleMouseEvents ()) { + if (manager.handleMouseEvent (nsEvent)) { + return true; + } + } Shell shell = null; Event event = new Event (); switch (type) { @@ -3075,7 +3172,7 @@ boolean translateTraversal (int key, NSEvent theEvent, boolean [] consume) { } int traversalCode (int key, NSEvent theEvent) { - int code = SWT.TRAVERSE_RETURN | SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS; + int code = SWT.TRAVERSE_RETURN | SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_PAGE_NEXT | SWT.TRAVERSE_PAGE_PREVIOUS; Shell shell = getShell (); if (shell.parent != null) code |= SWT.TRAVERSE_ESCAPE; return code; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java index 4b65630249..b4dca00c9f 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java @@ -112,6 +112,8 @@ public class Display extends Device { boolean dragging; Control currentControl, grabControl, trackingControl; + NSDictionary markedAttributes; + Menu menuBar; Menu[] menus; @@ -1607,6 +1609,12 @@ protected void init () { initApplicationDelegate(); application.finishLaunching(); timerDelegate = (SWTWindowDelegate)new SWTWindowDelegate().alloc().init(); + + NSTextView textView = (NSTextView)new NSTextView().alloc(); + textView.initWithFrame (new NSRect ()); + markedAttributes = textView.markedTextAttributes (); + markedAttributes.retain (); + textView.release (); } void initApplicationDelegate() { @@ -1647,6 +1655,7 @@ void addEventMethods (int cls, int proc2, int proc3) { OS.class_addMethod(cls, OS.sel_becomeFirstResponder, proc2, "@:"); OS.class_addMethod(cls, OS.sel_keyDown_1, proc3, "@:@"); OS.class_addMethod(cls, OS.sel_keyUp_1, proc3, "@:@"); + OS.class_addMethod(cls, OS.sel_flagsChanged_1, proc3, "@:@"); } void addFrameMethods(int cls, int setFrameOriginProc, int setFrameSizeProc) { @@ -1679,7 +1688,13 @@ void initClasses () { int setFrameOriginProc = OS.setFrame_CALLBACK(proc3); int setFrameSizeProc = OS.setFrame_CALLBACK(proc3); int hitTestProc = OS.hitTest_CALLBACK(proc3); - + int markedRangeProc = OS.markedRange_CALLBACK(proc2); + int selectedRangeProc = OS.selectedRange_CALLBACK(proc2); + int setMarkedText_selectedRangeProc = OS.setMarkedText_selectedRange_CALLBACK(proc4); + int attributedSubstringFromRangeProc = OS.attributedSubstringFromRange_CALLBACK(proc3); + int characterIndexForPointProc = OS.characterIndexForPoint_CALLBACK(proc3); + int firstRectForCharacterRangeProc = OS.firstRectForCharacterRange_CALLBACK(proc3); + String className = "SWTWindowDelegate"; int cls = OS.objc_allocateClassPair(OS.class_NSObject, className, 0); OS.class_addIvar(cls, SWT_OBJECT, OS.PTR_SIZEOF, (byte)(Math.log(OS.PTR_SIZEOF) / Math.log(2)), "i"); @@ -1711,12 +1726,27 @@ void initClasses () { className = "SWTView"; cls = OS.objc_allocateClassPair(OS.class_NSView, className, 0); + OS.class_addProtocol(cls, OS.objc_getProtocol("NSTextInput")); OS.class_addIvar(cls, SWT_OBJECT, OS.PTR_SIZEOF, (byte)(Math.log(OS.PTR_SIZEOF) / Math.log(2)), "i"); OS.class_addMethod(cls, OS.sel_isFlipped, proc2, "@:"); OS.class_addMethod(cls, OS.sel_drawRect_1, drawRectProc, "@:i"); OS.class_addMethod(cls, OS.sel_acceptsFirstResponder, proc2, "@:"); OS.class_addMethod(cls, OS.sel_isOpaque, proc2, "@:"); OS.class_addMethod(cls, OS.sel_hitTest_1, hitTestProc, "@:{NSPoint}"); + + //NSTextInput protocol + OS.class_addMethod(cls, OS.sel_hasMarkedText, proc2, "@:"); + OS.class_addMethod(cls, OS.sel_markedRange, markedRangeProc, "@:"); + OS.class_addMethod(cls, OS.sel_selectedRange, selectedRangeProc, "@:"); + OS.class_addMethod(cls, OS.sel_setMarkedText_1selectedRange_1, setMarkedText_selectedRangeProc, "@:@{NSRange}"); + OS.class_addMethod(cls, OS.sel_unmarkText, proc2, "@:"); + OS.class_addMethod(cls, OS.sel_validAttributesForMarkedText, proc2, "@:"); + OS.class_addMethod(cls, OS.sel_attributedSubstringFromRange_1, attributedSubstringFromRangeProc, "@:{NSRange}"); + OS.class_addMethod(cls, OS.sel_insertText_1, proc3, "@:@"); + OS.class_addMethod(cls, OS.sel_characterIndexForPoint_1, characterIndexForPointProc, "@:{NSPoint}"); + OS.class_addMethod(cls, OS.sel_firstRectForCharacterRange_1, firstRectForCharacterRangeProc, "@:{NSRange}"); + OS.class_addMethod(cls, OS.sel_doCommandBySelector_1, proc3, "@::"); + addEventMethods(cls, proc2, proc3); addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc); OS.objc_registerClassPair(cls); @@ -1867,6 +1897,17 @@ void initClasses () { OS.class_addIvar(cls, SWT_OBJECT, OS.PTR_SIZEOF, (byte)(Math.log(OS.PTR_SIZEOF) / Math.log(2)), "i"); addEventMethods(cls, proc2, proc3); addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc); + OS.class_addMethod(cls, OS.sel_insertText_1, proc3, "@:@"); + OS.class_addMethod(cls, OS.sel_doCommandBySelector_1, proc3, "@::"); + OS.objc_registerClassPair(cls); + + className = "SWTEditorView"; + cls = OS.objc_allocateClassPair(OS.class_NSTextView, className, 0); + OS.class_addIvar(cls, SWT_OBJECT, OS.PTR_SIZEOF, (byte)(Math.log(OS.PTR_SIZEOF) / Math.log(2)), "i"); + OS.class_addMethod(cls, OS.sel_keyDown_1, proc3, "@:@"); + OS.class_addMethod(cls, OS.sel_keyUp_1, proc3, "@:@"); + OS.class_addMethod(cls, OS.sel_insertText_1, proc3, "@:@"); + OS.class_addMethod(cls, OS.sel_doCommandBySelector_1, proc3, "@::"); OS.objc_registerClassPair(cls); className = "SWTTextField"; @@ -2541,6 +2582,9 @@ void releaseDisplay () { menuBar = null; menus = null; + + if (markedAttributes != null) markedAttributes.release(); + markedAttributes = null; /* The release pool needs to be released before the call backs. */ if (pool != null) pool.release(); @@ -3416,38 +3460,42 @@ int windowDelegateProc(int id, int sel) { if (widget == null) return 0; if (sel == OS.sel_isFlipped) { return widget.isFlipped() ? 1 : 0; - } - if (sel == OS.sel_sendSelection) { + } else if (sel == OS.sel_sendSelection) { widget.sendSelection(); - return 0; - } - if (sel == OS.sel_sendArrowSelection) { + } else if (sel == OS.sel_sendArrowSelection) { widget.sendArrowSelection(); - return 0; - } - if (sel == OS.sel_sendDoubleSelection) { + } else if (sel == OS.sel_sendDoubleSelection) { widget.sendDoubleSelection(); - return 0; - } - if (sel == OS.sel_sendVerticalSelection) { + } else if (sel == OS.sel_sendVerticalSelection) { widget.sendVerticalSelection(); - return 0; - } - if (sel == OS.sel_sendHorizontalSelection) { + } else if (sel == OS.sel_sendHorizontalSelection) { widget.sendHorizontalSelection(); - return 0; - } - if (sel == OS.sel_acceptsFirstResponder) { + } else if (sel == OS.sel_acceptsFirstResponder) { return widget.acceptsFirstResponder(id, sel) ? 1 : 0; - } - if (sel == OS.sel_becomeFirstResponder) { + } else if (sel == OS.sel_becomeFirstResponder) { return widget.becomeFirstResponder(id, sel) ? 1 : 0; - } - if (sel == OS.sel_resignFirstResponder) { + } else if (sel == OS.sel_resignFirstResponder) { return widget.resignFirstResponder(id, sel) ? 1 : 0; - } - if (sel == OS.sel_isOpaque) { + } else if (sel == OS.sel_isOpaque) { return widget.isOpaque(id, sel) ? 1 : 0; + } else if (sel == OS.sel_unmarkText) { + //TODO not called? + } else if (sel == OS.sel_validAttributesForMarkedText) { + return widget.validAttributesForMarkedText (id, sel); + } else if (sel == OS.sel_markedRange) { + NSRange range = widget.markedRange (id, sel); + /* NOTE that this is freed in C */ + int /*long*/ result = OS.malloc (NSRange.sizeof); + OS.memmove (result, range, NSRange.sizeof); + return result; + } else if (sel == OS.sel_selectedRange) { + NSRange range = widget.selectedRange (id, sel); + /* NOTE that this is freed in C */ + int /*long*/ result = OS.malloc (NSRange.sizeof); + OS.memmove (result, range, NSRange.sizeof); + return result; + } else if (sel == OS.sel_hasMarkedText) { + return widget.hasMarkedText (id, sel) ? 1 : 0; } return 0; } @@ -3457,6 +3505,9 @@ int windowDelegateProc(int id, int sel, int arg0) { return timerProc (arg0); } Widget widget = getWidget(id); + if (widget == null && (sel == OS.sel_keyDown_1 ||sel == OS.sel_keyUp_1 ||sel == OS.sel_insertText_1 ||sel == OS.sel_doCommandBySelector_1)) { + widget = getFocusControl (new NSView (id).window ()); + } if (widget == null) return 0; if (sel == OS.sel_windowWillClose_1) { widget.windowWillClose(arg0); @@ -3493,6 +3544,8 @@ int windowDelegateProc(int id, int sel, int arg0) { widget.keyDown(id, sel, arg0); } else if (sel == OS.sel_keyUp_1) { widget.keyUp(id, sel, arg0); + } else if (sel == OS.sel_flagsChanged_1) { + widget.flagsChanged(id, sel, arg0); } else if (sel == OS.sel_mouseUp_1) { widget.mouseUp(id, sel, arg0); } else if (sel == OS.sel_rightMouseDown_1) { @@ -3512,7 +3565,7 @@ int windowDelegateProc(int id, int sel, int arg0) { } else if (sel == OS.sel_mouseExited_1) { widget.mouseExited(id, sel, arg0); } else if (sel == OS.sel_menuForEvent_1) { - return widget.menuForEvent(id); + return widget.menuForEvent(id, sel, arg0); } else if (sel == OS.sel_numberOfRowsInTableView_1) { return widget.numberOfRowsInTableView(arg0); } else if (sel == OS.sel_comboBoxSelectionDidChange_1) { @@ -3545,6 +3598,20 @@ int windowDelegateProc(int id, int sel, int arg0) { widget.pageDown(id, sel, arg0); } else if (sel == OS.sel_pageUp_1) { widget.pageUp(id, sel, arg0); + } else if (sel == OS.sel_attributedSubstringFromRange_1) { + return widget.attributedSubstringFromRange (id, sel, arg0); + } else if (sel == OS.sel_characterIndexForPoint_1) { + return widget.characterIndexForPoint (id, sel, arg0); + } else if (sel == OS.sel_firstRectForCharacterRange_1) { + NSRect rect = widget.firstRectForCharacterRange (id, sel, arg0); + /* NOTE that this is freed in C */ + int /*long*/ result = OS.malloc (NSRect.sizeof); + OS.memmove (result, rect, NSRect.sizeof); + return result; + } else if (sel == OS.sel_insertText_1) { + widget.insertText (id, sel, arg0); + } else if (sel == OS.sel_doCommandBySelector_1) { + widget.doCommandBySelector (id, sel, arg0); } return 0; } @@ -3564,6 +3631,9 @@ int windowDelegateProc(int delegate, int sel, int arg0, int arg1) { return widget.outlineView_shouldExpandItem(arg0, arg1) ? 1 : 0; } else if (sel == OS.sel_menu_1willHighlightItem_1) { widget.menu_willHighlightItem(arg0, arg1); + } else if (sel == OS.sel_setMarkedText_1selectedRange_1) { + widget.setMarkedText_selectedRange (delegate, sel, arg0, arg1); + return 0; } return 0; } @@ -3573,8 +3643,7 @@ int windowDelegateProc(int delegate, int sel, int arg0, int arg1, int arg2) { if (widget == null) return 0; if (sel == OS.sel_tableView_1objectValueForTableColumn_1row_1) { return widget.tableView_objectValueForTableColumn_row(arg0, arg1, arg2); - } - if (sel == OS.sel_tableView_1shouldEditTableColumn_1row_1) { + } else if (sel == OS.sel_tableView_1shouldEditTableColumn_1row_1) { return widget.tableView_shouldEditTableColumn_row(arg0, arg1, arg2) ? 1 : 0; } else if (sel == OS.sel_textView_1clickedOnLink_1atIndex_1) { return widget.clickOnLink(arg0, arg1, arg2) ? 1 : 0; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/IME.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/IME.java new file mode 100644 index 0000000000..6218a0e100 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/IME.java @@ -0,0 +1,498 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.cocoa.*; + +/** + * Instances of this class represent input method editors. + * These are typically in-line pre-edit text areas that allow + * the user to compose characters from Far Eastern languages + * such as Japanese, Chinese or Korean. + * + * <dl> + * <dt><b>Styles:</b></dt> + * <dd>(none)</dd> + * <dt><b>Events:</b></dt> + * <dd>ImeComposition</dd> + * </dl> + * <p> + * IMPORTANT: This class is <em>not</em> intended to be subclassed. + * </p> + * + * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> + * + * @since 3.4 + */ +public class IME extends Widget { + Canvas parent; + int caretOffset; + int startOffset; + int commitCount; + String text; + int [] ranges; + TextStyle [] styles; + + static final int UNDERLINE_THICK = 1 << 16; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +IME () { +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + * <p> + * The style value is either one of the style constants defined in + * class <code>SWT</code> which is applicable to instances of this + * class, or must be built by <em>bitwise OR</em>'ing together + * (that is, using the <code>int</code> "|" operator) two or more + * of those <code>SWT</code> style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + * </p> + * + * @param parent a canvas control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> + * </ul> + * @exception SWTException <ul> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> + * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> + * </ul> + * + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public IME (Canvas parent, int style) { + super (parent, style); + this.parent = parent; + createWidget (); +} + +int attributedSubstringFromRange (int id, int sel, int rangePtr) { + Event event = new Event (); + event.detail = SWT.COMPOSITION_SELECTION; + sendEvent (SWT.ImeComposition, event); + NSRange range = new NSRange (); + OS.memmove (range, rangePtr, NSRange.sizeof); + int start = range.location; + int end = range.location + range.length; + if (event.start <= start && start <= event.end && event.start <= end && end <= event.end) { + NSString str = NSString.stringWith (event.text.substring(start - event.start, end - event.start)); + NSAttributedString attriStr = ((NSAttributedString)new NSAttributedString().alloc()).initWithString_attributes_(str, null); + attriStr.autorelease (); + return attriStr.id; + } + return 0; +} + +int characterIndexForPoint (int id, int sel, int point) { + if (!isInlineEnabled ()) return OS.NSNotFound; + NSPoint pt = new NSPoint (); + OS.memmove (pt, point, NSPoint.sizeof); + NSView view = parent.view; + pt = view.window ().convertScreenToBase (pt); + pt = view.convertPoint_fromView_ (pt, null); + Event event = new Event (); + event.detail = SWT.COMPOSITION_OFFSET; + event.x = (int) pt.x; + event.y = (int) pt.y; + sendEvent (SWT.ImeComposition, event); + int offset = event.index + event.count; + return offset != -1 ? offset : OS.NSNotFound; +} + +void createWidget () { + text = ""; + startOffset = -1; + if (parent.getIME () == null) { + parent.setIME (this); + } +} + +NSRect firstRectForCharacterRange(int id, int sel, int range) { + NSRect rect = new NSRect (); + Caret caret = parent.caret; + if (caret != null) { + NSView view = parent.view; + NSPoint pt = new NSPoint (); + pt.x = caret.x; + pt.y = caret.y + caret.height; + pt = view.convertPoint_toView_ (pt, null); + pt = view.window ().convertBaseToScreen (pt); + rect.x = pt.x; + rect.y = pt.y; + rect.width = caret.width; + rect.height = caret.height; + } + return rect; +} + +/** + * Returns the offset of the caret from the start of the document. + * The caret is within the current composition. + * + * @return the caret offset + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public int getCaretOffset () { + checkWidget (); + return startOffset + caretOffset; +} + +/** + * Returns the commit count of the composition. This is the + * number of characters that have been composed. When the + * commit count is equal to the length of the composition + * text, then the in-line edit operation is complete. + * + * @return the commit count + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see IME#getText + */ +public int getCommitCount () { + checkWidget (); + return commitCount; +} + +/** + * Returns the offset of the composition from the start of the document. + * This is the start offset of the composition within the document and + * in not changed by the input method editor itself during the in-line edit + * session. + * + * @return the offset of the composition + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public int getCompositionOffset () { + checkWidget (); + return startOffset; +} + +/** + * Returns the ranges for the style that should be applied during the + * in-line edit session. + * <p> + * The ranges array contains start and end pairs. Each pair refers to + * the corresponding style in the styles array. For example, the pair + * that starts at ranges[n] and ends at ranges[n+1] uses the style + * at styles[n/2] returned by <code>getStyles()</code>. + * </p> + * @return the ranges for the styles + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see IME#getStyles + */ +public int [] getRanges () { + checkWidget (); + if (ranges == null) return new int [0]; + int [] result = new int [ranges.length]; + for (int i = 0; i < result.length; i++) { + result [i] = ranges [i] + startOffset; + } + return result; +} + +/** + * Returns the styles for the ranges. + * <p> + * The ranges array contains start and end pairs. Each pair refers to + * the corresponding style in the styles array. For example, the pair + * that starts at ranges[n] and ends at ranges[n+1] uses the style + * at styles[n/2]. + * </p> + * + * @return the ranges for the styles + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see IME#getRanges + */ +public TextStyle [] getStyles () { + checkWidget (); + if (styles == null) return new TextStyle [0]; + TextStyle [] result = new TextStyle [styles.length]; + System.arraycopy (styles, 0, result, 0, styles.length); + return result; +} + +TextStyle getStyle (NSDictionary attribs) { + NSArray keys = attribs.allKeys (); + int count = keys.count (); + TextStyle style = new TextStyle (); + for (int j = 0; j < count; j++) { + NSString key = new NSString (keys.objectAtIndex (j)); + if (key.isEqualTo (new NSString (OS.NSBackgroundColorAttributeName ()))) { + NSColor color = new NSColor (attribs.objectForKey (key).id).colorUsingColorSpaceName_ (OS.NSCalibratedRGBColorSpace); + float [] rgbColor = new float []{color.redComponent(), color.greenComponent(), color.blueComponent(), color.alphaComponent()}; + style.background = Color.cocoa_new (display, rgbColor); + } else if (key.isEqualTo (new NSString (OS.NSForegroundColorAttributeName ()))) { + NSColor color = new NSColor (attribs.objectForKey (key).id).colorUsingColorSpaceName_ (OS.NSCalibratedRGBColorSpace); + float [] rgbColor = new float []{color.redComponent(), color.greenComponent(), color.blueComponent(), color.alphaComponent()}; + style.foreground = Color.cocoa_new (display, rgbColor); + } else if (key.isEqualTo (new NSString (OS.NSUnderlineColorAttributeName ()))) { + NSColor color = new NSColor (attribs.objectForKey (key).id).colorUsingColorSpaceName_ (OS.NSCalibratedRGBColorSpace); + float [] rgbColor = new float []{color.redComponent(), color.greenComponent(), color.blueComponent(), color.alphaComponent()}; + style.underlineColor = Color.cocoa_new (display, rgbColor); + } else if (key.isEqualTo (new NSString (OS.NSUnderlineStyleAttributeName ()))) { + NSNumber value = new NSNumber (attribs.objectForKey (key).id); + switch (value.intValue ()) { + case OS.NSUnderlineStyleSingle: style.underlineStyle = SWT.UNDERLINE_SINGLE; break; + case OS.NSUnderlineStyleDouble: style.underlineStyle = SWT.UNDERLINE_DOUBLE; break; + case OS.NSUnderlineStyleThick: style.underlineStyle = UNDERLINE_THICK; break; + } + style.underline = value.intValue () != OS.NSUnderlineStyleNone; + } else if (key.isEqualTo (new NSString (OS.NSStrikethroughColorAttributeName ()))) { + NSColor color = new NSColor (attribs.objectForKey (key).id).colorUsingColorSpaceName_ (OS.NSCalibratedRGBColorSpace); + float [] rgbColor = new float []{color.redComponent(), color.greenComponent(), color.blueComponent(), color.alphaComponent()}; + style.strikeoutColor = Color.cocoa_new (display, rgbColor); + } else if (key.isEqualTo (new NSString (OS.NSStrikethroughStyleAttributeName ()))) { + NSNumber value = new NSNumber (attribs.objectForKey (key).id); + style.strikeout = value.intValue () != OS.NSUnderlineStyleNone; + } else if (key.isEqualTo (new NSString (OS.NSFontAttributeName ()))) { + NSFont font = new NSFont (attribs.objectForKey (key).id); + style.font = Font.cocoa_new (display, font); + } + } + return style; +} + +/** + * Returns the composition text. + * <p> + * The text for an IME is the characters in the widget that + * are in the current composition. When the commit count is + * equal to the length of the composition text, then the + * in-line edit operation is complete. + * </p> + * + * @return the widget text + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public String getText () { + checkWidget (); + return text; +} + +/** + * Returns <code>true</code> if the caret should be wide, and + * <code>false</code> otherwise. In some languages, for example + * Korean, the caret is typically widened to the width of the + * current character in the in-line edit session. + * + * @return the wide caret state + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public boolean getWideCaret() { + return false; +} + +boolean hasMarkedText (int id, int sel) { + return text.length () != 0; +} + +boolean insertText (int id, int sel, int string) { + if (startOffset == -1) return true; + NSString str = new NSString (string); + if (str.isKindOfClass (OS.objc_getClass ("NSAttributedString"))) { + str = new NSAttributedString (string).string (); + } + int length = str.length (); + char[] chars = new char [length]; + str.getCharacters_ (chars); + int end = startOffset + text.length (); + ranges = null; + styles = null; + caretOffset = commitCount = length; + Event event = new Event (); + event.detail = SWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = end; + event.text = text = new String (chars); + sendEvent (SWT.ImeComposition, event); + text = ""; + caretOffset = commitCount = 0; + startOffset = -1; + return event.doit; +} + +boolean isInlineEnabled () { + return hooks (SWT.ImeComposition); +} + +NSRange markedRange (int id, int sel) { + if (startOffset == -1) { + Event event = new Event (); + event.detail = SWT.COMPOSITION_SELECTION; + sendEvent (SWT.ImeComposition, event); + startOffset = event.start; + } + NSRange range = new NSRange (); + range.location = startOffset; + range.length = text.length (); + return range; +} + +void releaseParent () { + super.releaseParent (); + if (this == parent.getIME ()) parent.setIME (null); +} + +void releaseWidget () { + super.releaseWidget (); + parent = null; + text = null; + styles = null; + ranges = null; +} + +NSRange selectedRange (int id, int sel) { + Event event = new Event (); + event.detail = SWT.COMPOSITION_SELECTION; + sendEvent (SWT.ImeComposition, event); + NSRange range = new NSRange (); + range.location = event.start; + range.length = event.text.length (); + return range; +} + +/** + * Sets the offset of the composition from the start of the document. + * This is the start offset of the composition within the document and + * in not changed by the input method editor itself during the in-line edit + * session but may need to be changed by clients of the IME. For example, + * if during an in-line edit operation, a text editor inserts characters + * above the IME, then the IME must be informed that the composition + * offset has changed. + * + * @return the offset of the composition + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public void setCompositionOffset (int offset) { + checkWidget (); + if (offset < 0) return; + if (startOffset != -1) { + startOffset = offset; + } +} + +boolean setMarkedText_selectedRange (int id, int sel, int string, int selRange) { + if (!isInlineEnabled ()) return true; + ranges = null; + styles = null; + caretOffset = commitCount = 0; + int end = startOffset + text.length (); + if (startOffset == -1) { + Event event = new Event (); + event.detail = SWT.COMPOSITION_SELECTION; + sendEvent (SWT.ImeComposition, event); + startOffset = event.start; + end = event.end; + } + NSString str = new NSString (string); + if (str.isKindOfClass (OS.objc_getClass ("NSAttributedString"))) { + NSAttributedString attribStr = new NSAttributedString (string); + str = attribStr.string (); + int length = str.length (); + styles = new TextStyle [length]; + ranges = new int [length * 2]; + NSRange rangeLimit = new NSRange (), effectiveRange = new NSRange (); + rangeLimit.length = length; + int rangeCount = 0; + int /*long*/ ptr = OS.malloc (NSRange.sizeof); + for (int i = 0; i < length;) { + NSDictionary attribs = attribStr.attributesAtIndex_longestEffectiveRange_inRange_ (i, ptr, rangeLimit); + OS.memmove (effectiveRange, ptr, NSRange.sizeof); + i = effectiveRange.location + effectiveRange.length; + ranges [rangeCount * 2] = effectiveRange.location; + ranges [rangeCount * 2 + 1] = effectiveRange.location + effectiveRange.length - 1; + styles [rangeCount++] = getStyle (attribs); + } + OS.free (ptr); + if (rangeCount != styles.length) { + TextStyle [] newStyles = new TextStyle [rangeCount]; + System.arraycopy (styles, 0, newStyles, 0, newStyles.length); + styles = newStyles; + int [] newRanges = new int [rangeCount * 2]; + System.arraycopy (ranges, 0, newRanges, 0, newRanges.length); + ranges = newRanges; + } + } + int length = str.length (); + if (ranges == null && length > 0) { + styles = new TextStyle []{getStyle (display.markedAttributes)}; + ranges = new int[]{0, length - 1}; + } + NSRange range = new NSRange (); + OS.memmove (range, selRange, NSRange.sizeof); + caretOffset = range.location; + char [] chars = new char [length]; + str.getCharacters_ (chars); + Event event = new Event (); + event.detail = SWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = end; + event.text = text = new String (chars); + sendEvent (SWT.ImeComposition, event); + return true; +} + +int validAttributesForMarkedText (int id, int sel) { + NSMutableArray attribs = NSMutableArray.arrayWithCapacity (6); + attribs.addObject (new NSString (OS.NSForegroundColorAttributeName ())); + attribs.addObject (new NSString (OS.NSBackgroundColorAttributeName ())); + attribs.addObject (new NSString (OS.NSUnderlineStyleAttributeName ())); + attribs.addObject (new NSString (OS.NSUnderlineColorAttributeName ())); + attribs.addObject (new NSString (OS.NSStrikethroughStyleAttributeName ())); + attribs.addObject (new NSString (OS.NSStrikethroughColorAttributeName ())); + return attribs.id; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Shell.java index 532b9c5760..ff48f76308 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Shell.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Shell.java @@ -503,6 +503,11 @@ void createHandle () { window.setAcceptsMouseMovedEvents(true); windowDelegate = (SWTWindowDelegate)new SWTWindowDelegate().alloc().init(); window.setDelegate(windowDelegate); + + id id = window.fieldEditor (true, null); + if (id != null) { + OS.object_setClass (id.id, OS.objc_getClass ("SWTEditorView")); + } } void deregister () { @@ -1338,7 +1343,8 @@ void setWindowVisible (boolean visible, boolean key) { } void setZOrder () { - window.setContentView (topView()); + if (scrollView != null) scrollView.setDocumentView (view); + window.setContentView (scrollView != null ? scrollView : view); } void setZOrder (Control control, boolean above) { @@ -1436,28 +1442,4 @@ boolean windowShouldClose(int window) { void windowWillClose(int notification) { } -void windowSendEvent(int id, int event) { - NSEvent nsEvent = new NSEvent(event); - int type = nsEvent.type(); - if (type == OS.NSFlagsChanged) { - Control eventTarget = display.getFocusControl(); - if (eventTarget != null) { - if (eventTarget.flagsChanged(event)) return; - } - } else if (type == OS.NSKeyDown || type == OS.NSKeyUp) { - Control eventTarget = display.getFocusControl(); - if (eventTarget != null) { - if (type == OS.NSKeyDown) { - boolean[] consume = new boolean[1]; - int key = nsEvent.keyCode(); - if (eventTarget.translateTraversal(key, nsEvent, consume)) return; - if (consume[0]) return; - if (eventTarget.isDisposed()) return; - } - if (!eventTarget.sendKeyEvent(nsEvent, type == OS.NSKeyDown ? SWT.KeyDown : SWT.KeyUp)) return; - } - } - super.windowSendEvent(id, event); -} - } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Text.java index 0f1c8c22a5..33139fee30 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Text.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Text.java @@ -1143,67 +1143,68 @@ public void selectAll () { } } -boolean sendKeyEvent (int type, Event event) { - if (!super.sendKeyEvent (type, event)) { - return false; - } - if (type != SWT.KeyDown) return true; - if ((style & SWT.READ_ONLY) != 0) return true; - if (event.character == 0) return true; - if ((event.stateMask & SWT.COMMAND) != 0) return true; - String oldText = ""; - int charCount = getCharCount (); - Point selection = getSelection (); - int start = selection.x, end = selection.y; - switch (event.character) { - case SWT.BS: - if (start == end) { - if (start == 0) return true; - start = Math.max (0, start - 1); - } - break; - case SWT.DEL: - if (start == end) { - if (start == charCount) return true; - end = Math.min (end + 1, charCount); - } - break; - case SWT.CR: - if ((style & SWT.SINGLE) != 0) return true; - oldText = DELIMITER; - break; - default: - if (event.character != '\t' && event.character < 0x20) return true; - oldText = new String (new char [] {event.character}); - } - String newText = verifyText (oldText, start, end, event); - if (newText == null) return false; - if (charCount - (end - start) + newText.length () > textLimit) { - return false; - } - boolean result = newText == oldText; - if (newText != oldText || hiddenText != null) { -// if (txnObject == 0) { -// String text = new String (getEditText (0, -1)); -// String leftText = text.substring (0, start); -// String rightText = text.substring (end, text.length ()); -// setEditText (leftText + newText + rightText); -// start += newText.length (); -// setSelection (new Point (start, start)); -// result = false; -// } else { -// setTXNText (start, end, newText); -// } - } - /* - * Post the modify event so that the character will be inserted - * into the widget when the modify event is delivered. Normally, - * modify events are sent but it is safe to post the event here - * because this method is called from the event loop. - */ - postEvent (SWT.Modify); - return result; -} +//boolean sendKeyEvent (int type, Event event) { +// //TODO +// if (!super.sendKeyEvent (type, event)) { +// return false; +// } +// if (type != SWT.KeyDown) return true; +// if ((style & SWT.READ_ONLY) != 0) return true; +// if (event.character == 0) return true; +// if ((event.stateMask & SWT.COMMAND) != 0) return true; +// String oldText = ""; +// int charCount = getCharCount (); +// Point selection = getSelection (); +// int start = selection.x, end = selection.y; +// switch (event.character) { +// case SWT.BS: +// if (start == end) { +// if (start == 0) return true; +// start = Math.max (0, start - 1); +// } +// break; +// case SWT.DEL: +// if (start == end) { +// if (start == charCount) return true; +// end = Math.min (end + 1, charCount); +// } +// break; +// case SWT.CR: +// if ((style & SWT.SINGLE) != 0) return true; +// oldText = DELIMITER; +// break; +// default: +// if (event.character != '\t' && event.character < 0x20) return true; +// oldText = new String (new char [] {event.character}); +// } +// String newText = verifyText (oldText, start, end, event); +// if (newText == null) return false; +// if (charCount - (end - start) + newText.length () > textLimit) { +// return false; +// } +// boolean result = newText == oldText; +// if (newText != oldText || hiddenText != null) { +//// if (txnObject == 0) { +//// String text = new String (getEditText (0, -1)); +//// String leftText = text.substring (0, start); +//// String rightText = text.substring (end, text.length ()); +//// setEditText (leftText + newText + rightText); +//// start += newText.length (); +//// setSelection (new Point (start, start)); +//// result = false; +//// } else { +//// setTXNText (start, end, newText); +//// } +// } +// /* +// * Post the modify event so that the character will be inserted +// * into the widget when the modify event is delivered. Normally, +// * modify events are sent but it is safe to post the event here +// * because this method is called from the event loop. +// */ +// postEvent (SWT.Modify); +// return result; +//} void setBackground (float [] color) { NSColor nsColor; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/ToolItem.java index dad355ce5d..e540f40ce1 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/ToolItem.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/ToolItem.java @@ -511,8 +511,8 @@ public boolean isEnabled () { return getEnabled () && parent.isEnabled (); } -int menuForEvent (int event) { - return parent.menuForEvent(event); +int menuForEvent (int id, int sel, int theEvent) { + return parent.menuForEvent (id, sel, theEvent); } void register () { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Widget.java index 9fc7889356..4d10de8ffd 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Widget.java @@ -129,6 +129,10 @@ public Widget (Widget parent, int style) { display = parent.display; } +int attributedSubstringFromRange (int id, int sel, int range) { + return 0; +} + void callSuper(int id, int selector, int arg0) { objc_super super_struct = new objc_super(); super_struct.receiver = id; @@ -143,6 +147,10 @@ boolean callSuperBoolean(int id, int sel) { return OS.objc_msgSendSuper(super_struct, sel) != 0; } +int characterIndexForPoint (int id, int sel, int point) { + return OS.NSNotFound; +} + boolean acceptsFirstResponder (int id, int sel) { return callSuperBoolean(id, sel); } @@ -378,6 +386,11 @@ public void dispose () { release (true); } +boolean doCommandBySelector (int id, int sel, int aSelector) { + callSuper (id, sel, aSelector); + return true; +} + void drawBackground (int control, int context) { /* Do nothing */ } @@ -400,6 +413,10 @@ boolean filters (int eventType) { return display.filters (eventType); } +NSRect firstRectForCharacterRange(int id, int sel, int range) { + return new NSRect (); +} + int fixMnemonic (char [] buffer) { int i=0, j=0; while (i < buffer.length) { @@ -559,6 +576,10 @@ public int getStyle () { return style; } +boolean hasMarkedText (int id, int sel) { + return false; +} + void helpRequested(int theEvent) { } @@ -574,6 +595,11 @@ boolean hooks (int eventType) { return eventTable.hooks (eventType); } +boolean insertText (int id, int sel, int string) { + callSuper (id, sel, string); + return true; +} + /** * Returns <code>true</code> if the widget has been disposed, * and <code>false</code> otherwise. @@ -626,32 +652,8 @@ boolean isValidThread () { return getDisplay ().isValidThread (); } -boolean flagsChanged (int theEvent) { - if ((state & SAFARI_EVENTS_FIX) != 0) return true; - int mask = 0; - NSEvent nsEvent = new NSEvent (theEvent); - int modifiers = nsEvent.modifierFlags (); - int keyCode = Display.translateKey (nsEvent.keyCode ()); - if (keyCode == 0) return true; - switch (keyCode) { - case SWT.ALT: mask = OS.NSAlternateKeyMask; break; - case SWT.CONTROL: mask = OS.NSControlKeyMask; break; - case SWT.COMMAND: mask = OS.NSCommandKeyMask; break; - case SWT.SHIFT: mask = OS.NSShiftKeyMask; break; - case SWT.CAPS_LOCK: - Event event = new Event(); - event.keyCode = keyCode; - setInputState (event, nsEvent, SWT.KeyDown); - sendKeyEvent (SWT.KeyDown, event); - setInputState (event, nsEvent, SWT.KeyUp); - sendKeyEvent (SWT.KeyUp, event); - return true; - } - int type = (mask & modifiers) != 0 ? SWT.KeyDown : SWT.KeyUp; - Event event = new Event(); - event.keyCode = keyCode; - setInputState (event, nsEvent, type); - return sendKeyEvent (type, event); +void flagsChanged (int id, int sel, int theEvent) { + callSuper (id, sel, theEvent); } void keyDown (int id, int sel, int theEvent) { @@ -702,13 +704,20 @@ void mouseExited(int id, int sel, int theEvent) { callSuper(id, sel, theEvent); } -int menuForEvent (int event) { - return 0; +int menuForEvent (int id, int sel, int theEvent) { + objc_super super_struct = new objc_super(); + super_struct.receiver = id; + super_struct.cls = OS.objc_msgSend(id, OS.sel_superclass); + return OS.objc_msgSendSuper(super_struct, sel, theEvent); } void menuNeedsUpdate(int menu) { } +NSRange markedRange (int id, int sel) { + return new NSRange (); +} + void menu_willHighlightItem(int menu, int item) { } @@ -928,6 +937,10 @@ void scrollWheel (int id, int sel, int theEvent) { callSuper(id, sel, theEvent); } +NSRange selectedRange (int id, int sel) { + return new NSRange (); +} + void sendArrowSelection () { } @@ -969,23 +982,9 @@ void sendEvent (int eventType, Event event, boolean send) { boolean sendKeyEvent (NSEvent nsEvent, int type) { if ((state & SAFARI_EVENTS_FIX) != 0) return true; - NSString chars = nsEvent.characters (); - int length = chars.length(); - if (length > 1) { - for (int i = 0; i < length; i++) { - Event event = new Event (); - event.character = (char) chars.characterAtIndex (i); - setInputState (event, nsEvent, type); - sendKeyEvent (type, event); - } - return true; - } else if (length == 1) { - Event event = new Event (); - if (!setKeyState (event, type, nsEvent)) return true; - return sendKeyEvent (type, event); - } - //TODO dead keys - return true; + Event event = new Event (); + if (!setKeyState (event, type, nsEvent)) return true; + return sendKeyEvent (type, event); } boolean sendKeyEvent (int type, Event event) { @@ -1207,12 +1206,12 @@ boolean setKeyState (Event event, int type, NSEvent nsEvent) { default: if (event.keyCode == 0 || (SWT.KEYPAD_MULTIPLY <= event.keyCode && event.keyCode <= SWT.KEYPAD_CR)) { NSString chars = nsEvent.characters (); - event.character = (char)chars.characterAtIndex (0); + if (chars.length() > 0) event.character = (char)chars.characterAtIndex (0); } if (event.keyCode == 0) { //TODO this is wrong for shifted keys like ';', '1' and non-english keyboards - NSString chars = nsEvent.charactersIgnoringModifiers ().lowercaseString(); - event.keyCode = (char)chars.characterAtIndex(0); + NSString unmodifiedChars = nsEvent.charactersIgnoringModifiers ().lowercaseString(); + if (unmodifiedChars.length() > 0) event.keyCode = (char)unmodifiedChars.characterAtIndex(0); } } if (event.keyCode == 0 && event.character == 0) { @@ -1222,6 +1221,10 @@ boolean setKeyState (Event event, int type, NSEvent nsEvent) { return true; } +boolean setMarkedText_selectedRange (int id, int sel, int string, int range) { + return true; +} + void tableViewSelectionDidChange (int aNotification) { } @@ -1254,6 +1257,10 @@ public String toString () { return getName () + " {" + string + "}"; } +int validAttributesForMarkedText (int id, int sel) { + return 0; +} + void willSelectTabViewItem(int tabView, int tabViewItem) { } |