void gdk_input_set_extension_events (GdkWindow *window, gint mask, GdkExtensionMode mode) { GdkDeviceManager *device_manager; GList *devices, *d; g_return_if_fail (GDK_IS_WINDOW (window)); if (GDK_WINDOW_DESTROYED (window)) return; if (mode == GDK_EXTENSION_EVENTS_NONE) mask = 0; window->extension_events = mask; device_manager = gdk_display_get_device_manager (_gdk_display); devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING); for (d = devices; d; d = d->next) { GdkDevice *dev; gint dev_mask; dev = d->data; dev_mask = mask; if (gdk_device_get_mode (dev) == GDK_MODE_DISABLED || (!gdk_device_get_has_cursor (dev) && mode == GDK_EXTENSION_EVENTS_CURSOR)) dev_mask = 0; gdk_window_set_device_events (window, dev, mask); } g_list_free (devices); }
gboolean _gdk_input_other_event (GdkEvent *event, MSG *msg, GdkWindow *window) { GdkDisplay *display; GdkDeviceWintab *device = NULL; GdkDeviceGrabInfo *last_grab; GdkEventMask masktest; guint key_state; POINT pt; PACKET packet; gdouble 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; } window = gdk_window_at_pointer (&x, &y); if (window == NULL) window = _gdk_root; g_object_ref (window); display = gdk_window_get_display (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) { 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 ((device = _gdk_device_manager_find_wintab_device ((HCTX) msg->lParam, packet.pkCursor)) == NULL) return FALSE; if (gdk_device_get_mode (GDK_DEVICE (device)) == GDK_MODE_DISABLED) return FALSE; last_grab = _gdk_display_get_last_device_grab (_gdk_display, GDK_DEVICE (device)); if (last_grab && last_grab->window) { g_object_unref (window); window = g_object_ref (last_grab->window); } if (window == _gdk_root) { GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n")); return FALSE; } num_axes = 0; if (device->pktdata & PK_X) device->last_axis_data[num_axes++] = packet.pkX; if (device->pktdata & PK_Y) device->last_axis_data[num_axes++] = packet.pkY; if (device->pktdata & PK_NORMAL_PRESSURE) device->last_axis_data[num_axes++] = packet.pkNormalPressure; if (device->pktdata & PK_ORIENTATION) { decode_tilt (device->last_axis_data + num_axes, device->orientation_axes, &packet); num_axes += 2; } translated_buttons = button_map[packet.pkButtons & 0x07] | (packet.pkButtons & ~0x07); if (translated_buttons != 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 ^ 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; } device->button_state ^= button_mask; } else { event->any.type = GDK_MOTION_NOTIFY; masktest = GDK_POINTER_MOTION_MASK; if (device->button_state & (1 << 0)) masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK; if (device->button_state & (1 << 1)) masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK; if (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 (device)) == 0) { GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n")); if (window->parent == GDK_WINDOW (_gdk_root)) return FALSE; /* It is not good to propagate the extended events up to the parent * if this window wants normal (not extended) motion/button events */ if (window->event_mask & masktest) { GDK_NOTE (EVENTS_OR_INPUT, g_print ("... wants ordinary event, ignoring this\n")); 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)); } if (gdk_window_get_device_events (window, GDK_DEVICE (device)) == 0) return FALSE; 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); gdk_event_set_device (event, GDK_DEVICE (device)); event->button.axes = g_new (gdouble, num_axes); _gdk_device_wintab_get_window_coords (window, &root_x, &root_y); _gdk_device_wintab_translate_axes (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 | ((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, GDK_DEVICE (device)); event->motion.axes = g_new (gdouble, num_axes); _gdk_device_wintab_get_window_coords (window, &root_x, &root_y); _gdk_device_wintab_translate_axes (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 | ((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_PROXIMITY: if (LOWORD (msg->lParam) == 0) { event->proximity.type = GDK_PROXIMITY_OUT; set_ignore_core (FALSE); } else { event->proximity.type = GDK_PROXIMITY_IN; set_ignore_core (TRUE); } event->proximity.time = _gdk_win32_get_next_tick (msg->time); gdk_event_set_device (event, GDK_DEVICE (device)); GDK_NOTE (EVENTS_OR_INPUT, g_print ("WINTAB proximity %s\n", (event->proximity.type == GDK_PROXIMITY_IN ? "in" : "out"))); return TRUE; } return FALSE; }
void _gdk_device_wintab_translate_axes (GdkDeviceWintab *device_wintab, GdkSurface *window, gdouble *axes, gdouble *x, gdouble *y) { GdkDevice *device; GdkSurface *impl_surface; gint root_x, root_y; gdouble temp_x, temp_y; gint i; device = GDK_DEVICE (device_wintab); impl_surface = _gdk_surface_get_impl_surface (window); temp_x = temp_y = 0; gdk_surface_get_origin (impl_surface, &root_x, &root_y); for (i = 0; i < gdk_device_get_n_axes (device); i++) { GdkAxisUse use; use = gdk_device_get_axis_use (device, i); switch (use) { case GDK_AXIS_X: case GDK_AXIS_Y: if (gdk_device_get_mode (device) == GDK_MODE_SURFACE) _gdk_device_translate_surface_coord (device, window, i, device_wintab->last_axis_data[i], &axes[i]); else { HMONITOR hmonitor; MONITORINFO minfo = {sizeof (MONITORINFO),}; hmonitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST); GetMonitorInfo (hmonitor, &minfo); /* XXX: the dimensions from minfo may need to be scaled for HiDPI usage */ _gdk_device_translate_screen_coord (device, window, root_x, root_y, minfo.rcWork.right - minfo.rcWork.left, minfo.rcWork.bottom - minfo.rcWork.top, i, device_wintab->last_axis_data[i], &axes[i]); } if (use == GDK_AXIS_X) temp_x = axes[i]; else if (use == GDK_AXIS_Y) temp_y = axes[i]; break; default: _gdk_device_translate_axis (device, i, device_wintab->last_axis_data[i], &axes[i]); break; } } if (x) *x = temp_x; if (y) *y = temp_y; }