Skip to content

Commit 208e907

Browse files
committed
Mac: Implemented TextInput event for all controls
1 parent 3eafe67 commit 208e907

File tree

11 files changed

+308
-61
lines changed

11 files changed

+308
-61
lines changed

src/Eto.Mac/EtoBundle.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
using MonoMac.CoreGraphics;
1313
using MonoMac.ObjCRuntime;
1414
using MonoMac.CoreAnimation;
15+
using nfloat = System.Double;
16+
using nint = System.Int64;
17+
using nuint = System.UInt64;
1518
#endif
1619

1720
namespace Eto.Mac
@@ -20,13 +23,20 @@ static class MarshalDelegates
2023
{
2124
// delegates used for marshalling in .NET Core, as it doesn't support marshalling Func<> or Action<T>
2225
public delegate bool Func_IntPtr_IntPtr_IntPtr_IntPtr_bool(IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4);
26+
public delegate IntPtr Func_IntPtr_IntPtr_IntPtr(IntPtr arg1, IntPtr arg2);
27+
public delegate NSRange Func_IntPtr_IntPtr_NSRange(IntPtr arg1, IntPtr arg2);
28+
public delegate IntPtr Func_IntPtr_IntPtr_NSRange_IntPtr_IntPtr(IntPtr arg1, IntPtr arg2, NSRange arg3, IntPtr arg4);
29+
public delegate nuint Func_IntPtr_IntPtr_CGPoint_nuint(IntPtr arg1, IntPtr arg2, CGPoint arg3);
30+
public delegate CGRect Func_IntPtr_IntPtr_NSRange_IntPtr_CGRect(IntPtr arg1, IntPtr arg2, NSRange arg3, IntPtr arg4);
2331
public delegate void Action_IntPtr_IntPtr_IntPtr(IntPtr arg1, IntPtr arg2, IntPtr arg3);
2432
public delegate bool Func_IntPtr_IntPtr_bool(IntPtr arg1, IntPtr arg2);
2533
public delegate bool Func_IntPtr_IntPtr_IntPtr_bool(IntPtr arg1, IntPtr arg2, IntPtr arg3);
2634
public delegate void Action_IntPtr_IntPtr_CGRect(IntPtr arg1, IntPtr arg2, CGRect arg3);
2735
public delegate void Action_IntPtr_IntPtr(IntPtr arg1, IntPtr arg2);
2836
public delegate NSDragOperation Func_IntPtr_IntPtr_IntPtr_NSDragOperation(IntPtr arg1, IntPtr arg2, IntPtr arg3);
2937
public delegate void Action_IntPtr_IntPtr_CGSize(IntPtr arg1, IntPtr arg2, CGSize arg3);
38+
public delegate void Action_IntPtr_IntPtr_IntPtr_NSRange(IntPtr arg1, IntPtr arg2, IntPtr arg3, NSRange range);
39+
public delegate void Action_IntPtr_IntPtr_IntPtr_NSRange_NSRange(IntPtr arg1, IntPtr arg2, IntPtr arg3, NSRange range, NSRange range2);
3040
}
3141

3242
public static class EtoBundle

src/Eto.Mac/Forms/Controls/ListBoxHandler.cs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,11 @@ public class ListBoxHandler : MacControl<NSTableView, ListBox, ListBox.ICallback
9292
CollectionHandler collection;
9393
MacImageListItemCell cell;
9494

95-
public override NSView ContainerControl
96-
{
97-
get { return scroll; }
98-
}
95+
public override NSView ContainerControl => scroll;
9996

100-
public NSScrollView Scroll
101-
{
102-
get { return scroll; }
103-
}
97+
public NSScrollView Scroll => scroll;
98+
99+
public override NSView TextInputControl => Control;
104100

105101
public class EtoDataSource : NSTableViewDataSource
106102
{
@@ -185,16 +181,9 @@ public override void OnKeyDown(KeyEventArgs e)
185181
}
186182
}
187183

188-
public ContextMenu ContextMenu
189-
{
190-
get;
191-
set;
192-
}
184+
public ContextMenu ContextMenu { get; set; }
193185

194-
protected override NSTableView CreateControl()
195-
{
196-
return new EtoListBoxTableView();
197-
}
186+
protected override NSTableView CreateControl() => new EtoListBoxTableView();
198187

199188
protected override void Initialize()
200189
{

src/Eto.Mac/Forms/Controls/TextAreaHandler.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,11 @@ public override void OnKeyDown(KeyEventArgs e)
169169

170170
public NSScrollView Scroll { get; private set; }
171171

172-
public override NSView ContainerControl
173-
{
174-
get { return Scroll; }
175-
}
172+
public override NSView ContainerControl => Scroll;
176173

177-
protected override NSTextView CreateControl()
178-
{
179-
return new EtoTextView(this);
180-
}
174+
public override NSView TextInputControl => Control;
175+
176+
protected override NSTextView CreateControl() => new EtoTextView(this);
181177

182178
protected override void Initialize()
183179
{

src/Eto.Mac/Forms/Controls/TreeViewHandler.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public class TreeViewHandler : MacControl<NSOutlineView, TreeView, TreeView.ICal
5858

5959
public NSScrollView Scroll { get; private set; }
6060

61+
public override NSView TextInputControl => Control;
62+
6163
public class EtoTreeItem : MacImageData
6264
{
6365
Dictionary<int, EtoTreeItem> items;
@@ -293,15 +295,9 @@ public EtoOutlineView(IntPtr handle) : base(handle)
293295
}
294296
}
295297

296-
public override NSView ContainerControl
297-
{
298-
get { return Scroll; }
299-
}
298+
public override NSView ContainerControl => Scroll;
300299

301-
protected override NSOutlineView CreateControl()
302-
{
303-
return new EtoOutlineView();
304-
}
300+
protected override NSOutlineView CreateControl() => new EtoOutlineView();
305301

306302
protected override void Initialize()
307303
{

src/Eto.Mac/Forms/MacBase.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,9 @@ public interface IMacControlHandler
3232
bool IsEventHandled(string eventName);
3333

3434
NSView ContentControl { get; }
35-
3635
NSView EventControl { get; }
37-
3836
NSView FocusControl { get; }
37+
NSView TextInputControl { get; }
3938

4039
void RecalculateKeyViewLoop(ref NSView last);
4140

src/Eto.Mac/Forms/MacView.cs

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public void ScrollWheel(NSEvent theEvent)
8484
if (h == null) return;
8585
h.Callback.OnMouseWheel(h.Widget, MacConversions.GetMouseEvent(h, theEvent, true));
8686
}
87+
8788
}
8889

8990
public interface IMacViewHandler : IMacControlHandler
@@ -109,6 +110,8 @@ public interface IMacViewHandler : IMacControlHandler
109110
bool? ShouldHaveFocus { get; set; }
110111
int SuppressMouseEvents { get; set; }
111112
bool SuppressMouseTriggerCallback { get; set; }
113+
bool TextInputCancelled { get; set; }
114+
bool TextInputImplemented { get; }
112115

113116
DragEventArgs GetDragEventArgs(NSDraggingInfo info, object customControl);
114117

@@ -126,7 +129,7 @@ public interface IMacViewHandler : IMacControlHandler
126129
MouseEventArgs TriggerMouseUp(NSObject obj, IntPtr sel, NSEvent theEvent);
127130
}
128131

129-
static class MacView
132+
static partial class MacView
130133
{
131134
public static readonly object AutoSize_Key = new object();
132135
public static readonly object MinimumSize_Key = new object();
@@ -138,6 +141,8 @@ static class MacView
138141
public static readonly object Enabled_Key = new object();
139142
public static readonly object ActualEnabled_Key = new object();
140143
public static readonly object AcceptsFirstMouse_Key = new object();
144+
public static readonly object TextInputCancelled_Key = new object();
145+
public static readonly object TextInputImplemented_Key = new object();
141146
public static readonly IntPtr selMouseDown = Selector.GetHandle("mouseDown:");
142147
public static readonly IntPtr selMouseUp = Selector.GetHandle("mouseUp:");
143148
public static readonly IntPtr selMouseDragged = Selector.GetHandle("mouseDragged:");
@@ -154,7 +159,7 @@ static class MacView
154159
public static readonly IntPtr selBecomeFirstResponder = Selector.GetHandle("becomeFirstResponder");
155160
public static readonly IntPtr selSetFrameSize = Selector.GetHandle("setFrameSize:");
156161
public static readonly IntPtr selResignFirstResponder = Selector.GetHandle("resignFirstResponder");
157-
public static readonly IntPtr selInsertText = Selector.GetHandle("insertText:");
162+
public static readonly IntPtr selInsertTextReplacementRange = Selector.GetHandle("insertText:replacementRange:");
158163
public static readonly IntPtr selDraggingEntered = Selector.GetHandle("draggingEntered:");
159164
public static readonly IntPtr selDraggingExited = Selector.GetHandle("draggingExited:");
160165
public static readonly IntPtr selDraggingUpdated = Selector.GetHandle("draggingUpdated:");
@@ -284,6 +289,7 @@ static void TriggerMouseWheel(IntPtr sender, IntPtr sel, IntPtr e)
284289
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, e);
285290
}
286291

292+
static int _interpretingKeyEvents;
287293
internal static MarshalDelegates.Action_IntPtr_IntPtr_IntPtr TriggerKeyDown_Delegate = TriggerKeyDown;
288294
static void TriggerKeyDown(IntPtr sender, IntPtr sel, IntPtr e)
289295
{
@@ -293,7 +299,21 @@ static void TriggerKeyDown(IntPtr sender, IntPtr sel, IntPtr e)
293299
var theEvent = Messaging.GetNSObject<NSEvent>(e);
294300
if (!MacEventView.KeyDown(handler.Widget, theEvent))
295301
{
296-
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, e);
302+
if (handler.TextInputImplemented && _interpretingKeyEvents == 0)
303+
{
304+
_interpretingKeyEvents++;
305+
// sending this twice for the same event actually makes it go to the same control..
306+
handler.TextInputControl.InterpretKeyEvents(new [] { theEvent });
307+
308+
if (!handler.TextInputCancelled)
309+
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, e);
310+
311+
_interpretingKeyEvents--;
312+
}
313+
else
314+
{
315+
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, e);
316+
}
297317
}
298318
}
299319
}
@@ -389,21 +409,28 @@ static void TriggerDraggingExited(IntPtr sender, IntPtr sel, IntPtr draggingInfo
389409
}
390410
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, draggingInfoPtr);
391411
}
412+
392413

393-
internal static MarshalDelegates.Action_IntPtr_IntPtr_IntPtr TriggerTextInput_Delegate = TriggerTextInput;
394-
static void TriggerTextInput(IntPtr sender, IntPtr sel, IntPtr textPtr)
414+
internal static MarshalDelegates.Action_IntPtr_IntPtr_IntPtr_NSRange TriggerTextInput_Delegate = TriggerTextInput;
415+
static void TriggerTextInput(IntPtr sender, IntPtr sel, IntPtr textPtr, NSRange range)
395416
{
396417
var obj = Runtime.GetNSObject(sender);
397418

398419
if (MacBase.GetHandler(obj) is IMacViewHandler handler)
399420
{
421+
handler.TextInputCancelled = false;
400422
var text = (string)Messaging.GetNSObject<NSString>(textPtr);
401423
var args = new TextInputEventArgs(text);
402424
handler.Callback.OnTextInput(handler.Widget, args);
403425
if (args.Cancel)
426+
{
427+
handler.TextInputCancelled = true;
404428
return;
429+
}
405430
}
406-
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, textPtr);
431+
432+
if (ObjCExtensions.SuperClassInstancesRespondsToSelector(obj, sel))
433+
Messaging.void_objc_msgSendSuper_IntPtr_NSRange(obj.SuperHandle, sel, textPtr, range);
407434
}
408435

409436

@@ -499,6 +526,7 @@ static void TriggerSystemAction(IntPtr sender, IntPtr sel, IntPtr e)
499526
}
500527

501528
internal static MarshalDelegates.Func_IntPtr_IntPtr_IntPtr_bool ValidateSystemUserInterfaceItem_Delegate = ValidateSystemUserInterfaceItem;
529+
502530
static bool ValidateSystemUserInterfaceItem(IntPtr sender, IntPtr sel, IntPtr item)
503531
{
504532
var actionHandle = Messaging.IntPtr_objc_msgSend(item, MacView.selGetAction);
@@ -514,22 +542,15 @@ static bool ValidateSystemUserInterfaceItem(IntPtr sender, IntPtr sel, IntPtr it
514542
return command.Enabled;
515543
}
516544
}
517-
518-
var objClass = Messaging.IntPtr_objc_msgSend(sender, MacView.selClass_Handle);
519-
520-
if (objClass == IntPtr.Zero)
521-
return false;
522-
523-
var superClass = ObjCExtensions.class_getSuperclass(objClass);
545+
524546
return
525-
superClass != IntPtr.Zero
526-
&& ObjCExtensions.ClassInstancesRespondToSelector(superClass, sel)
547+
ObjCExtensions.SuperClassInstancesRespondsToSelector(sender, sel)
527548
&& Messaging.bool_objc_msgSendSuper_IntPtr(control.SuperHandle, sel, item);
528549
}
529550

530551
}
531552

532-
public abstract class MacView<TControl, TWidget, TCallback> : MacObject<TControl, TWidget, TCallback>, Control.IHandler, IMacViewHandler
553+
public abstract partial class MacView<TControl, TWidget, TCallback> : MacObject<TControl, TWidget, TCallback>, Control.IHandler, IMacViewHandler
533554
where TControl : NSObject
534555
where TWidget : Control
535556
where TCallback : Control.ICallback
@@ -545,13 +566,13 @@ public abstract class MacView<TControl, TWidget, TCallback> : MacObject<TControl
545566

546567
public abstract NSView ContainerControl { get; }
547568

548-
public virtual NSView ContentControl { get { return ContainerControl; } }
569+
public virtual NSView ContentControl => ContainerControl;
549570

550571
public virtual NSView DragControl => ContainerControl;
551572

552-
public virtual NSView EventControl { get { return ContainerControl; } }
573+
public virtual NSView EventControl => ContainerControl;
553574

554-
public virtual NSView FocusControl { get { return EventControl; } }
575+
public virtual NSView FocusControl => EventControl;
555576

556577
public virtual IEnumerable<Control> VisualControls => Enumerable.Empty<Control>();
557578

@@ -800,7 +821,10 @@ public override void AttachEvent(string id)
800821
// TODO
801822
break;
802823
case Eto.Forms.Control.TextInputEvent:
803-
AddMethod(MacView.selInsertText, MacView.TriggerTextInput_Delegate, "v@:@");
824+
if (EnsureTextInputImplemented())
825+
{
826+
HandleEvent(Eto.Forms.Control.KeyDownEvent);
827+
}
804828
break;
805829

806830
case Eto.Forms.Control.DragDropEvent:
@@ -1456,6 +1480,18 @@ public virtual MouseEventArgs TriggerMouseUp(NSObject obj, IntPtr sel, NSEvent t
14561480
}
14571481
return args;
14581482
}
1483+
1484+
bool IMacViewHandler.TextInputCancelled
1485+
{
1486+
get => Widget.Properties.Get<bool>(MacView.TextInputCancelled_Key);
1487+
set => Widget.Properties.Set(MacView.TextInputCancelled_Key, value);
1488+
}
1489+
1490+
public bool TextInputImplemented
1491+
{
1492+
get => Widget.Properties.Get<bool>(MacView.TextInputImplemented_Key);
1493+
private set => Widget.Properties.Set(MacView.TextInputImplemented_Key, value);
1494+
}
14591495
}
14601496
}
14611497

0 commit comments

Comments
 (0)