diff --git a/Pinta.Core/Classes/DocumentWorkspace.cs b/Pinta.Core/Classes/DocumentWorkspace.cs index 54873453ff..7b809352f8 100644 --- a/Pinta.Core/Classes/DocumentWorkspace.cs +++ b/Pinta.Core/Classes/DocumentWorkspace.cs @@ -52,6 +52,7 @@ internal DocumentWorkspace (Document document) #region Public Properties public Gtk.DrawingArea Canvas { get; set; } = null!; // NRT - This is set soon after creation + public Gtk.Widget CanvasWindow { get; set; } = null!; // NRT - This is set soon after creation /// /// Returns whether the zoomed image fits in the window without requiring scrolling. @@ -177,6 +178,19 @@ public void InvalidateWindowRect (RectangleI windowRect) OnCanvasInvalidated (new CanvasInvalidatedEventArgs (windowRect)); } + /// + /// Grabs focus to the canvas widget. This can be used to avoid leaving focus in + /// toolbar widgets, for example. + /// + public void GrabFocusToCanvas () + { + bool gained_focus = CanvasWindow.GrabFocus (); + // Log a warning if something went wrong, e.g. there is a non-focusable widget + // in the hierarchy. + if (!gained_focus) + Console.Error.WriteLine ("Failed to gain focus on the canvas widget!"); + } + /// /// Determines whether the rectangle lies (at least partially) outside the canvas area. /// diff --git a/Pinta.Core/Extensions/Gtk/GtkExtensions.Widget.cs b/Pinta.Core/Extensions/Gtk/GtkExtensions.Widget.cs index cacb0e7cfa..b8fbdfe19c 100644 --- a/Pinta.Core/Extensions/Gtk/GtkExtensions.Widget.cs +++ b/Pinta.Core/Extensions/Gtk/GtkExtensions.Widget.cs @@ -120,7 +120,7 @@ public static Gtk.SpinButton CreateToolBarSpinButton ( // tools can handle subsequent key events. spin.OnValueChanged += (o, e) => { if (PintaCore.Workspace.HasOpenDocuments) - PintaCore.Workspace.ActiveWorkspace.Canvas.GrabFocus (); + PintaCore.Workspace.ActiveWorkspace.GrabFocusToCanvas (); }; return spin; } diff --git a/Pinta.Gui.Widgets/Widgets/Canvas/CanvasWindow.cs b/Pinta.Gui.Widgets/Widgets/Canvas/CanvasWindow.cs index cdd8ce2b49..fc30eccf7c 100644 --- a/Pinta.Gui.Widgets/Widgets/Canvas/CanvasWindow.cs +++ b/Pinta.Gui.Widgets/Widgets/Canvas/CanvasWindow.cs @@ -79,9 +79,9 @@ public CanvasWindow ( scroll_controller.OnDecelerate += (_, _) => gesture_zoom.IsActive (); // Cancel scroll deceleration when zooming vp.AddController (scroll_controller); - // The mouse handler in PintaCanvas grabs focus away from toolbar widgets. + // The mouse handler in PintaCanvas grabs focus away from toolbar widgets, along + // with DocumentWorkpace.GrabFocusToCanvas() Focusable = true; - Canvas = new PintaCanvas (this, document, canvasGrid) { Name = "canvas" }; // Rulers diff --git a/Pinta.Tools/Tools/TextTool.cs b/Pinta.Tools/Tools/TextTool.cs index 18a953e812..9f7b95be9f 100644 --- a/Pinta.Tools/Tools/TextTool.cs +++ b/Pinta.Tools/Tools/TextTool.cs @@ -334,7 +334,7 @@ protected override void OnSaveSettings (ISettingsService settings) private void HandleFontChanged (object? sender, EventArgs e) { if (workspace.HasOpenDocuments) - workspace.ActiveDocument.Workspace.Canvas.GrabFocus (); + workspace.ActiveDocument.Workspace.GrabFocusToCanvas (); UpdateFont (); } diff --git a/Pinta/MainWindow.cs b/Pinta/MainWindow.cs index a8ddcfe5b3..785e10b437 100644 --- a/Pinta/MainWindow.cs +++ b/Pinta/MainWindow.cs @@ -117,7 +117,7 @@ public void Activate () private void Workspace_DocumentClosed (object? sender, DocumentEventArgs e) { - var tab = FindTabWithCanvas ((PintaCanvas) e.Document.Workspace.Canvas); + var tab = FindTabWithCanvas ((CanvasWindow) e.Document.Workspace.CanvasWindow); if (tab != null) canvas_pad.Notebook.RemoveTab (tab); @@ -164,6 +164,7 @@ private void Workspace_DocumentCreated (object? sender, DocumentEventArgs e) RulersVisible = PintaCore.Actions.View.Rulers.Value, RulerMetric = GetCurrentRulerMetric () }; + doc.Workspace.CanvasWindow = canvas; doc.Workspace.Canvas = canvas.Canvas; DocumentViewContent my_content = new (doc, canvas); @@ -223,9 +224,9 @@ private bool HandleGlobalKeyPress ( // first shot at handling the event if // the mouse pointer is on the canvas if (PintaCore.Workspace.HasOpenDocuments) { - var canvas_window = ((PintaCanvas) PintaCore.Workspace.ActiveWorkspace.Canvas).CanvasWindow; + var canvas_window = (CanvasWindow) PintaCore.Workspace.ActiveWorkspace.CanvasWindow; - if ((canvas_window.Canvas.HasFocus || canvas_window.IsMouseOnCanvas) && + if ((canvas_window.HasFocus || canvas_window.IsMouseOnCanvas) && canvas_window.Canvas.DoKeyPressEvent (controller, args)) { return true; } @@ -249,9 +250,9 @@ private void HandleGlobalKeyRelease ( // Give the Canvas (and by extension the tools) // first shot at handling the event if // the mouse pointer is on the canvas - var canvas_window = ((PintaCanvas) PintaCore.Workspace.ActiveWorkspace.Canvas).CanvasWindow; + var canvas_window = (CanvasWindow) PintaCore.Workspace.ActiveWorkspace.CanvasWindow; - if (canvas_window.Canvas.HasFocus || canvas_window.IsMouseOnCanvas) + if (canvas_window.HasFocus || canvas_window.IsMouseOnCanvas) canvas_window.Canvas.DoKeyReleaseEvent (controller, args); } @@ -575,10 +576,10 @@ private void ZoomToWindow_Activated (object sender, EventArgs e) int image_x = PintaCore.Workspace.ImageSize.Width; int image_y = PintaCore.Workspace.ImageSize.Height; - var canvas_window = PintaCore.Workspace.ActiveWorkspace.Canvas.Parent!; + var canvas_viewport = PintaCore.Workspace.ActiveWorkspace.Canvas.Parent!; - int window_x = canvas_window.GetAllocatedWidth (); - int window_y = canvas_window.GetAllocatedHeight (); + int window_x = canvas_viewport.GetAllocatedWidth (); + int window_y = canvas_viewport.GetAllocatedHeight (); double ratio = (image_x / (double) window_x >= image_y / (double) window_y) @@ -608,16 +609,16 @@ private void ActiveDocumentChanged (object? sender, EventArgs e) PintaCore.Actions.View.ResumeZoomUpdate (); var doc = PintaCore.Workspace.ActiveDocument; - var tab = FindTabWithCanvas ((PintaCanvas) doc.Workspace.Canvas); + var tab = FindTabWithCanvas ((CanvasWindow) doc.Workspace.CanvasWindow); if (tab != null) canvas_pad.Notebook.ActiveItem = tab; - doc.Workspace.Canvas.GrabFocus (); + doc.Workspace.GrabFocusToCanvas (); } - private IDockNotebookItem? FindTabWithCanvas (PintaCanvas canvas) => + private IDockNotebookItem? FindTabWithCanvas (CanvasWindow canvas_window) => canvas_pad.Notebook.Items - .Where (i => ((CanvasWindow) i.Widget).Canvas == canvas) + .Where (i => ((CanvasWindow) i.Widget) == canvas_window) .FirstOrDefault (); }