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; }
/* * maybe this should be integrated with the default message loop - or maybe not ;-) */ static LRESULT CALLBACK inner_clipboard_window_procedure (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { switch (message) { case WM_DESTROY: /* remove us from chain */ { ChangeClipboardChain (hwnd, _hwnd_next_viewer); PostQuitMessage (0); return 0; } case WM_CHANGECBCHAIN: { HWND hwndRemove = (HWND) wparam; /* handle of window being removed */ HWND hwndNext = (HWND) lparam; /* handle of next window in chain */ if (hwndRemove == _hwnd_next_viewer) _hwnd_next_viewer = hwndNext == hwnd ? NULL : hwndNext; else if (_hwnd_next_viewer != NULL) return SendMessage (_hwnd_next_viewer, message, wparam, lparam); return 0; } case WM_CLIPBOARDUPDATE: case WM_DRAWCLIPBOARD: { int success; HWND hwndOwner; #ifdef G_ENABLE_DEBUG UINT nFormat = 0; #endif GdkEvent *event; GdkWindow *owner; success = OpenClipboard (hwnd); if (!success) { g_warning ("Failed to OpenClipboard on window handle %p", hwnd); return 0; } hwndOwner = GetClipboardOwner (); owner = gdk_win32_window_lookup_for_display (_gdk_display, hwndOwner); if (owner == NULL) owner = gdk_win32_window_foreign_new_for_display (_gdk_display, hwndOwner); GDK_NOTE (DND, g_print (" drawclipboard owner: %p", hwndOwner)); #ifdef G_ENABLE_DEBUG if (_gdk_debug_flags & GDK_DEBUG_DND) { while ((nFormat = EnumClipboardFormats (nFormat)) != 0) g_print ("%s ", _gdk_win32_cf_to_string (nFormat)); } #endif GDK_NOTE (DND, g_print (" \n")); event = gdk_event_new (GDK_OWNER_CHANGE); event->owner_change.window = gdk_get_default_root_window (); event->owner_change.owner = owner; event->owner_change.reason = GDK_OWNER_CHANGE_NEW_OWNER; event->owner_change.selection = GDK_SELECTION_CLIPBOARD; event->owner_change.time = _gdk_win32_get_next_tick (0); event->owner_change.selection_time = GDK_CURRENT_TIME; _gdk_win32_append_event (event); CloseClipboard (); if (_hwnd_next_viewer != NULL) return SendMessage (_hwnd_next_viewer, message, wparam, lparam); /* clear error to avoid confusing SetClipboardViewer() return */ SetLastError (0); return 0; } default: /* Otherwise call DefWindowProcW(). */ GDK_NOTE (EVENTS, g_print (" DefWindowProcW")); return DefWindowProc (hwnd, message, wparam, lparam); } }