static void window_grab_broken_cb (GSWindow *window, GdkEventGrabBroken *event, GSManager *manager) { GdkDisplay *display; GdkSeat *seat; GdkDevice *device; display = gdk_window_get_display (gs_window_get_gdk_window (window)); seat = gdk_display_get_default_seat (display); if (event->keyboard) { gs_debug ("KEYBOARD GRAB BROKEN!"); device = gdk_seat_get_pointer (seat); if (!gdk_display_device_is_grabbed (display, device)) gs_grab_reset (manager->priv->grab); } else { gs_debug ("POINTER GRAB BROKEN!"); device = gdk_seat_get_keyboard (seat); if (!gdk_display_device_is_grabbed (display, device)) gs_grab_reset (manager->priv->grab); } }
static gboolean maybe_redirect_mouse_event (XEvent *xevent) { GdkDisplay *gdisplay; MetaUI *ui; #if GTK_CHECK_VERSION (3, 0, 0) GdkDeviceManager *gmanager; GdkDevice *gdevice; GdkEvent *gevent; #else GdkEvent gevent; #endif GdkWindow *gdk_window; Window window; switch (xevent->type) { case ButtonPress: case ButtonRelease: window = xevent->xbutton.window; break; case MotionNotify: window = xevent->xmotion.window; break; case EnterNotify: case LeaveNotify: window = xevent->xcrossing.window; break; default: return FALSE; } gdisplay = gdk_x11_lookup_xdisplay (xevent->xany.display); ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui"); if (!ui) return FALSE; #if GTK_CHECK_VERSION (3, 0, 0) gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window); #else gdk_window = gdk_window_lookup_for_display (gdisplay, window); #endif if (gdk_window == NULL) return FALSE; #if GTK_CHECK_VERSION (3, 0, 0) gmanager = gdk_display_get_device_manager (gdisplay); gdevice = gdk_device_manager_get_client_pointer (gmanager); #endif /* If GDK already thinks it has a grab, we better let it see events; this * is the menu-navigation case and events need to get sent to the appropriate * (client-side) subwindow for individual menu items. */ #if GTK_CHECK_VERSION (3, 0, 0) if (gdk_display_device_is_grabbed (gdisplay, gdevice)) #else if (gdk_display_pointer_is_grabbed (gdisplay)) #endif return FALSE; #if !GTK_CHECK_VERSION (3, 0, 0) memset (&gevent, 0, sizeof (gevent)); #endif switch (xevent->type) { case ButtonPress: case ButtonRelease: if (xevent->type == ButtonPress) { GtkSettings *settings = gtk_settings_get_default (); int double_click_time; int double_click_distance; g_object_get (settings, "gtk-double-click-time", &double_click_time, "gtk-double-click-distance", &double_click_distance, NULL); if (xevent->xbutton.button == ui->button_click_number && xevent->xbutton.window == ui->button_click_window && xevent->xbutton.time < ui->button_click_time + double_click_time && ABS (xevent->xbutton.x - ui->button_click_x) <= double_click_distance && ABS (xevent->xbutton.y - ui->button_click_y) <= double_click_distance) { #if GTK_CHECK_VERSION (3, 0, 0) gevent = gdk_event_new (GDK_2BUTTON_PRESS); #else gevent.button.type = GDK_2BUTTON_PRESS; #endif ui->button_click_number = 0; } else { #if GTK_CHECK_VERSION (3, 0, 0) gevent = gdk_event_new (GDK_BUTTON_PRESS); #else gevent.button.type = GDK_BUTTON_PRESS; #endif ui->button_click_number = xevent->xbutton.button; ui->button_click_window = xevent->xbutton.window; ui->button_click_time = xevent->xbutton.time; ui->button_click_x = xevent->xbutton.x; ui->button_click_y = xevent->xbutton.y; } } else { #if GTK_CHECK_VERSION (3, 0, 0) gevent = gdk_event_new (GDK_BUTTON_RELEASE); #else gevent.button.type = GDK_BUTTON_RELEASE; #endif } #if GTK_CHECK_VERSION (3, 0, 0) gevent->button.window = g_object_ref (gdk_window); gevent->button.button = xevent->xbutton.button; gevent->button.time = xevent->xbutton.time; gevent->button.x = xevent->xbutton.x; gevent->button.y = xevent->xbutton.y; gevent->button.x_root = xevent->xbutton.x_root; gevent->button.y_root = xevent->xbutton.y_root; #else gevent.button.window = gdk_window; gevent.button.button = xevent->xbutton.button; gevent.button.time = xevent->xbutton.time; gevent.button.x = xevent->xbutton.x; gevent.button.y = xevent->xbutton.y; gevent.button.x_root = xevent->xbutton.x_root; gevent.button.y_root = xevent->xbutton.y_root; #endif break; case MotionNotify: #if GTK_CHECK_VERSION (3, 0, 0) gevent = gdk_event_new (GDK_MOTION_NOTIFY); gevent->motion.type = GDK_MOTION_NOTIFY; gevent->motion.window = g_object_ref (gdk_window); #else gevent.motion.type = GDK_MOTION_NOTIFY; gevent.motion.window = gdk_window; #endif break; case EnterNotify: case LeaveNotify: #if GTK_CHECK_VERSION (3, 0, 0) gevent = gdk_event_new (xevent->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); gevent->crossing.window = g_object_ref (gdk_window); gevent->crossing.x = xevent->xcrossing.x; gevent->crossing.y = xevent->xcrossing.y; #else gevent.crossing.type = xevent->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY; gevent.crossing.window = gdk_window; gevent.crossing.x = xevent->xcrossing.x; gevent.crossing.y = xevent->xcrossing.y; #endif break; default: g_assert_not_reached (); break; } /* If we've gotten here, we've filled in the gdk_event and should send it on */ #if GTK_CHECK_VERSION (3, 0, 0) gdk_event_set_device (gevent, gdevice); gtk_main_do_event (gevent); gdk_event_free (gevent); #else gtk_main_do_event (&gevent); #endif return TRUE; }
static gboolean maybe_redirect_mouse_event (XEvent *xevent) { GdkDisplay *gdisplay; GdkDeviceManager *gmanager; GdkDevice *gdevice; MetaUI *ui; GdkEvent *gevent; GdkWindow *gdk_window; Window window; XIEvent *xev; XIDeviceEvent *xev_d = NULL; XIEnterEvent *xev_e = NULL; if (!is_input_event (xevent)) return FALSE; xev = (XIEvent *) xevent->xcookie.data; switch (xev->evtype) { case XI_TouchBegin: case XI_ButtonPress: case XI_ButtonRelease: case XI_Motion: xev_d = (XIDeviceEvent *) xev; window = xev_d->event; break; case XI_Enter: case XI_Leave: xev_e = (XIEnterEvent *) xev; window = xev_e->event; break; default: return FALSE; } gdisplay = gdk_x11_lookup_xdisplay (xev->display); ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui"); if (!ui) return FALSE; gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window); if (gdk_window == NULL) return FALSE; gmanager = gdk_display_get_device_manager (gdisplay); gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID); /* If GDK already thinks it has a grab, we better let it see events; this * is the menu-navigation case and events need to get sent to the appropriate * (client-side) subwindow for individual menu items. */ if (gdk_display_device_is_grabbed (gdisplay, gdevice)) return FALSE; switch (xev->evtype) { case XI_TouchBegin: case XI_ButtonPress: case XI_ButtonRelease: if (xev_d->evtype == XI_ButtonPress || xev_d->evtype == XI_TouchBegin) { GtkSettings *settings = gtk_settings_get_default (); int double_click_time; int double_click_distance; int button; g_object_get (settings, "gtk-double-click-time", &double_click_time, "gtk-double-click-distance", &double_click_distance, NULL); if (xev->evtype == XI_TouchBegin) button = 1; else button = xev_d->detail; if (button == ui->button_click_number && xev_d->event == ui->button_click_window && xev_d->time < ui->button_click_time + double_click_time && ABS (xev_d->event_x - ui->button_click_x) <= double_click_distance && ABS (xev_d->event_y - ui->button_click_y) <= double_click_distance) { gevent = gdk_event_new (GDK_2BUTTON_PRESS); ui->button_click_number = 0; } else { gevent = gdk_event_new (GDK_BUTTON_PRESS); ui->button_click_number = button; ui->button_click_window = xev_d->event; ui->button_click_time = xev_d->time; ui->button_click_x = xev_d->event_x; ui->button_click_y = xev_d->event_y; } gevent->button.button = button; } else { gevent = gdk_event_new (GDK_BUTTON_RELEASE); gevent->button.button = xev_d->detail; } gevent->button.window = g_object_ref (gdk_window); gevent->button.time = xev_d->time; gevent->button.x = xev_d->event_x; gevent->button.y = xev_d->event_y; gevent->button.x_root = xev_d->root_x; gevent->button.y_root = xev_d->root_y; break; case XI_Motion: gevent = gdk_event_new (GDK_MOTION_NOTIFY); gevent->motion.type = GDK_MOTION_NOTIFY; gevent->motion.window = g_object_ref (gdk_window); break; case XI_Enter: case XI_Leave: gevent = gdk_event_new (xev_e->evtype == XI_Enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); gevent->crossing.window = g_object_ref (gdk_window); gevent->crossing.x = xev_e->event_x; gevent->crossing.y = xev_e->event_y; break; default: g_assert_not_reached (); break; } /* If we've gotten here, we've created the gdk_event and should send it on */ gdk_event_set_device (gevent, gdevice); gtk_main_do_event (gevent); gdk_event_free (gevent); return TRUE; }