diff --git a/app/display/Makefile.am b/app/display/Makefile.am index 5f30089122..42546cbd1b 100644 --- a/app/display/Makefile.am +++ b/app/display/Makefile.am @@ -89,6 +89,8 @@ libappdisplay_a_sources = \ gimpdisplayshell-draw.h \ gimpdisplayshell-expose.c \ gimpdisplayshell-expose.h \ + gimpdisplayshell-grab.c \ + gimpdisplayshell-grab.h \ gimpdisplayshell-handlers.c \ gimpdisplayshell-handlers.h \ gimpdisplayshell-filter.c \ diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c index 67bab2f949..5a385f825d 100644 --- a/app/display/gimpdisplayshell-callbacks.c +++ b/app/display/gimpdisplayshell-callbacks.c @@ -69,6 +69,7 @@ #include "gimpdisplayshell-coords.h" #include "gimpdisplayshell-cursor.h" #include "gimpdisplayshell-draw.h" +#include "gimpdisplayshell-grab.h" #include "gimpdisplayshell-layer-select.h" #include "gimpdisplayshell-preview.h" #include "gimpdisplayshell-scale.h" @@ -496,14 +497,16 @@ gimp_display_shell_stop_scrolling (GimpDisplayShell *shell) static void gimp_display_shell_space_pressed (GimpDisplayShell *shell, - GdkModifierType state, - guint32 time) + GdkEvent *event) { Gimp *gimp = gimp_display_get_gimp (shell->display); if (shell->space_pressed) return; + if (! gimp_display_shell_keyboard_grab (shell, event)) + return; + switch (shell->display->config->space_bar_action) { case GIMP_SPACE_BAR_ACTION_NONE: @@ -513,22 +516,26 @@ gimp_display_shell_space_pressed (GimpDisplayShell *shell, { GimpCoords coords; + if (! gimp_display_shell_pointer_grab (shell, event, + GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK)) + { + gimp_display_shell_keyboard_ungrab (shell, event); + return; + } + gimp_device_info_get_device_coords (gimp_devices_get_current (gimp), gtk_widget_get_window (shell->canvas), &coords); gimp_display_shell_start_scrolling (shell, coords.x, coords.y); - - gdk_pointer_grab (gtk_widget_get_window (shell->canvas), FALSE, - GDK_POINTER_MOTION_MASK | - GDK_POINTER_MOTION_HINT_MASK, - NULL, NULL, time); } break; case GIMP_SPACE_BAR_ACTION_MOVE: { - GimpTool *active_tool = tool_manager_get_active (gimp); + GimpTool *active_tool = tool_manager_get_active (gimp); + GdkModifierType state; if (! active_tool || GIMP_IS_MOVE_TOOL (active_tool)) return; @@ -539,21 +546,20 @@ gimp_display_shell_space_pressed (GimpDisplayShell *shell, gimp_context_set_tool (gimp_get_user_context (gimp), gimp_get_tool_info (gimp, "gimp-move-tool")); + gdk_event_get_state (event, &state); + tool_manager_focus_display_active (gimp, shell->display); tool_manager_modifier_state_active (gimp, state, shell->display); } break; } - gdk_keyboard_grab (gtk_widget_get_window (shell->canvas), FALSE, time); - shell->space_pressed = TRUE; } static void gimp_display_shell_space_released (GimpDisplayShell *shell, - GdkModifierType state, - guint32 time) + GdkEvent *event) { Gimp *gimp = gimp_display_get_gimp (shell->display); @@ -567,21 +573,27 @@ gimp_display_shell_space_released (GimpDisplayShell *shell, case GIMP_SPACE_BAR_ACTION_PAN: gimp_display_shell_stop_scrolling (shell); - gdk_display_pointer_ungrab (gtk_widget_get_display (shell->canvas), time); + gimp_display_shell_pointer_ungrab (shell, event); break; case GIMP_SPACE_BAR_ACTION_MOVE: - gimp_context_set_tool (gimp_get_user_context (gimp), - gimp_get_tool_info (gimp, - shell->space_shaded_tool)); - shell->space_shaded_tool = NULL; + { + GdkModifierType state; - tool_manager_focus_display_active (gimp, shell->display); - tool_manager_modifier_state_active (gimp, state, shell->display); + gimp_context_set_tool (gimp_get_user_context (gimp), + gimp_get_tool_info (gimp, + shell->space_shaded_tool)); + shell->space_shaded_tool = NULL; + + gdk_event_get_state (event, &state); + + tool_manager_focus_display_active (gimp, shell->display); + tool_manager_modifier_state_active (gimp, state, shell->display); + } break; } - gdk_display_keyboard_ungrab (gtk_widget_get_display (shell->canvas), time); + gimp_display_shell_keyboard_ungrab (shell, event); shell->space_pressed = FALSE; shell->space_release_pending = FALSE; @@ -946,11 +958,15 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas, } } - gdk_pointer_grab (gtk_widget_get_window (canvas), - FALSE, event_mask, NULL, NULL, time); + if (! gimp_display_shell_pointer_grab (shell, event, event_mask)) + return TRUE; if (! shell->space_pressed && ! shell->space_release_pending) - gdk_keyboard_grab (gtk_widget_get_window (canvas), FALSE, time); + if (! gimp_display_shell_keyboard_grab (shell, event)) + { + gimp_display_shell_pointer_ungrab (shell, event); + return TRUE; + } if (active_tool && (! gimp_image_is_empty (image) || @@ -1128,9 +1144,9 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas, state &= ~GDK_BUTTON1_MASK; if (! shell->space_pressed && ! shell->space_release_pending) - gdk_display_keyboard_ungrab (gdk_display, time); + gimp_display_shell_keyboard_ungrab (shell, event); - gdk_display_pointer_ungrab (gdk_display, time); + gimp_display_shell_pointer_ungrab (shell, event); gtk_grab_add (canvas); @@ -1159,7 +1175,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas, gtk_grab_remove (canvas); if (shell->space_release_pending) - gimp_display_shell_space_released (shell, state, time); + gimp_display_shell_space_released (shell, event); break; case 2: @@ -1590,7 +1606,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas, case GDK_space: case GDK_KP_Space: - gimp_display_shell_space_pressed (shell, state, time); + gimp_display_shell_space_pressed (shell, event); return_val = TRUE; break; @@ -1694,7 +1710,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas, { case GDK_space: case GDK_KP_Space: - gimp_display_shell_space_released (shell, state, time); + gimp_display_shell_space_released (shell, event); return_val = TRUE; break; @@ -1845,8 +1861,6 @@ gimp_display_shell_ruler_button_press (GtkWidget *widget, if (active_tool) { - GdkGrabStatus status; - if (! gtk_widget_has_focus (shell->canvas)) { gimp_display_shell_update_focus (shell, NULL, event->state); @@ -1860,18 +1874,14 @@ gimp_display_shell_ruler_button_press (GtkWidget *widget, gdk_event_get_time ((GdkEvent *) event)); } - status = gdk_pointer_grab (gtk_widget_get_window (shell->canvas), FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, event->time); - - if (status == GDK_GRAB_SUCCESS) + if (gimp_display_shell_pointer_grab (shell, + (GdkEvent *) event, + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK)) { - status = gdk_keyboard_grab (gtk_widget_get_window (shell->canvas), - FALSE, event->time); - - if (status == GDK_GRAB_SUCCESS) + if (gimp_display_shell_keyboard_grab (shell, + (GdkEvent *) event)) { if (sample_point) gimp_color_tool_start_sample_point (active_tool, display); @@ -1884,18 +1894,10 @@ gimp_display_shell_ruler_button_press (GtkWidget *widget, } else { - g_printerr ("%s: gdk_keyboard_grab failed with status %d\n", - G_STRFUNC, status); - - gdk_display_pointer_ungrab (gtk_widget_get_display (shell->canvas), - event->time); + gimp_display_shell_pointer_ungrab (shell, + (GdkEvent *) event); } } - else - { - g_printerr ("%s: gdk_pointer_grab failed with status %d\n", - G_STRFUNC, status); - } } } diff --git a/app/display/gimpdisplayshell-grab.c b/app/display/gimpdisplayshell-grab.c new file mode 100644 index 0000000000..1320c0a075 --- /dev/null +++ b/app/display/gimpdisplayshell-grab.c @@ -0,0 +1,109 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpdisplayshell-grab.c + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include + +#include "display-types.h" + +#include "gimpdisplayshell.h" +#include "gimpdisplayshell-grab.h" + + +gboolean +gimp_display_shell_pointer_grab (GimpDisplayShell *shell, + GdkEvent *event, + GdkEventMask event_mask) +{ + GdkGrabStatus status; + + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + g_return_val_if_fail (shell->pointer_grabbed == FALSE, FALSE); + + status = gdk_pointer_grab (gtk_widget_get_window (shell->canvas), + FALSE, event_mask, NULL, NULL, + gdk_event_get_time (event)); + + if (status == GDK_GRAB_SUCCESS) + { + shell->pointer_grabbed = TRUE; + + return TRUE; + } + + g_printerr ("%s: gdk_pointer_grab failed with status %d\n", + G_STRFUNC, status); + + return FALSE; +} + +void +gimp_display_shell_pointer_ungrab (GimpDisplayShell *shell, + GdkEvent *event) +{ + g_return_if_fail (shell->pointer_grabbed == TRUE); + + gdk_display_pointer_ungrab (gtk_widget_get_display (shell->canvas), + gdk_event_get_time (event)); + + shell->pointer_grabbed = FALSE; +} + +gboolean +gimp_display_shell_keyboard_grab (GimpDisplayShell *shell, + GdkEvent *event) +{ + GdkGrabStatus status; + + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + g_return_val_if_fail (shell->keyboard_grabbed == FALSE, FALSE); + + status = gdk_keyboard_grab (gtk_widget_get_window (shell->canvas), + FALSE, + gdk_event_get_time (event)); + + if (status == GDK_GRAB_SUCCESS) + { + shell->keyboard_grabbed = TRUE; + + return TRUE; + } + + g_printerr ("%s: gdk_keyboard_grab failed with status %d\n", + G_STRFUNC, status); + + return FALSE; +} + +void +gimp_display_shell_keyboard_ungrab (GimpDisplayShell *shell, + GdkEvent *event) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + g_return_if_fail (event != NULL); + g_return_if_fail (shell->keyboard_grabbed == TRUE); + + gdk_display_keyboard_ungrab (gtk_widget_get_display (shell->canvas), + gdk_event_get_time (event)); + + shell->keyboard_grabbed = FALSE; +} diff --git a/app/display/gimpdisplayshell-grab.h b/app/display/gimpdisplayshell-grab.h new file mode 100644 index 0000000000..b01144566b --- /dev/null +++ b/app/display/gimpdisplayshell-grab.h @@ -0,0 +1,36 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpdisplayshell-grab.h + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_DISPLAY_SHELL_GRAB_H__ +#define __GIMP_DISPLAY_SHELL_GRAB_H__ + + +gboolean gimp_display_shell_pointer_grab (GimpDisplayShell *shell, + GdkEvent *event, + GdkEventMask event_mask); +void gimp_display_shell_pointer_ungrab (GimpDisplayShell *shell, + GdkEvent *event); + +gboolean gimp_display_shell_keyboard_grab (GimpDisplayShell *shell, + GdkEvent *event); +void gimp_display_shell_keyboard_ungrab (GimpDisplayShell *shell, + GdkEvent *event); + + +#endif /* __GIMP_DISPLAY_SHELL_GRAB_H__ */ diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h index bf97b002fb..1f890872eb 100644 --- a/app/display/gimpdisplayshell.h +++ b/app/display/gimpdisplayshell.h @@ -184,6 +184,9 @@ struct _GimpDisplayShell gboolean size_allocate_from_configure_event; /* the state of gimp_display_shell_tool_events() */ + gboolean pointer_grabbed; + gboolean keyboard_grabbed; + gboolean space_pressed; gboolean space_release_pending; const gchar *space_shaded_tool;