Handle broken grabs.

2005-06-29  Matthias Clasen  <mclasen@redhat.com>

        * gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
        grabs.

        * gtk/gtkrange.c (gtk_range_grab_broken): Handle broken
        grabs.

        * gdk/gdkevents.h: Add a boolean to specify wether the broken
        grab was implicit.

        * gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed):
        As the documentation states, don't return TRUE for
        implicit grabs.

        * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
        a boolean field to store wether a pointer grab is implicit.

        * gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event):
        Track implicit grabs.

        * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
        _gdk_xgrab_check_button_event for button events.
This commit is contained in:
Matthias Clasen 2005-06-30 03:35:30 +00:00 committed by Matthias Clasen
parent 546e045ccf
commit 87cafe5b4b
10 changed files with 184 additions and 12 deletions

View File

@ -1,3 +1,27 @@
2005-06-29 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
grabs.
* gtk/gtkrange.c (gtk_range_grab_broken): Handle broken
grabs.
* gdk/gdkevents.h: Add a boolean to specify wether the broken
grab was implicit.
* gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed):
As the documentation states, don't return TRUE for
implicit grabs.
* gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
a boolean field to store wether a pointer grab is implicit.
* gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event):
Track implicit grabs.
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
_gdk_xgrab_check_button_event for button events.
2005-06-28 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2):

View File

@ -1,3 +1,27 @@
2005-06-29 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
grabs.
* gtk/gtkrange.c (gtk_range_grab_broken): Handle broken
grabs.
* gdk/gdkevents.h: Add a boolean to specify wether the broken
grab was implicit.
* gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed):
As the documentation states, don't return TRUE for
implicit grabs.
* gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
a boolean field to store wether a pointer grab is implicit.
* gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event):
Track implicit grabs.
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
_gdk_xgrab_check_button_event for button events.
2005-06-28 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2):

View File

@ -1,3 +1,27 @@
2005-06-29 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
grabs.
* gtk/gtkrange.c (gtk_range_grab_broken): Handle broken
grabs.
* gdk/gdkevents.h: Add a boolean to specify wether the broken
grab was implicit.
* gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed):
As the documentation states, don't return TRUE for
implicit grabs.
* gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
a boolean field to store wether a pointer grab is implicit.
* gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event):
Track implicit grabs.
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
_gdk_xgrab_check_button_event for button events.
2005-06-28 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2):

View File

@ -1,3 +1,4 @@
#ifndef __GDK_EVENTS_H__
#define __GDK_EVENTS_H__
@ -436,6 +437,7 @@ struct _GdkEventGrabBroken {
GdkWindow *window;
gint8 send_event;
gboolean keyboard;
gboolean implicit;
GdkWindow *grab_window;
};

View File

@ -539,7 +539,8 @@ gdk_display_pointer_is_grabbed (GdkDisplay * display)
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL);
return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
!GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
}
/**

View File

@ -88,6 +88,7 @@ struct _GdkDisplayX11
GdkWindowObject *pointer_xgrab_window;
gulong pointer_xgrab_serial;
gboolean pointer_xgrab_owner_events;
gboolean pointer_xgrab_implicit;
guint32 pointer_xgrab_time;
GdkWindowObject *keyboard_xgrab_window;

View File

@ -1132,6 +1132,8 @@ gdk_event_translate (GdkDisplay *display,
}
set_user_time (window, event);
_gdk_xgrab_check_button_event (window, xevent);
break;
case ButtonRelease:
@ -1170,7 +1172,8 @@ gdk_event_translate (GdkDisplay *display,
event->button.device = display->core_pointer;
set_screen_from_root (display, event, xevent->xbutton.root);
_gdk_xgrab_check_button_event (window, xevent);
break;
case MotionNotify:

View File

@ -139,8 +139,9 @@ gdk_x11_convert_grab_status (gint status)
static void
generate_grab_broken_event (GdkWindow *window,
GdkWindow *grab_window,
gboolean keyboard)
gboolean keyboard,
gboolean implicit,
GdkWindow *grab_window)
{
GdkEvent event;
@ -148,6 +149,7 @@ generate_grab_broken_event (GdkWindow *window,
event.grab_broken.window = window;
event.grab_broken.send_event = 0;
event.grab_broken.keyboard = keyboard;
event.grab_broken.implicit = implicit;
event.grab_broken.grab_window = grab_window;
gdk_event_put (&event);
@ -254,14 +256,16 @@ gdk_pointer_grab (GdkWindow * window,
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
if (display_x11->pointer_xgrab_window != NULL &&
display_x11->pointer_xgrab_window != window)
display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
window, FALSE);
FALSE, display_x11->pointer_xgrab_implicit,
window);
display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
display_x11->pointer_xgrab_serial = serial;
display_x11->pointer_xgrab_owner_events = owner_events;
display_x11->pointer_xgrab_time = time;
display_x11->pointer_xgrab_implicit = FALSE;
}
return gdk_x11_convert_grab_status (return_val);
@ -357,9 +361,9 @@ gdk_keyboard_grab (GdkWindow * window,
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
if (display_x11->keyboard_xgrab_window != NULL &&
display_x11->keyboard_xgrab_window != window)
display_x11->keyboard_xgrab_window != (GdkWindowObject *)window)
generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
window, TRUE);
TRUE, FALSE, window);
display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
display_x11->keyboard_xgrab_serial = serial;
@ -435,7 +439,8 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
if (tmp)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
NULL, FALSE);
FALSE, display_x11->pointer_xgrab_implicit,
NULL);
display_x11->pointer_xgrab_window = NULL;
}
}
@ -453,7 +458,7 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
if (tmp)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
NULL, TRUE);
TRUE, FALSE, NULL);
display_x11->keyboard_xgrab_window = NULL;
}
}
@ -474,18 +479,58 @@ _gdk_xgrab_check_destroy (GdkWindow *window)
if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
NULL, FALSE);
FALSE, display_x11->pointer_xgrab_implicit,
NULL);
display_x11->pointer_xgrab_window = NULL;
}
if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_window)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
NULL, TRUE);
TRUE, FALSE, NULL);
display_x11->keyboard_xgrab_window = NULL;
}
}
/**
* _gdk_xgrab_check_button_event:
* @window: a #GdkWindow
* @event: an XEvent of type ButtonPress or ButtonRelease
*
* Checks to see if a button event starts or ends an implicit grab.
**/
void
_gdk_xgrab_check_button_event (GdkWindow *window,
XEvent *xevent)
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
/* track implicit grabs for button presses */
switch (xevent->type)
{
case ButtonPress:
if (!display_x11->pointer_xgrab_window)
{
display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
display_x11->pointer_xgrab_serial = xevent->xany.serial;
display_x11->pointer_xgrab_owner_events = FALSE;
display_x11->pointer_xgrab_time = xevent->xbutton.time;
display_x11->pointer_xgrab_implicit = TRUE;
}
break;
case ButtonRelease:
if (display_x11->pointer_xgrab_window &&
display_x11->pointer_xgrab_implicit &&
(xevent->xbutton.state & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
{
display_x11->pointer_xgrab_window = NULL;
}
break;
default:
g_assert_not_reached ();
}
}
void
_gdk_windowing_display_set_sm_client_id (GdkDisplay *display,
const gchar *sm_client_id)

View File

@ -112,6 +112,8 @@ static gint gtk_button_button_press (GtkWidget *widget,
GdkEventButton *event);
static gint gtk_button_button_release (GtkWidget *widget,
GdkEventButton *event);
static gint gtk_button_grab_broken (GtkWidget *widget,
GdkEventAny *event);
static gint gtk_button_key_release (GtkWidget *widget,
GdkEventKey *event);
static gint gtk_button_enter_notify (GtkWidget *widget,
@ -201,6 +203,7 @@ gtk_button_class_init (GtkButtonClass *klass)
widget_class->expose_event = gtk_button_expose;
widget_class->button_press_event = gtk_button_button_press;
widget_class->button_release_event = gtk_button_button_release;
widget_class->grab_broken_event = gtk_button_grab_broken;
widget_class->key_release_event = gtk_button_key_release;
widget_class->enter_notify_event = gtk_button_enter_notify;
widget_class->leave_notify_event = gtk_button_leave_notify;
@ -1262,6 +1265,29 @@ gtk_button_button_release (GtkWidget *widget,
return TRUE;
}
static gboolean
gtk_button_grab_broken (GtkWidget *widget,
GdkEventAny *event)
{
GtkButton *button = GTK_BUTTON (widget);
gboolean save_in;
/* Simulate a button release without the pointer in the button */
if (button->button_down)
{
save_in = button->in_button;
button->in_button = FALSE;
gtk_button_released (button);
if (save_in != button->in_button)
{
button->in_button = save_in;
gtk_button_update_state (button);
}
}
return TRUE;
}
static gboolean
gtk_button_key_release (GtkWidget *widget,
GdkEventKey *event)

View File

@ -124,6 +124,8 @@ static gint gtk_range_enter_notify (GtkWidget *widget,
GdkEventCrossing *event);
static gint gtk_range_leave_notify (GtkWidget *widget,
GdkEventCrossing *event);
static gboolean gtk_range_grab_broken (GtkWidget *widget,
GdkEventGrabBroken *event);
static void gtk_range_grab_notify (GtkWidget *widget,
gboolean was_grabbed);
static void gtk_range_state_changed (GtkWidget *widget,
@ -244,6 +246,7 @@ gtk_range_class_init (GtkRangeClass *class)
widget_class->scroll_event = gtk_range_scroll_event;
widget_class->enter_notify_event = gtk_range_enter_notify;
widget_class->leave_notify_event = gtk_range_leave_notify;
widget_class->grab_broken_event = gtk_range_grab_broken;
widget_class->grab_notify = gtk_range_grab_notify;
widget_class->state_changed = gtk_range_state_changed;
widget_class->style_set = gtk_range_style_set;
@ -1378,6 +1381,25 @@ stop_scrolling (GtkRange *range)
gtk_widget_queue_draw (GTK_WIDGET (range));
}
static gboolean
gtk_range_grab_broken (GtkWidget *widget,
GdkEventGrabBroken *event)
{
GtkRange *range = GTK_RANGE (widget);
if (range->layout->grab_location != MOUSE_OUTSIDE)
{
if (range->layout->grab_location == MOUSE_SLIDER)
update_slider_position (range, range->layout->mouse_x, range->layout->mouse_y);
stop_scrolling (range);
return TRUE;
}
return FALSE;
}
static gint
gtk_range_button_release (GtkWidget *widget,
GdkEventButton *event)