summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2005-06-25 07:10:40 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2005-06-25 07:10:40 +0000
commit9b356ea0d8ee1992ad9b3559aadad0c4e2b56f2c (patch)
tree2b22564953b69dff46505860a4918ac10c467e3b
parenteffe3785cf61084d9f7e9427cea0999bb4a32473 (diff)
downloadgdk-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--ChangeLog33
-rw-r--r--ChangeLog.pre-2-1033
-rw-r--r--ChangeLog.pre-2-833
-rw-r--r--docs/reference/ChangeLog4
-rw-r--r--docs/reference/gdk/gdk-sections.txt1
-rw-r--r--docs/reference/gdk/tmpl/event_structs.sgml16
-rw-r--r--docs/reference/gdk/tmpl/events.sgml2
-rw-r--r--gdk/gdkevents.h12
-rw-r--r--gdk/win32/gdkevents-win32.c23
-rw-r--r--gdk/x11/gdkmain-x11.c47
-rw-r--r--gtk/gtkcolorsel.c40
-rw-r--r--gtk/gtkmain.c1
-rw-r--r--gtk/gtkmenushell.c24
-rw-r--r--gtk/gtkpaned.c41
-rw-r--r--gtk/gtkwidget.c31
-rw-r--r--gtk/gtkwidget.h5
16 files changed, 319 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 28d90c1b0..c4bdfc1c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);