+Fri Mar 1 18:39:44 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h,
+ gdkwindow-x11.c}: Robustify tracking of pointer grab window.
+
+ * gdk/x11/gdkmain-x11.c: Keep track of current keyboard
+ grab window.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only,
+ gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk
+ API for finding out current grab information.
+
+ * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events
+ so that the effective behavior of owner_events = TRUE is changed
+ to "deliver events to same window group normally" instead
+ of "deliver events to same application normally. #69934
+
+ * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that
+ it works within the GtkList combo, where there is a
+ owner_events = FALSE gdk_pointer_grab() already in effect.
+ (#65006, reported by Damon Chaplin)
+
Sat Mar 2 14:32:50 2002 Owen Taylor <otaylor@redhat.com>
* configure.in: Default to --disable-gtk-doc (avoid Jade
+Fri Mar 1 18:39:44 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h,
+ gdkwindow-x11.c}: Robustify tracking of pointer grab window.
+
+ * gdk/x11/gdkmain-x11.c: Keep track of current keyboard
+ grab window.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only,
+ gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk
+ API for finding out current grab information.
+
+ * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events
+ so that the effective behavior of owner_events = TRUE is changed
+ to "deliver events to same window group normally" instead
+ of "deliver events to same application normally. #69934
+
+ * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that
+ it works within the GtkList combo, where there is a
+ owner_events = FALSE gdk_pointer_grab() already in effect.
+ (#65006, reported by Damon Chaplin)
+
Sat Mar 2 14:32:50 2002 Owen Taylor <otaylor@redhat.com>
* configure.in: Default to --disable-gtk-doc (avoid Jade
+Fri Mar 1 18:39:44 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h,
+ gdkwindow-x11.c}: Robustify tracking of pointer grab window.
+
+ * gdk/x11/gdkmain-x11.c: Keep track of current keyboard
+ grab window.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only,
+ gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk
+ API for finding out current grab information.
+
+ * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events
+ so that the effective behavior of owner_events = TRUE is changed
+ to "deliver events to same window group normally" instead
+ of "deliver events to same application normally. #69934
+
+ * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that
+ it works within the GtkList combo, where there is a
+ owner_events = FALSE gdk_pointer_grab() already in effect.
+ (#65006, reported by Damon Chaplin)
+
Sat Mar 2 14:32:50 2002 Owen Taylor <otaylor@redhat.com>
* configure.in: Default to --disable-gtk-doc (avoid Jade
+Fri Mar 1 18:39:44 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h,
+ gdkwindow-x11.c}: Robustify tracking of pointer grab window.
+
+ * gdk/x11/gdkmain-x11.c: Keep track of current keyboard
+ grab window.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only,
+ gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk
+ API for finding out current grab information.
+
+ * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events
+ so that the effective behavior of owner_events = TRUE is changed
+ to "deliver events to same window group normally" instead
+ of "deliver events to same application normally. #69934
+
+ * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that
+ it works within the GtkList combo, where there is a
+ owner_events = FALSE gdk_pointer_grab() already in effect.
+ (#65006, reported by Damon Chaplin)
+
Sat Mar 2 14:32:50 2002 Owen Taylor <otaylor@redhat.com>
* configure.in: Default to --disable-gtk-doc (avoid Jade
+Fri Mar 1 18:39:44 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h,
+ gdkwindow-x11.c}: Robustify tracking of pointer grab window.
+
+ * gdk/x11/gdkmain-x11.c: Keep track of current keyboard
+ grab window.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only,
+ gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk
+ API for finding out current grab information.
+
+ * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events
+ so that the effective behavior of owner_events = TRUE is changed
+ to "deliver events to same window group normally" instead
+ of "deliver events to same application normally. #69934
+
+ * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that
+ it works within the GtkList combo, where there is a
+ owner_events = FALSE gdk_pointer_grab() already in effect.
+ (#65006, reported by Damon Chaplin)
+
Sat Mar 2 14:32:50 2002 Owen Taylor <otaylor@redhat.com>
* configure.in: Default to --disable-gtk-doc (avoid Jade
+Fri Mar 1 18:39:44 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h,
+ gdkwindow-x11.c}: Robustify tracking of pointer grab window.
+
+ * gdk/x11/gdkmain-x11.c: Keep track of current keyboard
+ grab window.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only,
+ gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk
+ API for finding out current grab information.
+
+ * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events
+ so that the effective behavior of owner_events = TRUE is changed
+ to "deliver events to same window group normally" instead
+ of "deliver events to same application normally. #69934
+
+ * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that
+ it works within the GtkList combo, where there is a
+ owner_events = FALSE gdk_pointer_grab() already in effect.
+ (#65006, reported by Damon Chaplin)
+
Sat Mar 2 14:32:50 2002 Owen Taylor <otaylor@redhat.com>
* configure.in: Default to --disable-gtk-doc (avoid Jade
+Fri Mar 1 18:39:44 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h,
+ gdkwindow-x11.c}: Robustify tracking of pointer grab window.
+
+ * gdk/x11/gdkmain-x11.c: Keep track of current keyboard
+ grab window.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only,
+ gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk
+ API for finding out current grab information.
+
+ * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events
+ so that the effective behavior of owner_events = TRUE is changed
+ to "deliver events to same window group normally" instead
+ of "deliver events to same application normally. #69934
+
+ * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that
+ it works within the GtkList combo, where there is a
+ owner_events = FALSE gdk_pointer_grab() already in effect.
+ (#65006, reported by Damon Chaplin)
+
Sat Mar 2 14:32:50 2002 Owen Taylor <otaylor@redhat.com>
* configure.in: Default to --disable-gtk-doc (avoid Jade
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_ICONIFIED);
-
- if (_gdk_xgrab_window == window_private)
- _gdk_xgrab_window = NULL;
+
+ _gdk_xgrab_check_unmap (window, xevent->xany.serial);
break;
static GSList *gdk_error_traps = NULL; /* List of error traps */
static GSList *gdk_error_trap_free_list = NULL; /* Free list */
+/* Information about current pointer and keyboard grabs held by this
+ * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window
+ * window is NULL, then the other associated fields are ignored
+ */
+static GdkWindowObject *gdk_pointer_xgrab_window = NULL;
+static gulong gdk_pointer_xgrab_serial;
+static gboolean gdk_pointer_xgrab_owner_events;
+
+static GdkWindowObject *gdk_keyboard_xgrab_window = NULL;
+static gulong gdk_keyboard_xgrab_serial;
+static gboolean gdk_keyboard_xgrab_owner_events;
+
GdkArgDesc _gdk_windowing_args[] = {
{ "display", GDK_ARG_STRING, &_gdk_display_name, (GdkArgFunc)NULL },
{ "sync", GDK_ARG_BOOL, &gdk_synchronize, (GdkArgFunc)NULL },
Window xwindow;
Window xconfine_to;
Cursor xcursor;
+ unsigned long serial;
int i;
g_return_val_if_fail (window != NULL, 0);
cursor_private = (GdkCursorPrivate*) cursor;
xwindow = GDK_WINDOW_XID (window);
+ serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
xconfine_to = None;
}
if (return_val == GrabSuccess)
- _gdk_xgrab_window = (GdkWindowObject *)window;
+ {
+ gdk_pointer_xgrab_window = (GdkWindowObject *)window;
+ gdk_pointer_xgrab_serial = serial;
+ gdk_pointer_xgrab_owner_events = owner_events;
+ }
return gdk_x11_convert_grab_status (return_val);
}
_gdk_input_ungrab_pointer (time);
XUngrabPointer (gdk_display, time);
- _gdk_xgrab_window = NULL;
+ gdk_pointer_xgrab_window = NULL;
}
/*
gboolean
gdk_pointer_is_grabbed (void)
{
- return _gdk_xgrab_window != NULL;
+ return gdk_pointer_xgrab_window != NULL;
+}
+
+/**
+ * gdk_pointer_grab_info_libgtk_only:
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ * the @owner_events flag to gdk_pointer_grab() was %TRUE.
+ *
+ * Determines information about the current pointer grab.
+ * This is not public API and must not be used by applications.
+ *
+ * Return value: %TRUE if this application currently has the
+ * pointer grabbed.
+ **/
+gboolean
+gdk_pointer_grab_info_libgtk_only (GdkWindow **grab_window,
+ gboolean *owner_events)
+{
+ if (gdk_pointer_xgrab_window)
+ {
+ if (grab_window)
+ *grab_window = (GdkWindow *)gdk_pointer_xgrab_window;
+ if (owner_events)
+ *owner_events = gdk_pointer_xgrab_owner_events;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
}
/*
guint32 time)
{
gint return_val;
+ unsigned long serial;
g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+ serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+
if (!GDK_WINDOW_DESTROYED (window))
{
#ifdef G_ENABLE_DEBUG
else
return_val = AlreadyGrabbed;
+ if (return_val == GrabSuccess)
+ {
+ gdk_keyboard_xgrab_window = (GdkWindowObject *)window;
+ gdk_keyboard_xgrab_serial = serial;
+ gdk_keyboard_xgrab_owner_events = owner_events;
+ }
+
return gdk_x11_convert_grab_status (return_val);
}
gdk_keyboard_ungrab (guint32 time)
{
XUngrabKeyboard (gdk_display, time);
+ gdk_keyboard_xgrab_window = NULL;
+}
+
+/**
+ * gdk_keyboard_grab_info_libgtk_only:
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ * the @owner_events flag to gdk_keyboard_grab() was %TRUE.
+ *
+ * Determines information about the current keyboard grab.
+ * This is not public API and must not be used by applications.
+ *
+ * Return value: %TRUE if this application currently has the
+ * keyboard grabbed.
+ **/
+gboolean
+gdk_keyboard_grab_info_libgtk_only (GdkWindow **grab_window,
+ gboolean *owner_events)
+{
+ if (gdk_keyboard_xgrab_window)
+ {
+ if (grab_window)
+ *grab_window = (GdkWindow *)gdk_keyboard_xgrab_window;
+ if (owner_events)
+ *owner_events = gdk_keyboard_xgrab_owner_events;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * _gdk_xgrab_check_unmap:
+ * @window: a #GdkWindow
+ * @serial: serial from Unmap event (or from NextRequest(display)
+ * if the unmap is being done by this client.)
+ *
+ * Checks to see if an unmap request or event causes the current
+ * grab window to become not viewable, and if so, clear the
+ * the pointer we keep to it.
+ **/
+void
+_gdk_xgrab_check_unmap (GdkWindow *window,
+ gulong serial)
+{
+ if (gdk_pointer_xgrab_window && serial >= gdk_pointer_xgrab_serial)
+ {
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+ GdkWindowObject *tmp = gdk_pointer_xgrab_window;
+
+
+ while (tmp && tmp != private)
+ tmp = tmp->parent;
+
+ if (tmp)
+ gdk_pointer_xgrab_window = NULL;
+ }
+
+ if (gdk_keyboard_xgrab_window && serial >= gdk_keyboard_xgrab_serial)
+ {
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+ GdkWindowObject *tmp = gdk_keyboard_xgrab_window;
+
+
+ while (tmp && tmp != private)
+ tmp = tmp->parent;
+
+ if (tmp)
+ gdk_keyboard_xgrab_window = NULL;
+ }
+}
+
+/**
+ * _gdk_xgrab_check_destroy:
+ * @window: a #GdkWindow
+ *
+ * Checks to see if window is the current grab window, and if
+ * so, clear the current grab window.
+ **/
+void
+_gdk_xgrab_check_destroy (GdkWindow *window)
+{
+ if ((GdkWindowObject *)window == gdk_pointer_xgrab_window)
+ gdk_pointer_xgrab_window = NULL;
+
+ if ((GdkWindowObject *)window == gdk_keyboard_xgrab_window)
+ gdk_keyboard_xgrab_window = NULL;
}
/*
void _gdk_x11_initialize_locale (void);
+void _gdk_xgrab_check_unmap (GdkWindow *window,
+ gulong serial);
+void _gdk_xgrab_check_destroy (GdkWindow *window);
+
extern GdkDrawableClass _gdk_x11_drawable_class;
extern Window _gdk_root_window;
extern gboolean _gdk_use_xshm;
extern Window _gdk_leader_window;
-extern GdkWindowObject *_gdk_xgrab_window; /* Window that currently holds the
- * x pointer grab
- */
-
/* Used to detect not-up-to-date keymap */
extern guint _gdk_keymap_serial;
wrapper = (GdkWindowObject*) draw_impl->wrapper;
+ _gdk_xgrab_check_destroy (GDK_WINDOW (wrapper));
+
if (!GDK_WINDOW_DESTROYED (wrapper))
{
gdk_xid_table_remove (draw_impl->xid);
}
}
else if (!recursing && !foreign_destroy)
- XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+ {
+ XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+ }
}
/* This function is called when the XWindow is really gone.
gdk_xid_table_remove (GDK_WINDOW_XID (window));
if (window_impl->focus_window)
gdk_xid_table_remove (window_impl->focus_window);
+
+ _gdk_xgrab_check_destroy (window);
gdk_drawable_unref (window);
}
private = (GdkWindowObject*) window;
+ /* We'll get the unmap notify eventually, and handle it then,
+ * but checking here makes things more consistent if we are
+ * just doing stuff ourself.
+ */
+ _gdk_xgrab_check_unmap (window,
+ NextRequest (GDK_WINDOW_XDISPLAY (window)));
+
/* You can't simply unmap toplevel windows. */
switch (private->window_type)
{
return TRUE;
}
+/* private libgtk to libgdk interfaces
+ */
+gboolean gdk_pointer_grab_info_libgtk_only (GdkWindow **grab_window,
+ gboolean *owner_events);
+gboolean gdk_keyboard_grab_info_libgtk_only (GdkWindow **grab_window,
+ gboolean *owner_events);
+
+static void
+rewrite_events_translate (GdkWindow *old_window,
+ GdkWindow *new_window,
+ gdouble *x,
+ gdouble *y)
+{
+ gint old_origin_x, old_origin_y;
+ gint new_origin_x, new_origin_y;
+
+ gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
+ gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
+
+ *x += new_origin_x - old_origin_x;
+ *y += new_origin_y - old_origin_y;
+}
+
+GdkEvent *
+rewrite_event_for_window (GdkEvent *event,
+ GdkWindow *new_window)
+{
+ event = gdk_event_copy (event);
+
+ switch (event->type)
+ {
+ case GDK_SCROLL:
+ rewrite_events_translate (event->any.window,
+ new_window,
+ &event->scroll.x, &event->scroll.y);
+ break;
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ rewrite_events_translate (event->any.window,
+ new_window,
+ &event->button.x, &event->button.y);
+ break;
+ case GDK_MOTION_NOTIFY:
+ rewrite_events_translate (event->any.window,
+ new_window,
+ &event->motion.x, &event->motion.y);
+ break;
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ case GDK_PROXIMITY_IN:
+ case GDK_PROXIMITY_OUT:
+ break;
+
+ default:
+ return event;
+ }
+
+ g_object_unref (event->any.window);
+ event->any.window = g_object_ref (new_window);
+
+ return event;
+}
+
+/* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
+ * then what X11 does is deliver the event normally if it was going to this
+ * client, otherwise, delivers it in terms of the grab window. This function
+ * rewrites events to the effect that events going to the same window group
+ * are delivered normally, otherwise, the event is delivered in terms of the
+ * grab window.
+ */
+static GdkEvent *
+rewrite_event_for_grabs (GdkEvent *event)
+{
+ GdkWindow *grab_window;
+ GtkWidget *event_widget, *grab_widget;;
+ gboolean owner_events;
+
+ switch (event->type)
+ {
+ case GDK_SCROLL:
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ case GDK_MOTION_NOTIFY:
+ case GDK_PROXIMITY_IN:
+ case GDK_PROXIMITY_OUT:
+ if (!gdk_pointer_grab_info_libgtk_only (&grab_window, &owner_events) ||
+ !owner_events)
+ return NULL;
+ break;
+
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ if (!gdk_keyboard_grab_info_libgtk_only (&grab_window, &owner_events) ||
+ !owner_events)
+ return NULL;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ event_widget = gtk_get_event_widget (event);
+ gdk_window_get_user_data (grab_window, (void**) &grab_widget);
+
+ if (grab_widget &&
+ gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
+ return rewrite_event_for_window (event, grab_window);
+ else
+ return NULL;
+}
+
void
gtk_main_do_event (GdkEvent *event)
{
GtkWidget *grab_widget;
GtkWindowGroup *window_group;
GdkEvent *next_event;
+ GdkEvent *rewritten_event = NULL;
GList *tmp_list;
/* If there are any events pending then get the next one.
return;
}
+
+ /* If pointer or keyboard grabs are in effect, munge the events
+ * so that each window group looks like a separate app.
+ */
+ rewritten_event = rewrite_event_for_grabs (event);
+ if (rewritten_event)
+ {
+ event = rewritten_event;
+ event_widget = gtk_get_event_widget (event);
+ }
+ window_group = gtk_main_get_window_group (event_widget);
+
/* Push the event onto a stack of current events for
* gtk_current_event_get().
*/
current_events = g_list_prepend (current_events, event);
- window_group = gtk_main_get_window_group (event_widget);
-
/* If there is a grab in effect...
*/
if (window_group->grabs)
tmp_list = current_events;
current_events = g_list_remove_link (current_events, tmp_list);
g_list_free_1 (tmp_list);
+
+ if (rewritten_event)
+ gdk_event_free (rewritten_event);
}
gboolean
{
/* we don't actually gtk_grab, since a button is down */
+ gtk_grab_add (GTK_WIDGET (range));
+
range->layout->grab_location = location;
range->layout->grab_button = button;
static void
range_grab_remove (GtkRange *range)
{
+ gtk_grab_remove (GTK_WIDGET (range));
+
range->layout->grab_location = MOUSE_OUTSIDE;
range->layout->grab_button = 0;
{
GtkRange *range = GTK_RANGE (widget);
- range->layout->mouse_x = event->x;
- range->layout->mouse_y = event->y;
+ if (event->window == range->event_window)
+ {
+ range->layout->mouse_x = event->x;
+ range->layout->mouse_y = event->y;
+ }
+ else
+ {
+ gdk_window_get_pointer (range->event_window,
+ &range->layout->mouse_x,
+ &range->layout->mouse_y,
+ NULL);
+ }
if (range->layout->grab_button == event->button)
{
gtk_range_remove_step_timer (range);
if (grab_location == MOUSE_SLIDER)
- update_slider_position (range, event->x, event->y);
+ update_slider_position (range, range->layout->mouse_x, range->layout->mouse_y);
/* Flush any pending discontinuous/delayed updates */
gtk_range_update_value (range);