From 9afdd3ad04bad7813f5690b848f63ccb316f1137 Mon Sep 17 00:00:00 2001 From: Gabriele Barbero Date: Thu, 5 Jun 2025 21:01:23 +0200 Subject: [PATCH] tools: allow on-canvas text editor to move This commit implements the ability to freely move the on-canvas text editor across the screen by introducing a drag-and-drop mechanism. --- app/display/gimpdisplayshell.c | 5 ++ app/tools/gimptexttool-editor.c | 117 ++++++++++++++++++++++++++++++++ app/tools/gimptexttool.h | 6 ++ app/widgets/gimpoverlayframe.c | 2 +- app/widgets/gimpoverlayframe.h | 4 +- 5 files changed, 131 insertions(+), 3 deletions(-) diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 198c31d1b1..bdd652514b 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -1365,6 +1365,11 @@ gimp_display_shell_transform_overlay (GimpDisplayShell *shell, *x -= requisition.width + overlay->spacing_x; *y -= requisition.height / 2; break; + + default: + *x -= overlay->spacing_x; + *y -= overlay->spacing_y; + break; } } diff --git a/app/tools/gimptexttool-editor.c b/app/tools/gimptexttool-editor.c index c8ac4d5ba5..dc5716b2f1 100644 --- a/app/tools/gimptexttool-editor.c +++ b/app/tools/gimptexttool-editor.c @@ -128,6 +128,20 @@ static void gimp_text_tool_fix_position (GimpTextTool *text_tool, static void gimp_text_tool_convert_gdkkeyevent (GimpTextTool *text_tool, GdkEventKey *kevent); +static gboolean gimp_text_tool_style_overlay_button_press + (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); +static gboolean gimp_text_tool_style_overlay_button_release + (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); +static gboolean gimp_text_tool_style_overlay_button_motion + (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data); + +#define DEFAULT_DRAG_OFFSET 25 /* public functions */ @@ -214,6 +228,23 @@ gimp_text_tool_editor_start (GimpTextTool *text_tool) gimp_overlay_box_set_child_opacity (GIMP_OVERLAY_BOX (shell->canvas), text_tool->style_overlay, 0.85); + gtk_widget_add_events (text_tool->style_overlay, + (GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_BUTTON_MOTION_MASK)); + + g_signal_connect_object (text_tool->style_overlay, "button-press-event", + G_CALLBACK (gimp_text_tool_style_overlay_button_press), + text_tool, 0); + g_signal_connect_object (text_tool->style_overlay, "button-release-event", + G_CALLBACK (gimp_text_tool_style_overlay_button_release), + text_tool, 0); + g_signal_connect_object (text_tool->style_overlay, "motion-notify-event", + G_CALLBACK (gimp_text_tool_style_overlay_button_motion), + text_tool, 0); + + text_tool->overlay_dragging = FALSE; + if (text_tool->image) gimp_image_get_resolution (text_tool->image, &xres, &yres); @@ -1893,3 +1924,89 @@ gimp_text_tool_convert_gdkkeyevent (GimpTextTool *text_tool, break; } } + +static gboolean +gimp_text_tool_style_overlay_button_press (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + GimpTextTool *text_tool = GIMP_TEXT_TOOL (user_data); + GtkWidget *event_widget = gtk_get_event_widget ((GdkEvent*) event); + + if (event_widget != GTK_WIDGET (text_tool->style_overlay) && + gtk_widget_is_ancestor (event_widget, GTK_WIDGET (text_tool->style_editor))) + { + return FALSE; + } + + if (gtk_widget_get_window (GTK_WIDGET (text_tool->style_overlay))) + { + GdkCursor *cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (text_tool->style_overlay)), + GDK_FLEUR); + if (cursor) + { + gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (text_tool->style_overlay)), + cursor); + g_object_unref (cursor); + } + } + + text_tool->overlay_dragging = TRUE; + text_tool->drag_offset_x = event->x; + text_tool->drag_offset_y = event->y; + + return TRUE; +} + +static gboolean +gimp_text_tool_style_overlay_button_release (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + GimpTextTool *text_tool = GIMP_TEXT_TOOL (user_data); + GtkWidget *event_widget = gtk_get_event_widget ((GdkEvent*) event); + + if (event_widget != GTK_WIDGET (text_tool->style_overlay) && + gtk_widget_is_ancestor (event_widget, GTK_WIDGET (text_tool->style_editor))) + { + return FALSE; + } + + text_tool->overlay_dragging = FALSE; + + if (gtk_widget_get_window (GTK_WIDGET (text_tool->style_overlay))) + gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (text_tool->style_overlay)), NULL); + + return TRUE; +} + +static gboolean +gimp_text_tool_style_overlay_button_motion (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data) +{ + GimpTextTool *text_tool = GIMP_TEXT_TOOL (user_data); + + if (text_tool->overlay_dragging) + { + GimpTool *tool = GIMP_TOOL (text_tool); + GimpDisplayShell *shell = gimp_display_get_shell (tool->display); + gdouble x, y; + + gdk_window_get_device_position_double (gtk_widget_get_window (GTK_WIDGET (shell)), + event->device, + &x, &y, NULL); + + gimp_display_shell_untransform_xy_f (shell, + x, y, + &x, &y); + + gimp_display_shell_move_overlay (shell, + text_tool->style_overlay, + x, y, -1, + text_tool->drag_offset_x + DEFAULT_DRAG_OFFSET, + text_tool->drag_offset_y + DEFAULT_DRAG_OFFSET); + } + + return TRUE; +} diff --git a/app/tools/gimptexttool.h b/app/tools/gimptexttool.h index a46f7fb9d1..6d226ff7bc 100644 --- a/app/tools/gimptexttool.h +++ b/app/tools/gimptexttool.h @@ -71,6 +71,12 @@ struct _GimpTextTool GtkWidget *style_overlay; GtkWidget *style_editor; + /* style overlay dragging: */ + + gboolean overlay_dragging; + gdouble drag_offset_x; + gdouble drag_offset_y; + gboolean selecting; GtkTextIter select_start_iter; gboolean select_words; diff --git a/app/widgets/gimpoverlayframe.c b/app/widgets/gimpoverlayframe.c index 0f400d8650..0719f41b37 100644 --- a/app/widgets/gimpoverlayframe.c +++ b/app/widgets/gimpoverlayframe.c @@ -36,7 +36,7 @@ static gboolean gimp_overlay_frame_draw (GtkWidget *widget, cairo_t *cr); -G_DEFINE_TYPE (GimpOverlayFrame, gimp_overlay_frame, GTK_TYPE_BIN) +G_DEFINE_TYPE (GimpOverlayFrame, gimp_overlay_frame, GTK_TYPE_EVENT_BOX) #define parent_class gimp_overlay_frame_parent_class diff --git a/app/widgets/gimpoverlayframe.h b/app/widgets/gimpoverlayframe.h index 4bbf0f616e..0fe773da84 100644 --- a/app/widgets/gimpoverlayframe.h +++ b/app/widgets/gimpoverlayframe.h @@ -35,12 +35,12 @@ typedef struct _GimpOverlayFrameClass GimpOverlayFrameClass; struct _GimpOverlayFrame { - GtkBin parent_instance; + GtkEventBox parent_instance; }; struct _GimpOverlayFrameClass { - GtkBinClass parent_class; + GtkEventBoxClass parent_class; };