Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authoriain holmes <iain@xamarin.com>2019-07-10 18:40:51 +0300
committermonojenkins <jo.shields+jenkins@xamarin.com>2019-07-17 10:33:33 +0300
commit1b66b1df26ac0705356cbed38415a9d1de45e09b (patch)
tree5e4cb67ce32ab0d7262e3963b134dcb1542e4adb /main
parente2be0e1c3811151a114357e9c5a070b766e0bbcf (diff)
[Mac] Fix keyboard input in Global Search when in fullscreen
In fullscreen Cocoa stops delivering performKeyEquivalent messages to the SearchBar which breaks handling of cursor keys and similar. Instead of using it, use our own delegate to catch control:textView:doCommandBySelector: and create a command from the selector. Fixes VSTS #937857
Diffstat (limited to 'main')
-rw-r--r--main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs7
-rw-r--r--main/src/addins/MacPlatform/MainToolbar/SearchBar.cs71
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs12
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/IMainToolbarView.cs11
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs76
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs26
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs30
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs7
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)