diff options
author | Matthias Clasen <mclasen@redhat.com> | 2005-06-25 07:10:40 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2005-06-25 07:10:40 +0000 |
commit | 9b356ea0d8ee1992ad9b3559aadad0c4e2b56f2c (patch) | |
tree | 2b22564953b69dff46505860a4918ac10c467e3b | |
parent | effe3785cf61084d9f7e9427cea0999bb4a32473 (diff) | |
download | gdk-pixbuf-9b356ea0d8ee1992ad9b3559aadad0c4e2b56f2c.tar.gz |
Add a GrabBroken event to GDK, and a grab-broken-event signal to
2005-06-25 Matthias Clasen <mclasen@redhat.com>
Add a GrabBroken event to GDK, and a grab-broken-event
signal to GtkWidget. (#107320, Simon Cooke, initial patch
by John Ehresman)
* gdk/gdkevents.h: Add a GDK_GRAB_BROKEN event type,
define a GdkEventGrabBroken event struct.
* gdk/win32/gdkevents-win32.c (gdk_event_translate):
Generate GrabBroken events in response to WM_KILLFOCUS.
* gdk/x11/gdkmain-x11.c: Generate GrabBroken events
when a grab is broken by the window becoming unviewable,
or by another grab from the same client.
* gtk/gtkwidget.h (GtkWidgetClass): Add grab_broken_event.
* gtk/gtkwidget.c (gtk_widget_event_internal): Translate
GrabBroken events into grab_broken_event signals.
* gtk/gtkmain.c (gtk_main_do_event): Propagate GrabBroken
events.
* gtk/gtkmenushell.c (gtk_menu_shell_grab_broken): Deactivate
the menu when the grab is broken.
* gtk/gtkcolorsel.c (gtk_color_selection_grab_broken): Stop
the color picker if the grab is broken.
* gtk/gtkpaned.c (gtk_paned_grab_broken): Stop the drag if
the grab is broken.
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 33 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 33 | ||||
-rw-r--r-- | docs/reference/ChangeLog | 4 | ||||
-rw-r--r-- | docs/reference/gdk/gdk-sections.txt | 1 | ||||
-rw-r--r-- | docs/reference/gdk/tmpl/event_structs.sgml | 16 | ||||
-rw-r--r-- | docs/reference/gdk/tmpl/events.sgml | 2 | ||||
-rw-r--r-- | gdk/gdkevents.h | 12 | ||||
-rw-r--r-- | gdk/win32/gdkevents-win32.c | 23 | ||||
-rw-r--r-- | gdk/x11/gdkmain-x11.c | 47 | ||||
-rw-r--r-- | gtk/gtkcolorsel.c | 40 | ||||
-rw-r--r-- | gtk/gtkmain.c | 1 | ||||
-rw-r--r-- | gtk/gtkmenushell.c | 24 | ||||
-rw-r--r-- | gtk/gtkpaned.c | 41 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 31 | ||||
-rw-r--r-- | gtk/gtkwidget.h | 5 |
16 files changed, 319 insertions, 27 deletions
@@ -1,5 +1,38 @@ 2005-06-25 Matthias Clasen <mclasen@redhat.com> + Add a GrabBroken event to GDK, and a grab-broken-event + signal to GtkWidget. (#107320, Simon Cooke, initial patch + by John Ehresman) + + * gdk/gdkevents.h: Add a GDK_GRAB_BROKEN event type, + define a GdkEventGrabBroken event struct. + + * gdk/win32/gdkevents-win32.c (gdk_event_translate): + Generate GrabBroken events in response to WM_KILLFOCUS. + + * gdk/x11/gdkmain-x11.c: Generate GrabBroken events + when a grab is broken by the window becoming unviewable, + or by another grab from the same client. + + * gtk/gtkwidget.h (GtkWidgetClass): Add grab_broken_event. + + * gtk/gtkwidget.c (gtk_widget_event_internal): Translate + GrabBroken events into grab_broken_event signals. + + * gtk/gtkmain.c (gtk_main_do_event): Propagate GrabBroken + events. + + * gtk/gtkmenushell.c (gtk_menu_shell_grab_broken): Deactivate + the menu when the grab is broken. + + * gtk/gtkcolorsel.c (gtk_color_selection_grab_broken): Stop + the color picker if the grab is broken. + + * gtk/gtkpaned.c (gtk_paned_grab_broken): Stop the drag if + the grab is broken. + +2005-06-25 Matthias Clasen <mclasen@redhat.com> + Add some new stock items. (#166480, Kristof Vansant) * gtk/stock-icons/stock_fullscreen_16.png: diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 28d90c1b0..c4bdfc1c2 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,5 +1,38 @@ 2005-06-25 Matthias Clasen <mclasen@redhat.com> + Add a GrabBroken event to GDK, and a grab-broken-event + signal to GtkWidget. (#107320, Simon Cooke, initial patch + by John Ehresman) + + * gdk/gdkevents.h: Add a GDK_GRAB_BROKEN event type, + define a GdkEventGrabBroken event struct. + + * gdk/win32/gdkevents-win32.c (gdk_event_translate): + Generate GrabBroken events in response to WM_KILLFOCUS. + + * gdk/x11/gdkmain-x11.c: Generate GrabBroken events + when a grab is broken by the window becoming unviewable, + or by another grab from the same client. + + * gtk/gtkwidget.h (GtkWidgetClass): Add grab_broken_event. + + * gtk/gtkwidget.c (gtk_widget_event_internal): Translate + GrabBroken events into grab_broken_event signals. + + * gtk/gtkmain.c (gtk_main_do_event): Propagate GrabBroken + events. + + * gtk/gtkmenushell.c (gtk_menu_shell_grab_broken): Deactivate + the menu when the grab is broken. + + * gtk/gtkcolorsel.c (gtk_color_selection_grab_broken): Stop + the color picker if the grab is broken. + + * gtk/gtkpaned.c (gtk_paned_grab_broken): Stop the drag if + the grab is broken. + +2005-06-25 Matthias Clasen <mclasen@redhat.com> + Add some new stock items. (#166480, Kristof Vansant) * gtk/stock-icons/stock_fullscreen_16.png: diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 28d90c1b0..c4bdfc1c2 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,5 +1,38 @@ 2005-06-25 Matthias Clasen <mclasen@redhat.com> + Add a GrabBroken event to GDK, and a grab-broken-event + signal to GtkWidget. (#107320, Simon Cooke, initial patch + by John Ehresman) + + * gdk/gdkevents.h: Add a GDK_GRAB_BROKEN event type, + define a GdkEventGrabBroken event struct. + + * gdk/win32/gdkevents-win32.c (gdk_event_translate): + Generate GrabBroken events in response to WM_KILLFOCUS. + + * gdk/x11/gdkmain-x11.c: Generate GrabBroken events + when a grab is broken by the window becoming unviewable, + or by another grab from the same client. + + * gtk/gtkwidget.h (GtkWidgetClass): Add grab_broken_event. + + * gtk/gtkwidget.c (gtk_widget_event_internal): Translate + GrabBroken events into grab_broken_event signals. + + * gtk/gtkmain.c (gtk_main_do_event): Propagate GrabBroken + events. + + * gtk/gtkmenushell.c (gtk_menu_shell_grab_broken): Deactivate + the menu when the grab is broken. + + * gtk/gtkcolorsel.c (gtk_color_selection_grab_broken): Stop + the color picker if the grab is broken. + + * gtk/gtkpaned.c (gtk_paned_grab_broken): Stop the drag if + the grab is broken. + +2005-06-25 Matthias Clasen <mclasen@redhat.com> + Add some new stock items. (#166480, Kristof Vansant) * gtk/stock-icons/stock_fullscreen_16.png: diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 5b27becfe..7fc72db2c 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,7 @@ +2005-06-25 Matthias Clasen <mclasen@redhat.com> + + * gdk/gdk-sections.txt: Add GdkEventGrabBroken. + 2005-06-21 Matthias Clasen <mclasen@redhat.com> * gdk/gdk-sections.txt: Add gdk_window_move_region diff --git a/docs/reference/gdk/gdk-sections.txt b/docs/reference/gdk/gdk-sections.txt index 6dcde195e..09007673d 100644 --- a/docs/reference/gdk/gdk-sections.txt +++ b/docs/reference/gdk/gdk-sections.txt @@ -1101,6 +1101,7 @@ GdkEventNoExpose GdkEventWindowState GdkEventSetting GdkEventOwnerChange +GdkEventGrabBroken <SUBSECTION> GdkScrollDirection diff --git a/docs/reference/gdk/tmpl/event_structs.sgml b/docs/reference/gdk/tmpl/event_structs.sgml index 732cbeb07..438bb6e39 100644 --- a/docs/reference/gdk/tmpl/event_structs.sgml +++ b/docs/reference/gdk/tmpl/event_structs.sgml @@ -424,6 +424,22 @@ only available if the X server supports the XFIXES extension. @selection_time: the time at which the selection ownership was taken over @Since: 2.6 +<!-- ##### STRUCT GdkEventGrabBroken ##### --> +<para> +Generated when a pointer or keyboard grab is broken. On X11, this happens +when the grab window becomes unviewable (i.e. it or one of its ancestors +is unmapped), or if the same application grabs the pointer or keyboard +again. +</para> + +@type: the type of the event (%GDK_GRAB_BROKEN) +@window: the window which received the event, i.e. the window + that previously owned the grab +@send_event: %TRUE if the event was sent explicitly (e.g. using <function>XSendEvent</function>). +@keyboard: %TRUE if a keyboard grab was broken, %FALSE if a pointer + grab was broken +@Since: 2.8 + <!-- ##### ENUM GdkScrollDirection ##### --> <para> Specifies the direction for #GdkEventScroll. diff --git a/docs/reference/gdk/tmpl/events.sgml b/docs/reference/gdk/tmpl/events.sgml index 9b902f5b5..b1eb7bcf4 100644 --- a/docs/reference/gdk/tmpl/events.sgml +++ b/docs/reference/gdk/tmpl/events.sgml @@ -90,6 +90,8 @@ for the possible window states @GDK_SETTING: a setting has been modified. @GDK_OWNER_CHANGE: the owner of a selection has changed. This event type was added in 2.6 +@GDK_GRAB_BROKEN: a pointer or keyboard grab was broken. This event type + was added in 2.8. <!-- ##### ENUM GdkEventMask ##### --> <para> diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h index 32873091d..797bee746 100644 --- a/gdk/gdkevents.h +++ b/gdk/gdkevents.h @@ -33,6 +33,7 @@ typedef struct _GdkEventClient GdkEventClient; typedef struct _GdkEventDND GdkEventDND; typedef struct _GdkEventWindowState GdkEventWindowState; typedef struct _GdkEventSetting GdkEventSetting; +typedef struct _GdkEventGrabBroken GdkEventGrabBroken; typedef union _GdkEvent GdkEvent; @@ -118,7 +119,8 @@ typedef enum GDK_SCROLL = 31, GDK_WINDOW_STATE = 32, GDK_SETTING = 33, - GDK_OWNER_CHANGE = 34 + GDK_OWNER_CHANGE = 34, + GDK_GRAB_BROKEN = 35 } GdkEventType; /* Event masks. (Used to select what types of events a window @@ -429,6 +431,13 @@ struct _GdkEventWindowState GdkWindowState new_window_state; }; +struct _GdkEventGrabBroken { + GdkEventType type; + GdkWindow *window; + gint8 send_event; + gboolean keyboard; +}; + /* Event types for DND */ struct _GdkEventDND { @@ -463,6 +472,7 @@ union _GdkEvent GdkEventDND dnd; GdkEventWindowState window_state; GdkEventSetting setting; + GdkEventGrabBroken grab_broken; }; GType gdk_event_get_type (void) G_GNUC_CONST; diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index 47a7eb482..23f92a241 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -2919,8 +2919,29 @@ gdk_event_translate (GdkDisplay *display, } break; - case WM_SETFOCUS: case WM_KILLFOCUS: + if (p_grab_window != NULL && !GDK_WINDOW_DESTROYED (p_grab_window)) + { + event = gdk_event_new (GDK_GRAB_BROKEN); + event->grab_broken.window = p_grab_window; + event->grab_broken.send_event = 0; + event->grab_broken.keyboard = FALSE; + + append_event (display, event); + } + if (k_grab_window != NULL && !GDK_WINDOW_DESTROYED (k_grab_window) + && k_grab_window != p_grab_window) + { + event = gdk_event_new (GDK_GRAB_BROKEN); + event->grab_broken.window = k_grab_window; + event->grab_broken.send_event = 0; + event->grab_broken.keyboard = TRUE; + + append_event (display, event); + } + + /* fallthrough */ + case WM_SETFOCUS: if (k_grab_window != NULL && !k_grab_owner_events) break; diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index 47b06cef7..92c9f63a6 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -137,6 +137,20 @@ gdk_x11_convert_grab_status (gint status) return 0; } +static void +generate_grab_broken_event (GdkWindow *window, + gboolean keyboard) +{ + GdkEvent event; + + event.type = GDK_GRAB_BROKEN; + event.grab_broken.window = window; + event.grab_broken.send_event = 0; + event.grab_broken.keyboard = keyboard; + + gdk_event_put (&event); +} + /* *-------------------------------------------------------------- * gdk_pointer_grab @@ -237,6 +251,10 @@ gdk_pointer_grab (GdkWindow * window, if (return_val == GrabSuccess) { GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window)); + if (display_x11->pointer_xgrab_window != NULL) + generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window), + FALSE); + display_x11->pointer_xgrab_window = (GdkWindowObject *)window; display_x11->pointer_xgrab_serial = serial; display_x11->pointer_xgrab_owner_events = owner_events; @@ -334,6 +352,11 @@ gdk_keyboard_grab (GdkWindow * window, if (return_val == GrabSuccess) { GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window)); + + if (display_x11->keyboard_xgrab_window != NULL) + generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window), + TRUE); + display_x11->keyboard_xgrab_window = (GdkWindowObject *)window; display_x11->keyboard_xgrab_serial = serial; display_x11->keyboard_xgrab_owner_events = owner_events; @@ -405,7 +428,11 @@ _gdk_xgrab_check_unmap (GdkWindow *window, tmp = tmp->parent; if (tmp) - display_x11->pointer_xgrab_window = NULL; + { + generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window), + FALSE); + display_x11->pointer_xgrab_window = NULL; + } } if (display_x11->keyboard_xgrab_window && @@ -419,7 +446,11 @@ _gdk_xgrab_check_unmap (GdkWindow *window, tmp = tmp->parent; if (tmp) - display_x11->keyboard_xgrab_window = NULL; + { + generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window), + TRUE); + display_x11->keyboard_xgrab_window = NULL; + } } } @@ -436,10 +467,18 @@ _gdk_xgrab_check_destroy (GdkWindow *window) GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window)); if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window) - display_x11->pointer_xgrab_window = NULL; + { + generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window), + FALSE); + display_x11->pointer_xgrab_window = NULL; + } if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_window) - display_x11->keyboard_xgrab_window = NULL; + { + generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window), + TRUE); + display_x11->keyboard_xgrab_window = NULL; + } } void diff --git a/gtk/gtkcolorsel.c b/gtk/gtkcolorsel.c index e0199f358..92bd24f9f 100644 --- a/gtk/gtkcolorsel.c +++ b/gtk/gtkcolorsel.c @@ -139,6 +139,8 @@ struct _ColorSelectionPrivate /* Window for grabbing on */ GtkWidget *dropper_grab_widget; + guint32 grab_time; + gboolean has_grab; /* Connection to settings */ gulong settings_connection; @@ -162,6 +164,8 @@ static void gtk_color_selection_get_property (GObject *object static void gtk_color_selection_realize (GtkWidget *widget); static void gtk_color_selection_unrealize (GtkWidget *widget); static void gtk_color_selection_show_all (GtkWidget *widget); +static gboolean gtk_color_selection_grab_broken (GtkWidget *widget, + GdkEventGrabBroken *event); static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel, gint index, @@ -1248,14 +1252,27 @@ shutdown_eyedropper (GtkWidget *widget) GtkColorSelection *colorsel; ColorSelectionPrivate *priv; GdkDisplay *display = gtk_widget_get_display (widget); - guint32 time = gtk_get_current_event_time (); colorsel = GTK_COLOR_SELECTION (widget); priv = colorsel->private_data; - gdk_display_keyboard_ungrab (display, time); - gdk_display_pointer_ungrab (display, time); - gtk_grab_remove (priv->dropper_grab_widget); + if (priv->has_grab) + { + gdk_display_keyboard_ungrab (display, priv->grab_time); + gdk_display_pointer_ungrab (display, priv->grab_time); + gtk_grab_remove (priv->dropper_grab_widget); + + priv->has_grab = FALSE; + } +} + +static gboolean +gtk_color_selection_grab_broken (GtkWidget *widget, + GdkEventGrabBroken *event) +{ + shutdown_eyedropper (widget); + + return TRUE; } static void @@ -1410,6 +1427,7 @@ get_screen_color (GtkWidget *button) GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button)); GdkCursor *picker_cursor; GdkGrabStatus grab_status; + guint32 time = gtk_get_current_event_time (); if (priv->dropper_grab_widget == NULL) { @@ -1419,11 +1437,14 @@ get_screen_color (GtkWidget *button) GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); gtk_widget_show (priv->dropper_grab_widget); + + gdk_window_set_user_data (priv->dropper_grab_widget->window, colorsel); + gdk_window_reparent (priv->dropper_grab_widget->window, + GTK_WIDGET (colorsel)->window, 0, 0); } if (gdk_keyboard_grab (priv->dropper_grab_widget->window, - FALSE, - gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS) + FALSE, time) != GDK_GRAB_SUCCESS) return; picker_cursor = make_picker_cursor (screen); @@ -1432,16 +1453,18 @@ get_screen_color (GtkWidget *button) GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, NULL, picker_cursor, - gtk_get_current_event_time ()); + time); gdk_cursor_unref (picker_cursor); if (grab_status != GDK_GRAB_SUCCESS) { - gdk_display_keyboard_ungrab (gtk_widget_get_display (button), GDK_CURRENT_TIME); + gdk_display_keyboard_ungrab (gtk_widget_get_display (button), time); return; } gtk_grab_add (priv->dropper_grab_widget); + priv->grab_time = time; + priv->has_grab = TRUE; g_signal_connect (priv->dropper_grab_widget, "button_press_event", G_CALLBACK (mouse_press), colorsel); @@ -1843,6 +1866,7 @@ gtk_color_selection_class_init (GtkColorSelectionClass *klass) widget_class->realize = gtk_color_selection_realize; widget_class->unrealize = gtk_color_selection_unrealize; widget_class->show_all = gtk_color_selection_show_all; + widget_class->grab_broken_event = gtk_color_selection_grab_broken; g_object_class_install_property (gobject_class, PROP_HAS_OPACITY_CONTROL, diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 1d53bf087..bd42c7ea4 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1369,6 +1369,7 @@ gtk_main_do_event (GdkEvent *event) case GDK_CLIENT_EVENT: case GDK_VISIBILITY_NOTIFY: case GDK_WINDOW_STATE: + case GDK_GRAB_BROKEN: gtk_widget_event (event_widget, event); break; diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c index 1febb4653..123f00911 100644 --- a/gtk/gtkmenushell.c +++ b/gtk/gtkmenushell.c @@ -166,6 +166,8 @@ static gint gtk_menu_shell_leave_notify (GtkWidget *widget, GdkEventCrossing *event); static void gtk_menu_shell_screen_changed (GtkWidget *widget, GdkScreen *previous_screen); +static gboolean gtk_menu_shell_grab_broken (GtkWidget *widget, + GdkEventGrabBroken *event); static void gtk_menu_shell_add (GtkContainer *container, GtkWidget *widget); static void gtk_menu_shell_remove (GtkContainer *container, @@ -254,6 +256,7 @@ gtk_menu_shell_class_init (GtkMenuShellClass *klass) widget_class->realize = gtk_menu_shell_realize; widget_class->button_press_event = gtk_menu_shell_button_press; widget_class->button_release_event = gtk_menu_shell_button_release; + widget_class->grab_broken_event = gtk_menu_shell_grab_broken; widget_class->key_press_event = gtk_menu_shell_key_press; widget_class->enter_notify_event = gtk_menu_shell_enter_notify; widget_class->leave_notify_event = gtk_menu_shell_leave_notify; @@ -604,6 +607,27 @@ gtk_menu_shell_button_press (GtkWidget *widget, return TRUE; } +static gboolean +gtk_menu_shell_grab_broken (GtkWidget *widget, + GdkEventGrabBroken *event) +{ + GtkMenuShell *menu_shell; + GtkWidget *menu_item; + gint deactivate; + + g_return_val_if_fail (GTK_IS_MENU_SHELL (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + menu_shell = GTK_MENU_SHELL (widget); + if (menu_shell->active) + { + gtk_menu_shell_deactivate (menu_shell); + g_signal_emit (menu_shell, menu_shell_signals[SELECTION_DONE], 0); + } + + return TRUE; +} + static gint gtk_menu_shell_button_release (GtkWidget *widget, GdkEventButton *event) diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c index dcf838efb..f0fb5f6ea 100644 --- a/gtk/gtkpaned.c +++ b/gtk/gtkpaned.c @@ -99,6 +99,8 @@ static gboolean gtk_paned_motion (GtkWidget *widget, GdkEventMotion *event); static gboolean gtk_paned_focus (GtkWidget *widget, GtkDirectionType direction); +static gboolean gtk_paned_grab_broken (GtkWidget *widget, + GdkEventGrabBroken *event); static void gtk_paned_add (GtkContainer *container, GtkWidget *widget); static void gtk_paned_remove (GtkContainer *container, @@ -127,7 +129,7 @@ static gboolean gtk_paned_accept_position (GtkPaned *paned); static gboolean gtk_paned_cancel_position (GtkPaned *paned); static gboolean gtk_paned_toggle_handle_focus (GtkPaned *paned); -static GType gtk_paned_child_type (GtkContainer *container); +static GType gtk_paned_child_type (GtkContainer *container); static GtkContainerClass *parent_class = NULL; @@ -135,6 +137,7 @@ struct _GtkPanedPrivate { GtkWidget *saved_focus; GtkPaned *first_paned; + guint32 grab_time; }; GType @@ -219,6 +222,7 @@ gtk_paned_class_init (GtkPanedClass *class) widget_class->button_press_event = gtk_paned_button_press; widget_class->button_release_event = gtk_paned_button_release; widget_class->motion_notify_event = gtk_paned_motion; + widget_class->grab_broken_event = gtk_paned_grab_broken; container_class->add = gtk_paned_add; container_class->remove = gtk_paned_remove; @@ -882,18 +886,20 @@ gtk_paned_button_press (GtkWidget *widget, if (!paned->in_drag && (event->window == paned->handle) && (event->button == 1)) { - paned->in_drag = TRUE; - /* We need a server grab here, not gtk_grab_add(), since * we don't want to pass events on to the widget's children */ - gdk_pointer_grab (paned->handle, FALSE, - GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON1_MOTION_MASK - | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK - | GDK_LEAVE_NOTIFY_MASK, - NULL, NULL, - event->time); + if (gdk_pointer_grab (paned->handle, FALSE, + GDK_POINTER_MOTION_HINT_MASK + | GDK_BUTTON1_MOTION_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK, + NULL, NULL, + event->time) != GDK_GRAB_SUCCESS) + return FALSE; + + paned->in_drag = TRUE; + paned->priv->grab_time = event->time; if (paned->orientation == GTK_ORIENTATION_HORIZONTAL) paned->drag_pos = event->y; @@ -907,6 +913,17 @@ gtk_paned_button_press (GtkWidget *widget, } static gboolean +gtk_paned_grab_broken (GtkWidget *widget, + GdkEventGrabBroken *event) +{ + GtkPaned *paned = GTK_PANED (widget); + + paned->in_drag = FALSE; + paned->drag_pos = -1; + paned->position_set = TRUE; +} + +static gboolean gtk_paned_button_release (GtkWidget *widget, GdkEventButton *event) { @@ -918,7 +935,7 @@ gtk_paned_button_release (GtkWidget *widget, paned->drag_pos = -1; paned->position_set = TRUE; gdk_display_pointer_ungrab (gtk_widget_get_display (widget), - event->time); + paned->priv->grab_time); return TRUE; } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 200678923..ea725f786 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -120,6 +120,7 @@ enum { ACCEL_CLOSURES_CHANGED, SCREEN_CHANGED, CAN_ACTIVATE_ACCEL, + GRAB_BROKEN, LAST_SIGNAL }; @@ -398,6 +399,7 @@ gtk_widget_class_init (GtkWidgetClass *klass) klass->drag_data_received = NULL; klass->screen_changed = NULL; klass->can_activate_accel = gtk_widget_real_can_activate_accel; + klass->grab_broken_event = NULL; klass->show_help = gtk_widget_real_show_help; @@ -1324,6 +1326,32 @@ gtk_widget_class_init (GtkWidgetClass *klass) _gtk_marshal_BOOLEAN__BOXED, G_TYPE_BOOLEAN, 1, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * GtkWidget::grab-broken: + * @widget: the object which received the signal + * @event: the #GdkEventGrabBroken event + * + * Emitted when a pointer or keyboard grab on a window belonging + * to @widget gets broken. + * + * On X11, this happens when the grab window becomes unviewable + * (i.e. it or one of its ancestors is unmapped), or if the same + * application grabs the pointer or keyboard again. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + * + * Since: 2.8 + */ + widget_signals[GRAB_BROKEN] = + g_signal_new ("grab_broken_event", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkWidgetClass, grab_broken_event), + _gtk_boolean_handled_accumulator, NULL, + _gtk_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** * GtkWidget::popup-menu * @widget: the object which received the signal @@ -3694,6 +3722,9 @@ gtk_widget_event_internal (GtkWidget *widget, case GDK_VISIBILITY_NOTIFY: signal_num = VISIBILITY_NOTIFY_EVENT; break; + case GDK_GRAB_BROKEN: + signal_num = GRAB_BROKEN; + break; default: g_warning ("gtk_widget_event(): unhandled event type: %d", event->type); signal_num = -1; diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index ac8ef52cf..0c487bcdb 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -403,8 +403,11 @@ struct _GtkWidgetClass gboolean (*can_activate_accel) (GtkWidget *widget, guint signal_id); + /* Sent when a grab is broken. */ + gboolean (*grab_broken_event) (GtkWidget *widget, + GdkEventGrabBroken *event); + /* Padding for future expansion */ - void (*_gtk_reserved2) (void); void (*_gtk_reserved3) (void); void (*_gtk_reserved4) (void); void (*_gtk_reserved5) (void); |