+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)
+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)
+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)
+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
GdkEventWindowState
GdkEventSetting
GdkEventOwnerChange
+GdkEventGrabBroken
<SUBSECTION>
GdkScrollDirection
@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.
@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>
typedef struct _GdkEventDND GdkEventDND;
typedef struct _GdkEventWindowState GdkEventWindowState;
typedef struct _GdkEventSetting GdkEventSetting;
+typedef struct _GdkEventGrabBroken GdkEventGrabBroken;
typedef union _GdkEvent GdkEvent;
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
GdkWindowState new_window_state;
};
+struct _GdkEventGrabBroken {
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ gboolean keyboard;
+};
+
/* Event types for DND */
struct _GdkEventDND {
GdkEventDND dnd;
GdkEventWindowState window_state;
GdkEventSetting setting;
+ GdkEventGrabBroken grab_broken;
};
GType gdk_event_get_type (void) G_GNUC_CONST;
}
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;
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
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;
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;
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 &&
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;
+ }
}
}
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
/* Window for grabbing on */
GtkWidget *dropper_grab_widget;
+ guint32 grab_time;
+ gboolean has_grab;
/* Connection to settings */
gulong settings_connection;
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,
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
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)
{
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);
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);
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,
case GDK_CLIENT_EVENT:
case GDK_VISIBILITY_NOTIFY:
case GDK_WINDOW_STATE:
+ case GDK_GRAB_BROKEN:
gtk_widget_event (event_widget, event);
break;
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,
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;
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)
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,
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;
{
GtkWidget *saved_focus;
GtkPaned *first_paned;
+ guint32 grab_time;
};
GType
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;
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;
return FALSE;
}
+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)
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;
}
ACCEL_CLOSURES_CHANGED,
SCREEN_CHANGED,
CAN_ACTIVATE_ACCEL,
+ GRAB_BROKEN,
LAST_SIGNAL
};
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;
_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
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;
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);