diff options
author | Lluis Sanchez <lluis@xamarin.com> | 2019-07-31 18:12:49 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-31 18:12:49 +0300 |
commit | 8bcdedfdc26a11c9976b700f6ee9581f6f57d459 (patch) | |
tree | dff897f37586560c223469376fa23a72eb088a9a /main | |
parent | c5a1ba1ee8b0f544e2564306cbf9d518110fb32c (diff) | |
parent | 1b66b1df26ac0705356cbed38415a9d1de45e09b (diff) |
Merge pull request #8116 from mono/backport-pr-8111-to-release-8.2
[release-8.2] [Mac] Fix keyboard input in Global Search when in fullscreen
Diffstat (limited to 'main')
10 files changed, 205 insertions, 40 deletions
diff --git a/main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs b/main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs index dbae2c656b..c5ac94797d 100644 --- a/main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs +++ b/main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs @@ -70,11 +70,11 @@ namespace MonoDevelop.MacIntegration.MainToolbar void AttachToolbarEvents (SearchBar bar) { - bar.Changed += (o, e) => { - SearchEntryChanged?.Invoke (o, e); + bar.PerformCommand += (o, e) => { + PerformCommand?.Invoke (o, e); }; bar.KeyPressed += (o, e) => { - SearchEntryKeyPressed?.Invoke (o, e); + SearchEntryChanged?.Invoke (o, e); }; bar.LostFocus += (o, e) => { SearchEntryLostFocus?.Invoke (o, e); @@ -209,6 +209,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar public event EventHandler RunButtonClicked; public event EventHandler SearchEntryChanged; public event EventHandler<Xwt.KeyEventArgs> SearchEntryKeyPressed; + public event EventHandler<SearchEntryCommandArgs> PerformCommand; public event EventHandler SearchEntryLostFocus; #pragma warning disable 0067 diff --git a/main/src/addins/MacPlatform/MainToolbar/SearchBar.cs b/main/src/addins/MacPlatform/MainToolbar/SearchBar.cs index 72b492c48f..3acaf0a486 100644 --- a/main/src/addins/MacPlatform/MainToolbar/SearchBar.cs +++ b/main/src/addins/MacPlatform/MainToolbar/SearchBar.cs @@ -32,11 +32,12 @@ using MonoDevelop.Core; using MonoDevelop.Ide; using Xwt.Mac; +using MonoDevelop.Components.MainToolbar; namespace MonoDevelop.MacIntegration.MainToolbar { [Register] - class SearchBar : NSSearchField + class SearchBar : NSSearchField, INSSearchFieldDelegate { internal Widget gtkWidget; internal event EventHandler<Xwt.KeyEventArgs> KeyPressed; @@ -183,6 +184,8 @@ namespace MonoDevelop.MacIntegration.MainToolbar { Cell = new DarkThemeSearchFieldCell (); + Delegate = this; + var nsa = (INSAccessibility)this; AccessibilitySubrole = NSAccessibilitySubroles.SearchFieldSubrole; @@ -198,6 +201,19 @@ namespace MonoDevelop.MacIntegration.MainToolbar UpdateLayout (); } + // Protection against the delegate being replaced by an external caller. + // The delegate needs to be set to make key handling work correctly + public override NSObject WeakDelegate { + get => base.WeakDelegate; + set { + if (base.WeakDelegate != null) { + throw new ApplicationException ("Cannot change the delegate of SearchBar"); + } + + base.WeakDelegate = value; + } + } + public override bool AccessibilityPerformShowMenu () { Cell.SearchButtonCell.PerformClick (this); @@ -259,20 +275,59 @@ namespace MonoDevelop.MacIntegration.MainToolbar return false; } - bool SendKeyPressed (Xwt.KeyEventArgs kargs) + void SendKeyPressed (Xwt.KeyEventArgs kargs) { if (KeyPressed != null) KeyPressed (this, kargs); + } + + internal event EventHandler<SearchEntryCommandArgs> PerformCommand; + + [Export ("control:textView:doCommandBySelector:")] + bool CommandBySelector (NSControl control, NSTextField field, ObjCRuntime.Selector sel) + { + SearchPopupCommand command; + + switch (sel.Name) { + case "moveDown:": // down arrow + command = SearchPopupCommand.NextItem; + break; + + case "moveUp:": // up arrow + command = SearchPopupCommand.PreviousItem; + break; + + case "scrollPageDown:": // page down + case "moveToEndOfDocument:": // cmd+down arrow + command = SearchPopupCommand.NextCategory; + break; + + case "scrollPageUp:": // page up + case "moveToBeginningOfDocument:": // cmd+up arrow + command = SearchPopupCommand.PreviousCategory; + break; + + case "insertNewline:": // Return + command = SearchPopupCommand.Activate; + break; + + case "cancelOperation:": // Escape + command = SearchPopupCommand.Cancel; + break; + + default: + return false; + } - return kargs.Handled; + var args = new SearchEntryCommandArgs (command); + PerformCommand?.Invoke (this, args); + return args.Handled; } - public override bool PerformKeyEquivalent (NSEvent theEvent) + [Export ("controlTextDidChange:")] + void ControlTextDidChange (NSNotification note) { - var popupHandled = SendKeyPressed (theEvent.ToXwtKeyEventArgs ()); - if (popupHandled) - return true; - return base.PerformKeyEquivalent (theEvent);; + SendKeyPressed (null); } bool ignoreEndEditing = false; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs index f6fbea24c3..326e5a8299 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs @@ -92,7 +92,7 @@ namespace MonoDevelop.Components.Commands internal static readonly object CommandRouteTerminator = new object (); internal bool handlerFoundInMulticast; - Gtk.Widget lastActiveWidget; + Gtk.Widget activeWidget; #if MAC Foundation.NSObject keyMonitor; @@ -108,6 +108,9 @@ namespace MonoDevelop.Components.Commands } } + WeakReference lastCommandTarget; + internal object LastCommandTarget => lastCommandTarget?.Target; + public CommandManager (): this (null) { } @@ -2277,10 +2280,11 @@ namespace MonoDevelop.Components.Commands widget = GetFocusedChild (widget); } - if (widget != lastActiveWidget) { + if (widget != activeWidget) { if (ActiveWidgetChanged != null) - ActiveWidgetChanged (this, new ActiveWidgetEventArgs () { OldActiveWidget = lastActiveWidget, NewActiveWidget = widget }); - lastActiveWidget = widget; + ActiveWidgetChanged (this, new ActiveWidgetEventArgs () { OldActiveWidget = activeWidget, NewActiveWidget = widget }); + lastCommandTarget = new WeakReference (activeWidget); + activeWidget = widget; } return widget; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs index cd690cdb02..9084175639 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs @@ -77,7 +77,8 @@ namespace MonoDevelop.Components.MainToolbar try { if (pattern.HasLineNumber) return; - CommandTargetRoute route = new CommandTargetRoute (MainToolbar.LastCommandTarget); + var route = new CommandTargetRoute (IdeApp.CommandService.LastCommandTarget); + var matcher = StringMatcher.GetMatcher (pattern.Pattern, false); foreach (var cmdTuple in allCommands) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/IMainToolbarView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/IMainToolbarView.cs index dd6fc74ace..5722d31d1b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/IMainToolbarView.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/IMainToolbarView.cs @@ -39,6 +39,16 @@ namespace MonoDevelop.Components.MainToolbar Stop } + public enum SearchPopupCommand + { + PreviousItem, + NextItem, + PreviousCategory, + NextCategory, + Cancel, + Activate + }; + /// <summary> /// Event arguments which specify if the event succeeded in at least one handler. /// </summary> @@ -197,6 +207,7 @@ namespace MonoDevelop.Components.MainToolbar /// Occurs when a key is pressed in the search entry. /// </summary> event EventHandler<Xwt.KeyEventArgs> SearchEntryKeyPressed; + event EventHandler<SearchEntryCommandArgs> PerformCommand; /// <summary> /// Occurs when the search entry is resized. diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs index ea36fc1404..0fc393e2fa 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs @@ -23,6 +23,8 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#if !MAC + using System; using Gtk; using MonoDevelop.Components.Commands; @@ -43,6 +45,7 @@ using System.Threading; using MonoDevelop.Ide.Editor; using System.Text; using MonoDevelop.Components.AtkCocoaHelper; +using System.Diagnostics; namespace MonoDevelop.Components.MainToolbar { @@ -90,10 +93,6 @@ namespace MonoDevelop.Components.MainToolbar } } - internal static object LastCommandTarget { - get { return lastCommandTarget != null ? lastCommandTarget.Target : null; } - } - static bool RuntimeIsSeparator (TreeModel model, TreeIter iter) { var runtime = (IRuntimeModel)model.GetValue (iter, 0); @@ -271,10 +270,6 @@ namespace MonoDevelop.Components.MainToolbar button.Clicked += HandleStartButtonClicked; - IdeApp.CommandService.ActiveWidgetChanged += (sender, e) => { - lastCommandTarget = new WeakReference (e.OldActiveWidget); - }; - this.ShowAll (); this.statusArea.statusIconBox.HideAll (); } @@ -323,21 +318,54 @@ namespace MonoDevelop.Components.MainToolbar void HandleSearchEntryKeyPressed (object sender, KeyPressEventArgs e) { - if (SearchEntryKeyPressed != null) { - // TODO: Refactor this in Xwt as an extension method. - var k = (Xwt.Key)e.Event.KeyValue; - var m = Xwt.ModifierKeys.None; - if ((e.Event.State & Gdk.ModifierType.ShiftMask) != 0) - m |= Xwt.ModifierKeys.Shift; - if ((e.Event.State & Gdk.ModifierType.ControlMask) != 0) - m |= Xwt.ModifierKeys.Control; - if ((e.Event.State & Gdk.ModifierType.Mod1Mask) != 0) - m |= Xwt.ModifierKeys.Alt; - // TODO: Backport this one. - if ((e.Event.State & Gdk.ModifierType.Mod2Mask) != 0) - m |= Xwt.ModifierKeys.Command; - var kargs = new Xwt.KeyEventArgs (k, m, false, (long)e.Event.Time); - SearchEntryKeyPressed (sender, kargs); + if (PerformCommand != null) { + bool cmdPressed = (e.Event.State & Gdk.ModifierType.Mod2Mask) != 0; + SearchPopupCommand command; + + switch ((Gdk.Key)e.Event.KeyValue) { + case Gdk.Key.Down: + case Gdk.Key.downarrow: + if (cmdPressed) { + goto case Gdk.Key.Page_Down; + } + + command = SearchPopupCommand.NextItem; + break; + + case Gdk.Key.Up: + case Gdk.Key.uparrow: + if (cmdPressed) { + goto case Gdk.Key.Page_Up; + } + + command = SearchPopupCommand.PreviousItem; + break; + + case Gdk.Key.KP_Page_Down: + case Gdk.Key.Page_Down: + command = SearchPopupCommand.NextCategory; + break; + + case Gdk.Key.KP_Page_Up: + case Gdk.Key.Page_Up: + command = SearchPopupCommand.PreviousCategory; + break; + + case Gdk.Key.Escape: + command = SearchPopupCommand.Cancel; + break; + + case Gdk.Key.Return: + case Gdk.Key.KP_Enter: + command = SearchPopupCommand.Activate; + break; + + default: + return; + } + + var kargs = new SearchEntryCommandArgs (command); + PerformCommand?.Invoke (sender, kargs); e.RetVal = kargs.Handled; } } @@ -582,6 +610,7 @@ namespace MonoDevelop.Components.MainToolbar public event EventHandler SearchEntryChanged; public event EventHandler SearchEntryActivated; public event EventHandler<Xwt.KeyEventArgs> SearchEntryKeyPressed; + public event EventHandler<SearchEntryCommandArgs> PerformCommand; public event EventHandler SearchEntryResized; public event EventHandler SearchEntryLostFocus; @@ -628,3 +657,4 @@ namespace MonoDevelop.Components.MainToolbar } } +#endif
\ No newline at end of file diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs index e371e00cb5..b497d148ff 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs @@ -77,6 +77,7 @@ namespace MonoDevelop.Components.MainToolbar ToolbarView.SearchEntryChanged += HandleSearchEntryChanged; ToolbarView.SearchEntryActivated += HandleSearchEntryActivated; ToolbarView.SearchEntryKeyPressed += HandleSearchEntryKeyPressed; + ToolbarView.PerformCommand += HandleSearchEntryCommand; ToolbarView.SearchEntryResized += (o, e) => PositionPopup (); ToolbarView.SearchEntryLostFocus += (o, e) => { ToolbarView.SearchText = ""; @@ -741,6 +742,21 @@ namespace MonoDevelop.Components.MainToolbar popup.OpenFile (); } + void HandleSearchEntryCommand (object sender, SearchEntryCommandArgs args) + { + if (args.Command == SearchPopupCommand.Cancel) { + DestroyPopup (); + var doc = IdeApp.Workbench.ActiveDocument; + if (doc != null) + doc.Select (); + return; + } + + if (popup != null) { + args.Handled = popup.ProcessCommand (args.Command); + } + } + void HandleSearchEntryKeyPressed (object sender, Xwt.KeyEventArgs e) { if (e.Key == Xwt.Key.Escape) {
@@ -1181,5 +1197,15 @@ namespace MonoDevelop.Components.MainToolbar public event EventHandler Activated; } } + + public class SearchEntryCommandArgs : HandledEventArgs + { + public SearchPopupCommand Command { get; private set; } + + public SearchEntryCommandArgs (SearchPopupCommand command) + { + Command = command; + } + } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs index f7a04db856..6a21e68944 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs @@ -81,6 +81,11 @@ namespace MonoDevelop.Components.MainToolbar Content.OpenFile (); } + internal bool ProcessCommand (SearchPopupCommand command) + { + return Content.ProcessCommand (command); + } + internal bool ProcessKey (Key key, ModifierKeys state) { return Content.ProcessKey (key, state); @@ -781,6 +786,31 @@ namespace MonoDevelop.Components.MainToolbar QueueDraw (); } + internal bool ProcessCommand (SearchPopupCommand command) + { + switch (command) { + case SearchPopupCommand.PreviousItem: + SelectItemUp (); + return true; + case SearchPopupCommand.NextItem: + SelectItemDown (); + return true; + case SearchPopupCommand.NextCategory: + SelectNextCategory (); + return true; + case SearchPopupCommand.PreviousCategory: + SelectPrevCategory (); + return true; + case SearchPopupCommand.Activate: + OnItemActivated (EventArgs.Empty); + return true; + + default: + break; + } + return false; + } + internal bool ProcessKey (Xwt.Key key, Xwt.ModifierKeys state) { switch (key) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs index 5ef61ef0ed..6115550e5a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs @@ -269,7 +269,7 @@ namespace MonoDevelop.Components.MainToolbar return false; } Runtime.RunInMainThread (delegate { - ci = IdeApp.CommandService.GetCommandInfo (command.Id, new CommandTargetRoute (MainToolbar.LastCommandTarget)); + ci = IdeApp.CommandService.GetCommandInfo (command.Id, new CommandTargetRoute (IdeApp.CommandService.LastCommandTarget)); }).Wait (); } return ci.Enabled && ci.Visible; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs index 994699d316..676ba907bb 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs @@ -409,14 +409,21 @@ namespace MonoDevelop.Ide.Desktop internal virtual IMainToolbarView CreateMainToolbar (Gtk.Window window) { + // This is overridden by MacPlatform +#if MAC + return null; +#else return new MainToolbar (); +#endif } internal virtual void AttachMainToolbar (Gtk.VBox parent, IMainToolbarView toolbar) { +#if !MAC var toolbarBox = new Gtk.HBox (); parent.PackStart (toolbarBox, false, false, 0); toolbarBox.PackStart ((MainToolbar)toolbar, true, true, 0); +#endif } public virtual bool GetIsFullscreen (Window window) |