Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac: Implemented TextInput event for all controls #2150

Merged
merged 2 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ env:
jobs:
build-windows:

runs-on: windows-latest
runs-on: windows-2019

steps:
- uses: actions/checkout@v2
Expand Down
10 changes: 10 additions & 0 deletions src/Eto.Mac/EtoBundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
using MonoMac.CoreGraphics;
using MonoMac.ObjCRuntime;
using MonoMac.CoreAnimation;
using nfloat = System.Double;
using nint = System.Int64;
using nuint = System.UInt64;
#endif

namespace Eto.Mac
Expand All @@ -20,13 +23,20 @@ static class MarshalDelegates
{
// delegates used for marshalling in .NET Core, as it doesn't support marshalling Func<> or Action<T>
public delegate bool Func_IntPtr_IntPtr_IntPtr_IntPtr_bool(IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4);
public delegate IntPtr Func_IntPtr_IntPtr_IntPtr(IntPtr arg1, IntPtr arg2);
public delegate NSRange Func_IntPtr_IntPtr_NSRange(IntPtr arg1, IntPtr arg2);
public delegate IntPtr Func_IntPtr_IntPtr_NSRange_IntPtr_IntPtr(IntPtr arg1, IntPtr arg2, NSRange arg3, IntPtr arg4);
public delegate nuint Func_IntPtr_IntPtr_CGPoint_nuint(IntPtr arg1, IntPtr arg2, CGPoint arg3);
public delegate CGRect Func_IntPtr_IntPtr_NSRange_IntPtr_CGRect(IntPtr arg1, IntPtr arg2, NSRange arg3, IntPtr arg4);
public delegate void Action_IntPtr_IntPtr_IntPtr(IntPtr arg1, IntPtr arg2, IntPtr arg3);
public delegate bool Func_IntPtr_IntPtr_bool(IntPtr arg1, IntPtr arg2);
public delegate bool Func_IntPtr_IntPtr_IntPtr_bool(IntPtr arg1, IntPtr arg2, IntPtr arg3);
public delegate void Action_IntPtr_IntPtr_CGRect(IntPtr arg1, IntPtr arg2, CGRect arg3);
public delegate void Action_IntPtr_IntPtr(IntPtr arg1, IntPtr arg2);
public delegate NSDragOperation Func_IntPtr_IntPtr_IntPtr_NSDragOperation(IntPtr arg1, IntPtr arg2, IntPtr arg3);
public delegate void Action_IntPtr_IntPtr_CGSize(IntPtr arg1, IntPtr arg2, CGSize arg3);
public delegate void Action_IntPtr_IntPtr_IntPtr_NSRange(IntPtr arg1, IntPtr arg2, IntPtr arg3, NSRange range);
public delegate void Action_IntPtr_IntPtr_IntPtr_NSRange_NSRange(IntPtr arg1, IntPtr arg2, IntPtr arg3, NSRange range, NSRange range2);
}

public static class EtoBundle
Expand Down
23 changes: 6 additions & 17 deletions src/Eto.Mac/Forms/Controls/ListBoxHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,11 @@ public class ListBoxHandler : MacControl<NSTableView, ListBox, ListBox.ICallback
CollectionHandler collection;
MacImageListItemCell cell;

public override NSView ContainerControl
{
get { return scroll; }
}
public override NSView ContainerControl => scroll;

public NSScrollView Scroll
{
get { return scroll; }
}
public NSScrollView Scroll => scroll;

public override NSView TextInputControl => Control;

public class EtoDataSource : NSTableViewDataSource
{
Expand Down Expand Up @@ -185,16 +181,9 @@ public override void OnKeyDown(KeyEventArgs e)
}
}

public ContextMenu ContextMenu
{
get;
set;
}
public ContextMenu ContextMenu { get; set; }

protected override NSTableView CreateControl()
{
return new EtoListBoxTableView();
}
protected override NSTableView CreateControl() => new EtoListBoxTableView();

protected override void Initialize()
{
Expand Down
12 changes: 4 additions & 8 deletions src/Eto.Mac/Forms/Controls/TextAreaHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,11 @@ public override void OnKeyDown(KeyEventArgs e)

public NSScrollView Scroll { get; private set; }

public override NSView ContainerControl
{
get { return Scroll; }
}
public override NSView ContainerControl => Scroll;

protected override NSTextView CreateControl()
{
return new EtoTextView(this);
}
public override NSView TextInputControl => Control;

protected override NSTextView CreateControl() => new EtoTextView(this);

protected override void Initialize()
{
Expand Down
12 changes: 4 additions & 8 deletions src/Eto.Mac/Forms/Controls/TreeViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public class TreeViewHandler : MacControl<NSOutlineView, TreeView, TreeView.ICal

public NSScrollView Scroll { get; private set; }

public override NSView TextInputControl => Control;

public class EtoTreeItem : MacImageData
{
Dictionary<int, EtoTreeItem> items;
Expand Down Expand Up @@ -293,15 +295,9 @@ public EtoOutlineView(IntPtr handle) : base(handle)
}
}

public override NSView ContainerControl
{
get { return Scroll; }
}
public override NSView ContainerControl => Scroll;

protected override NSOutlineView CreateControl()
{
return new EtoOutlineView();
}
protected override NSOutlineView CreateControl() => new EtoOutlineView();

protected override void Initialize()
{
Expand Down
3 changes: 1 addition & 2 deletions src/Eto.Mac/Forms/MacBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ public interface IMacControlHandler
bool IsEventHandled(string eventName);

NSView ContentControl { get; }

NSView EventControl { get; }

NSView FocusControl { get; }
NSView TextInputControl { get; }

void RecalculateKeyViewLoop(ref NSView last);

Expand Down
76 changes: 56 additions & 20 deletions src/Eto.Mac/Forms/MacView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public void ScrollWheel(NSEvent theEvent)
if (h == null) return;
h.Callback.OnMouseWheel(h.Widget, MacConversions.GetMouseEvent(h, theEvent, true));
}

}

public interface IMacViewHandler : IMacControlHandler
Expand All @@ -109,6 +110,8 @@ public interface IMacViewHandler : IMacControlHandler
bool? ShouldHaveFocus { get; set; }
int SuppressMouseEvents { get; set; }
bool SuppressMouseTriggerCallback { get; set; }
bool TextInputCancelled { get; set; }
bool TextInputImplemented { get; }

DragEventArgs GetDragEventArgs(NSDraggingInfo info, object customControl);

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

static class MacView
static partial class MacView
{
public static readonly object AutoSize_Key = new object();
public static readonly object MinimumSize_Key = new object();
Expand All @@ -138,6 +141,8 @@ static class MacView
public static readonly object Enabled_Key = new object();
public static readonly object ActualEnabled_Key = new object();
public static readonly object AcceptsFirstMouse_Key = new object();
public static readonly object TextInputCancelled_Key = new object();
public static readonly object TextInputImplemented_Key = new object();
public static readonly IntPtr selMouseDown = Selector.GetHandle("mouseDown:");
public static readonly IntPtr selMouseUp = Selector.GetHandle("mouseUp:");
public static readonly IntPtr selMouseDragged = Selector.GetHandle("mouseDragged:");
Expand All @@ -154,7 +159,7 @@ static class MacView
public static readonly IntPtr selBecomeFirstResponder = Selector.GetHandle("becomeFirstResponder");
public static readonly IntPtr selSetFrameSize = Selector.GetHandle("setFrameSize:");
public static readonly IntPtr selResignFirstResponder = Selector.GetHandle("resignFirstResponder");
public static readonly IntPtr selInsertText = Selector.GetHandle("insertText:");
public static readonly IntPtr selInsertTextReplacementRange = Selector.GetHandle("insertText:replacementRange:");
public static readonly IntPtr selDraggingEntered = Selector.GetHandle("draggingEntered:");
public static readonly IntPtr selDraggingExited = Selector.GetHandle("draggingExited:");
public static readonly IntPtr selDraggingUpdated = Selector.GetHandle("draggingUpdated:");
Expand Down Expand Up @@ -284,6 +289,7 @@ static void TriggerMouseWheel(IntPtr sender, IntPtr sel, IntPtr e)
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, e);
}

static int _interpretingKeyEvents;
internal static MarshalDelegates.Action_IntPtr_IntPtr_IntPtr TriggerKeyDown_Delegate = TriggerKeyDown;
static void TriggerKeyDown(IntPtr sender, IntPtr sel, IntPtr e)
{
Expand All @@ -293,7 +299,21 @@ static void TriggerKeyDown(IntPtr sender, IntPtr sel, IntPtr e)
var theEvent = Messaging.GetNSObject<NSEvent>(e);
if (!MacEventView.KeyDown(handler.Widget, theEvent))
{
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, e);
if (handler.TextInputImplemented && _interpretingKeyEvents == 0)
{
_interpretingKeyEvents++;
// sending this twice for the same event actually makes it go to the same control..
handler.TextInputControl.InterpretKeyEvents(new [] { theEvent });

if (!handler.TextInputCancelled)
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, e);

_interpretingKeyEvents--;
}
else
{
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, e);
}
}
}
}
Expand Down Expand Up @@ -389,21 +409,28 @@ static void TriggerDraggingExited(IntPtr sender, IntPtr sel, IntPtr draggingInfo
}
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, draggingInfoPtr);
}


internal static MarshalDelegates.Action_IntPtr_IntPtr_IntPtr TriggerTextInput_Delegate = TriggerTextInput;
static void TriggerTextInput(IntPtr sender, IntPtr sel, IntPtr textPtr)
internal static MarshalDelegates.Action_IntPtr_IntPtr_IntPtr_NSRange TriggerTextInput_Delegate = TriggerTextInput;
static void TriggerTextInput(IntPtr sender, IntPtr sel, IntPtr textPtr, NSRange range)
{
var obj = Runtime.GetNSObject(sender);

if (MacBase.GetHandler(obj) is IMacViewHandler handler)
{
handler.TextInputCancelled = false;
var text = (string)Messaging.GetNSObject<NSString>(textPtr);
var args = new TextInputEventArgs(text);
handler.Callback.OnTextInput(handler.Widget, args);
if (args.Cancel)
{
handler.TextInputCancelled = true;
return;
}
}
Messaging.void_objc_msgSendSuper_IntPtr(obj.SuperHandle, sel, textPtr);

if (ObjCExtensions.SuperClassInstancesRespondsToSelector(obj, sel))
Messaging.void_objc_msgSendSuper_IntPtr_NSRange(obj.SuperHandle, sel, textPtr, range);
}


Expand Down Expand Up @@ -499,6 +526,7 @@ static void TriggerSystemAction(IntPtr sender, IntPtr sel, IntPtr e)
}

internal static MarshalDelegates.Func_IntPtr_IntPtr_IntPtr_bool ValidateSystemUserInterfaceItem_Delegate = ValidateSystemUserInterfaceItem;

static bool ValidateSystemUserInterfaceItem(IntPtr sender, IntPtr sel, IntPtr item)
{
var actionHandle = Messaging.IntPtr_objc_msgSend(item, MacView.selGetAction);
Expand All @@ -514,22 +542,15 @@ static bool ValidateSystemUserInterfaceItem(IntPtr sender, IntPtr sel, IntPtr it
return command.Enabled;
}
}

var objClass = Messaging.IntPtr_objc_msgSend(sender, MacView.selClass_Handle);

if (objClass == IntPtr.Zero)
return false;

var superClass = ObjCExtensions.class_getSuperclass(objClass);

return
superClass != IntPtr.Zero
&& ObjCExtensions.ClassInstancesRespondToSelector(superClass, sel)
ObjCExtensions.SuperClassInstancesRespondsToSelector(sender, sel)
&& Messaging.bool_objc_msgSendSuper_IntPtr(control.SuperHandle, sel, item);
}

}

public abstract class MacView<TControl, TWidget, TCallback> : MacObject<TControl, TWidget, TCallback>, Control.IHandler, IMacViewHandler
public abstract partial class MacView<TControl, TWidget, TCallback> : MacObject<TControl, TWidget, TCallback>, Control.IHandler, IMacViewHandler
where TControl : NSObject
where TWidget : Control
where TCallback : Control.ICallback
Expand All @@ -545,13 +566,13 @@ public abstract class MacView<TControl, TWidget, TCallback> : MacObject<TControl

public abstract NSView ContainerControl { get; }

public virtual NSView ContentControl { get { return ContainerControl; } }
public virtual NSView ContentControl => ContainerControl;

public virtual NSView DragControl => ContainerControl;

public virtual NSView EventControl { get { return ContainerControl; } }
public virtual NSView EventControl => ContainerControl;

public virtual NSView FocusControl { get { return EventControl; } }
public virtual NSView FocusControl => EventControl;

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

Expand Down Expand Up @@ -800,7 +821,10 @@ public override void AttachEvent(string id)
// TODO
break;
case Eto.Forms.Control.TextInputEvent:
AddMethod(MacView.selInsertText, MacView.TriggerTextInput_Delegate, "v@:@");
if (EnsureTextInputImplemented())
{
HandleEvent(Eto.Forms.Control.KeyDownEvent);
}
break;

case Eto.Forms.Control.DragDropEvent:
Expand Down Expand Up @@ -1456,6 +1480,18 @@ public virtual MouseEventArgs TriggerMouseUp(NSObject obj, IntPtr sel, NSEvent t
}
return args;
}

bool IMacViewHandler.TextInputCancelled
{
get => Widget.Properties.Get<bool>(MacView.TextInputCancelled_Key);
set => Widget.Properties.Set(MacView.TextInputCancelled_Key, value);
}

public bool TextInputImplemented
{
get => Widget.Properties.Get<bool>(MacView.TextInputImplemented_Key);
private set => Widget.Properties.Set(MacView.TextInputImplemented_Key, value);
}
}
}

Loading