static GList * gdk_device_manager_win32_list_devices (GdkDeviceManager *device_manager, GdkDeviceType type) { GdkDeviceManagerWin32 *device_manager_win32; GList *devices = NULL, *l; device_manager_win32 = (GdkDeviceManagerWin32 *) device_manager; if (type == GDK_DEVICE_TYPE_MASTER) { devices = g_list_prepend (devices, device_manager_win32->core_keyboard); devices = g_list_prepend (devices, device_manager_win32->core_pointer); } else { if (type == GDK_DEVICE_TYPE_SLAVE) { devices = g_list_prepend (devices, device_manager_win32->system_keyboard); devices = g_list_prepend (devices, device_manager_win32->system_pointer); } for (l = device_manager_win32->wintab_devices; l != NULL; l = l->next) { GdkDevice *device = l->data; if (gdk_device_get_device_type (device) == type) devices = g_list_prepend (devices, device); } } return g_list_reverse (devices); }
static void device_changed_cb (GdkDeviceManager *manager, GdkDevice *device, gpointer user_data) { if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_FLOATING) device_removed_cb (manager, device, NULL); else device_added_cb (manager, device, NULL); }
/* * gtk_bubble_window_grab: * @window: a #GtkBubbleWindow * @device: a master #GdkDevice * @activate_time: timestamp to perform the grab * * This function performs GDK and GTK+ grabs on @device and * its paired #GdkDevice. After this call all pointer/keyboard * events will be handled by @window. * * Calling this also brings in a #GtkMenu alike behavior, clicking * outside the #GtkBubbleWindow or pressing the Escape key will * popdown the menu by default. * * <note> * If there was a previous grab, it will be undone before doing * the requested grab. * </note> * * Returns: %TRUE if the grab was successful * * Since: 3.8 */ gboolean _gtk_bubble_window_grab (GtkBubbleWindow *window, GdkDevice *device, guint32 activate_time) { GtkBubbleWindowPrivate *priv; GdkDevice *other_device; GdkWindow *grab_window; GdkGrabStatus status; g_return_val_if_fail (GTK_IS_BUBBLE_WINDOW (window), FALSE); g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE); g_return_val_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER, FALSE); priv = window->priv; if (!priv->has_pointing_to || gdk_window_is_destroyed (priv->relative_to)) return FALSE; if (priv->device) _gtk_bubble_window_ungrab (window); gtk_widget_realize (GTK_WIDGET (window)); grab_window = gtk_widget_get_window (GTK_WIDGET (window)); other_device = gdk_device_get_associated_device (device); status = gdk_device_grab (device, grab_window, GDK_OWNERSHIP_WINDOW, TRUE, GRAB_EVENT_MASK, NULL, activate_time); if (status == GDK_GRAB_SUCCESS) { status = gdk_device_grab (other_device, grab_window, GDK_OWNERSHIP_WINDOW, TRUE, GRAB_EVENT_MASK, NULL, activate_time); /* Ungrab the first device on error */ if (status != GDK_GRAB_SUCCESS) gdk_device_ungrab (device, activate_time); } if (status == GDK_GRAB_SUCCESS) { gtk_device_grab_add (GTK_WIDGET (window), device, TRUE); priv->device = device; } return status == GDK_GRAB_SUCCESS; }
/* taken from gtk/gtktreeview.c */ static void send_focus_change (GtkWidget *widget, GdkDevice *device, gboolean in) { GdkDeviceManager *device_manager; GList *devices, *d; device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget)); devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER); devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE)); devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING)); for (d = devices; d; d = d->next) { GdkDevice *dev = d->data; GdkEvent *fevent; GdkWindow *window; if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD) continue; window = gtk_widget_get_window (widget); /* Skip non-master keyboards that haven't * selected for events from this window */ if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER && !gdk_window_get_device_events (window, dev)) continue; fevent = gdk_event_new (GDK_FOCUS_CHANGE); fevent->focus_change.type = GDK_FOCUS_CHANGE; fevent->focus_change.window = g_object_ref (window); fevent->focus_change.in = in; gdk_event_set_device (fevent, device); gtk_widget_send_focus_change (widget, fevent); gdk_event_free (fevent); } g_list_free (devices); }
gboolean gdk_input_other_event (GdkDisplay *display, GdkEvent *event, MSG *msg, GdkWindow *window) { GdkDeviceManagerWin32 *device_manager; GdkDeviceWintab *source_device = NULL; GdkDeviceGrabInfo *last_grab; GdkEventMask masktest; guint key_state; POINT pt; PACKET packet; gint root_x, root_y; gint num_axes; gint x, y; guint translated_buttons, button_diff, button_mask; /* Translation from tablet button state to GDK button state for * buttons 1-3 - swap button 2 and 3. */ static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7}; if (event->any.window != wintab_window) { g_warning ("gdk_input_other_event: not wintab_window?"); return FALSE; } G_GNUC_BEGIN_IGNORE_DEPRECATIONS; device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (display)); G_GNUC_END_IGNORE_DEPRECATIONS; window = gdk_device_get_window_at_position (device_manager->core_pointer, &x, &y); if (window == NULL) window = gdk_get_default_root_window (); g_object_ref (window); GDK_NOTE (EVENTS_OR_INPUT, g_print ("gdk_input_other_event: window=%p %+d%+d\n", GDK_WINDOW_HWND (window), x, y)); if (msg->message == WT_PACKET || msg->message == WT_CSRCHANGE) { if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet)) return FALSE; } switch (msg->message) { case WT_PACKET: /* Don't produce any button or motion events while a window is being * moved or resized, see bug #151090. */ if (_modal_operation_in_progress) { GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n")); return FALSE; } if ((source_device = gdk_device_manager_find_wintab_device (device_manager, (HCTX) msg->lParam, packet.pkCursor)) == NULL) return FALSE; if (gdk_device_get_mode (GDK_DEVICE (source_device)) == GDK_MODE_DISABLED) return FALSE; last_grab = _gdk_display_get_last_device_grab (display, GDK_DEVICE (source_device)); if (last_grab && last_grab->window) { g_object_unref (window); window = g_object_ref (last_grab->window); } if (window == gdk_get_default_root_window ()) { GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n")); return FALSE; } num_axes = 0; if (source_device->pktdata & PK_X) source_device->last_axis_data[num_axes++] = packet.pkX; if (source_device->pktdata & PK_Y) source_device->last_axis_data[num_axes++] = packet.pkY; if (source_device->pktdata & PK_NORMAL_PRESSURE) source_device->last_axis_data[num_axes++] = packet.pkNormalPressure; if (source_device->pktdata & PK_ORIENTATION) { decode_tilt (source_device->last_axis_data + num_axes, source_device->orientation_axes, &packet); num_axes += 2; } translated_buttons = button_map[packet.pkButtons & 0x07] | (packet.pkButtons & ~0x07); if (translated_buttons != source_device->button_state) { /* At least one button has changed state so produce a button event * If more than one button has changed state (unlikely), * just care about the first and act on the next the next time * we get a packet */ button_diff = translated_buttons ^ source_device->button_state; /* Gdk buttons are numbered 1.. */ event->button.button = 1; for (button_mask = 1; button_mask != 0x80000000; button_mask <<= 1, event->button.button++) { if (button_diff & button_mask) { /* Found a button that has changed state */ break; } } if (!(translated_buttons & button_mask)) { event->any.type = GDK_BUTTON_RELEASE; masktest = GDK_BUTTON_RELEASE_MASK; } else { event->any.type = GDK_BUTTON_PRESS; masktest = GDK_BUTTON_PRESS_MASK; } source_device->button_state ^= button_mask; } else { event->any.type = GDK_MOTION_NOTIFY; masktest = GDK_POINTER_MOTION_MASK; if (source_device->button_state & (1 << 0)) masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK; if (source_device->button_state & (1 << 1)) masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK; if (source_device->button_state & (1 << 2)) masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK; } /* Now we can check if the window wants the event, and * propagate if necessary. */ while ((gdk_window_get_device_events (window, GDK_DEVICE (source_device)) & masktest) == 0 && (gdk_device_get_device_type (GDK_DEVICE (source_device)) == GDK_DEVICE_TYPE_SLAVE && (gdk_window_get_events (window) & masktest) == 0)) { GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n")); if (window->parent == gdk_get_default_root_window () || window->parent == NULL) return FALSE; pt.x = x; pt.y = y; ClientToScreen (GDK_WINDOW_HWND (window), &pt); g_object_unref (window); window = window->parent; g_object_ref (window); ScreenToClient (GDK_WINDOW_HWND (window), &pt); x = pt.x; y = pt.y; GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n", GDK_WINDOW_HWND (window), x, y)); } event->any.window = window; key_state = get_modifier_key_state (); if (event->any.type == GDK_BUTTON_PRESS || event->any.type == GDK_BUTTON_RELEASE) { event->button.time = _gdk_win32_get_next_tick (msg->time); if (source_device->sends_core) gdk_event_set_device (event, device_manager->core_pointer); gdk_event_set_source_device (event, GDK_DEVICE (source_device)); gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer)); event->button.axes = g_new (gdouble, num_axes); gdk_window_get_origin (window, &root_x, &root_y); _gdk_device_wintab_translate_axes (source_device, window, event->button.axes, &event->button.x, &event->button.y); event->button.x_root = event->button.x + root_x; event->button.y_root = event->button.y + root_y; event->button.state = key_state | ((source_device->button_state << 8) & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)); GDK_NOTE (EVENTS_OR_INPUT, g_print ("WINTAB button %s:%d %g,%g\n", (event->button.type == GDK_BUTTON_PRESS ? "press" : "release"), event->button.button, event->button.x, event->button.y)); } else { event->motion.time = _gdk_win32_get_next_tick (msg->time); event->motion.is_hint = FALSE; gdk_event_set_device (event, device_manager->core_pointer); gdk_event_set_source_device (event, GDK_DEVICE (source_device)); gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer)); event->motion.axes = g_new (gdouble, num_axes); gdk_window_get_origin (window, &root_x, &root_y); _gdk_device_wintab_translate_axes (source_device, window, event->motion.axes, &event->motion.x, &event->motion.y); event->motion.x_root = event->motion.x + root_x; event->motion.y_root = event->motion.y + root_y; event->motion.state = key_state | ((source_device->button_state << 8) & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)); GDK_NOTE (EVENTS_OR_INPUT, g_print ("WINTAB motion: %g,%g\n", event->motion.x, event->motion.y)); } return TRUE; case WT_CSRCHANGE: if ((source_device = gdk_device_manager_find_wintab_device (device_manager, (HCTX) msg->lParam, packet.pkCursor)) == NULL) return FALSE; if (gdk_device_get_mode (GDK_DEVICE (source_device)) == GDK_MODE_DISABLED) return FALSE; if (source_device->sends_core) { _gdk_device_virtual_set_active (device_manager->core_pointer, GDK_DEVICE (source_device)); _gdk_input_ignore_core = TRUE; } return FALSE; case WT_PROXIMITY: if (LOWORD (msg->lParam) == 0) { _gdk_input_ignore_core = FALSE; _gdk_device_virtual_set_active (device_manager->core_pointer, device_manager->system_pointer); } return FALSE; } return FALSE; }
void acquire_grab (GromitData *data, GdkDevice *dev) { show_window (data); if(!dev) /* this means grab all */ { GHashTableIter it; gpointer value; GromitDeviceData* devdata = NULL; g_hash_table_iter_init (&it, data->devdatatable); while (g_hash_table_iter_next (&it, NULL, &value)) { GdkCursor *cursor; devdata = value; if(devdata->is_grabbed || gdk_device_get_device_type(devdata->device) == GDK_DEVICE_TYPE_SLAVE) continue; if(devdata->cur_context && devdata->cur_context->type == GROMIT_ERASER) cursor = data->erase_cursor; else cursor = data->paint_cursor; if(gdk_device_grab(devdata->device, gtk_widget_get_window(data->win), GDK_OWNERSHIP_NONE, FALSE, GROMIT_MOUSE_EVENTS, cursor, GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS) { /* this probably means the device table is outdated, e.g. this device doesn't exist anymore */ g_printerr("Error grabbing Device '%s' while grabbing all, ignoring.\n", gdk_device_get_name(devdata->device)); continue; } devdata->is_grabbed = 1; } data->all_grabbed = 1; if(data->debug) g_printerr("DEBUG: Grabbed all Devices.\n"); return; } GromitDeviceData *devdata = g_hash_table_lookup(data->devdatatable, dev); if (!devdata->is_grabbed) { GdkCursor *cursor; if(devdata->cur_context && devdata->cur_context->type == GROMIT_ERASER) cursor = data->erase_cursor; else cursor = data->paint_cursor; if(gdk_device_grab(devdata->device, gtk_widget_get_window(data->win), GDK_OWNERSHIP_NONE, FALSE, GROMIT_MOUSE_EVENTS, cursor, GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS) { /* this probably means the device table is outdated, e.g. this device doesn't exist anymore */ g_printerr("Error grabbing device '%s', rescanning device list.\n", gdk_device_get_name(devdata->device)); setup_input_devices(data); return; } devdata->is_grabbed = 1; if(data->debug) g_printerr("DEBUG: Grabbed Device '%s'.\n", gdk_device_get_name(devdata->device)); } }
void setup_input_devices (GromitData *data) { /* ungrab all */ release_grab (data, NULL); /* and clear our own device data list */ GHashTableIter it; gpointer value; g_hash_table_iter_init (&it, data->devdatatable); while (g_hash_table_iter_next (&it, NULL, &value)) g_free(value); g_hash_table_remove_all(data->devdatatable); /* get devices */ GdkDeviceManager *device_manager = gdk_display_get_device_manager(data->display); GList *devices, *d; int i = 0; devices = g_list_concat(gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER), gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE)); for(d = devices; d; d = d->next) { GdkDevice *device = (GdkDevice *) d->data; /* only enable devices with 2 ore more axes */ if (gdk_device_get_source(device) != GDK_SOURCE_KEYBOARD && gdk_device_get_n_axes(device) >= 2) { gdk_device_set_mode (device, GDK_MODE_SCREEN); GromitDeviceData *devdata; devdata = g_malloc0(sizeof (GromitDeviceData)); devdata->device = device; devdata->index = i; /* get attached keyboard and grab the hotkey */ if (!data->hot_keycode) { g_printerr("ERROR: Grabbing hotkey from attached keyboard " "of '%s' failed, no hotkey defined.\n", gdk_device_get_name(device)); g_free(devdata); continue; } /* if this is a slave device, we need the master */ GdkDevice *kdevice=device; if(gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_SLAVE) kdevice=gdk_device_get_associated_device (device); gint dev_id = -1; g_object_get(kdevice, "device-id", &dev_id, NULL); gint kbd_dev_id = -1; XIDeviceInfo* devinfo; int devicecount = 0; devinfo = XIQueryDevice(GDK_DISPLAY_XDISPLAY(data->display), dev_id, &devicecount); if(devicecount) kbd_dev_id = devinfo->attachment; XIFreeDeviceInfo(devinfo); if(kbd_dev_id != -1) { if(data->debug) g_printerr("DEBUG: Grabbing hotkey from keyboard '%d' .\n", kbd_dev_id); XIEventMask mask; unsigned char bits[4] = {0,0,0,0}; mask.mask = bits; mask.mask_len = sizeof(bits); XISetMask(bits, XI_KeyPress); XISetMask(bits, XI_KeyRelease); XIGrabModifiers modifiers[] = {{XIAnyModifier, 0}}; int nmods = 1; gdk_error_trap_push (); XIGrabKeycode( GDK_DISPLAY_XDISPLAY(data->display), kbd_dev_id, data->hot_keycode, GDK_WINDOW_XID(data->root), GrabModeAsync, GrabModeAsync, True, &mask, nmods, modifiers); XSync(GDK_DISPLAY_XDISPLAY(data->display), False); if(gdk_error_trap_pop()) { g_printerr("ERROR: Grabbing hotkey from keyboard device %d failed.\n", kbd_dev_id); g_free(devdata); continue; } } g_hash_table_insert(data->devdatatable, device, devdata); g_printerr ("Enabled Device %d: \"%s\", (Type: %d)\n", i++, gdk_device_get_name(device), gdk_device_get_source(device)); } } g_printerr ("Now %d enabled devices.\n", g_hash_table_size(data->devdatatable)); }