[gtk+] GDK W32: Handle drivers that do not send WT_CSRCHANGE after WT_PROXIMITY
- From: Руслан Ижбулатов <ruslanizhb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] GDK W32: Handle drivers that do not send WT_CSRCHANGE after WT_PROXIMITY
- Date: Sat, 2 Dec 2017 11:23:47 +0000 (UTC)
commit d7e2017c289f69f52632661170e34786bbd08d7e
Author: Руслан Ижбулатов <lrn1986 gmail com>
Date: Fri Feb 10 10:49:00 2017 +0000
GDK W32: Handle drivers that do not send WT_CSRCHANGE after WT_PROXIMITY
Some drivers don't do that (not sure whether that is the correct behaviour
or not). Remember each WT_PROXIMITY with LOWORD(lParam) != 0 that we get,
then look for a WT_CSRCHANGE. If WT_CSRCHANGE doesn't come, but a WT_PACKET
does, assume that this device is the one that sent WT_PROXIMITY.
Also include fallback code to ensure that WT_PACKETs for an enabled device
disable the system pointer, because WT_PROXIMITY handler might have
enabled it by mistake, since it's not possible to know which device left
the proximity (it might have been a disabled device).
https://bugzilla.gnome.org/show_bug.cgi?id=778328
gdk/win32/gdkdevicemanager-win32.c | 93 ++++++++++++++++++++++++++++--------
gdk/win32/gdkdevicemanager-win32.h | 6 ++
gdk/win32/gdkdisplay-win32.c | 2 +-
gdk/win32/gdkevents-win32.c | 4 +-
gdk/win32/gdkglobals-win32.c | 2 +-
gdk/win32/gdkprivate-win32.h | 2 +-
6 files changed, 83 insertions(+), 26 deletions(-)
---
diff --git a/gdk/win32/gdkdevicemanager-win32.c b/gdk/win32/gdkdevicemanager-win32.c
index 18e12e5..9dbf800 100644
--- a/gdk/win32/gdkdevicemanager-win32.c
+++ b/gdk/win32/gdkdevicemanager-win32.c
@@ -923,6 +923,54 @@ gdk_input_other_event (GdkDisplay *display,
switch (msg->message)
{
case WT_PACKET:
+ source_device = gdk_device_manager_find_wintab_device (device_manager,
+ (HCTX) msg->lParam,
+ packet.pkCursor);
+
+ /* Check this first, as we get WT_PROXIMITY for disabled devices too */
+ if (device_manager->dev_entered_proximity > 0)
+ {
+ /* This is the same code as in WT_CSRCHANGE. Some drivers send
+ * WT_CSRCHANGE after each WT_PROXIMITY with LOWORD(lParam) != 0,
+ * this code is for those that don't.
+ */
+ device_manager->dev_entered_proximity -= 1;
+
+ if (source_device != NULL &&
+ source_device->sends_core &&
+ gdk_device_get_mode (GDK_DEVICE (source_device)) != GDK_MODE_DISABLED)
+ {
+ _gdk_device_virtual_set_active (device_manager->core_pointer,
+ GDK_DEVICE (source_device));
+ _gdk_input_ignore_core += 1;
+ }
+ }
+ else if (source_device != NULL &&
+ source_device->sends_core &&
+ gdk_device_get_mode (GDK_DEVICE (source_device)) != GDK_MODE_DISABLED &&
+ _gdk_input_ignore_core == 0)
+ {
+ /* A fallback for cases when two devices (disabled and enabled)
+ * were in proximity simultaneously.
+ * In this case the removal of a disabled device would also
+ * make the system pointer active, as we don't know which
+ * device was removed and assume it was the enabled one.
+ * If we are still getting packets for the enabled device,
+ * it means that the device that was removed was the disabled
+ * device, so we must make the enabled device active again and
+ * start ignoring the core pointer events. In practice this means that
+ * removing a disabled device while an enabled device is still
+ * in proximity might briefly make the core pointer active/visible.
+ */
+ _gdk_device_virtual_set_active (device_manager->core_pointer,
+ GDK_DEVICE (source_device));
+ _gdk_input_ignore_core += 1;
+ }
+
+ if (source_device == NULL ||
+ gdk_device_get_mode (GDK_DEVICE (source_device)) == GDK_MODE_DISABLED)
+ return FALSE;
+
/* Don't produce any button or motion events while a window is being
* moved or resized, see bug #151090.
*/
@@ -932,14 +980,6 @@ gdk_input_other_event (GdkDisplay *display,
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)
@@ -1113,18 +1153,20 @@ gdk_input_other_event (GdkDisplay *display,
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 (device_manager->dev_entered_proximity > 0)
+ device_manager->dev_entered_proximity -= 1;
- if (gdk_device_get_mode (GDK_DEVICE (source_device)) == GDK_MODE_DISABLED)
- return FALSE;
+ if ((source_device = gdk_device_manager_find_wintab_device (device_manager,
+ (HCTX) msg->lParam,
+ packet.pkCursor)) == NULL)
+ return FALSE;
- if (source_device->sends_core)
+ if (source_device->sends_core &&
+ gdk_device_get_mode (GDK_DEVICE (source_device)) != GDK_MODE_DISABLED)
{
- _gdk_device_virtual_set_active (device_manager->core_pointer, GDK_DEVICE (source_device));
- _gdk_input_ignore_core = TRUE;
+ _gdk_device_virtual_set_active (device_manager->core_pointer,
+ GDK_DEVICE (source_device));
+ _gdk_input_ignore_core += 1;
}
return FALSE;
@@ -1132,10 +1174,19 @@ gdk_input_other_event (GdkDisplay *display,
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);
- }
+ if (_gdk_input_ignore_core > 0)
+ {
+ _gdk_input_ignore_core -= 1;
+
+ if (_gdk_input_ignore_core == 0)
+ _gdk_device_virtual_set_active (device_manager->core_pointer,
+ device_manager->system_pointer);
+ }
+ }
+ else
+ {
+ device_manager->dev_entered_proximity += 1;
+ }
return FALSE;
}
diff --git a/gdk/win32/gdkdevicemanager-win32.h b/gdk/win32/gdkdevicemanager-win32.h
index ab82bba..8f71335 100644
--- a/gdk/win32/gdkdevicemanager-win32.h
+++ b/gdk/win32/gdkdevicemanager-win32.h
@@ -41,6 +41,12 @@ struct _GdkDeviceManagerWin32
GdkDevice *system_pointer;
GdkDevice *system_keyboard;
GList *wintab_devices;
+
+ /* Bumped up every time a wintab device enters the proximity
+ * of our context (WT_PROXIMITY). Bumped down when we either
+ * receive a WT_PACKET, or a WT_CSRCHANGE.
+ */
+ gint dev_entered_proximity;
};
struct _GdkDeviceManagerWin32Class
diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c
index a4b40da..4441308 100644
--- a/gdk/win32/gdkdisplay-win32.c
+++ b/gdk/win32/gdkdisplay-win32.c
@@ -408,7 +408,7 @@ _gdk_win32_display_open (const gchar *display_name)
_gdk_events_init (_gdk_display);
- _gdk_input_ignore_core = FALSE;
+ _gdk_input_ignore_core = 0;
_gdk_device_manager = g_object_new (GDK_TYPE_DEVICE_MANAGER_WIN32,
NULL);
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 1cba4c4..e850eed 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -1872,7 +1872,7 @@ generate_button_event (GdkEventType type,
GdkDeviceManagerWin32 *device_manager;
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
- if (_gdk_input_ignore_core)
+ if (_gdk_input_ignore_core > 0)
return;
device_manager = GDK_DEVICE_MANAGER_WIN32 (_gdk_device_manager);
@@ -2932,7 +2932,7 @@ gdk_event_translate (MSG *msg,
{
gdk_win32_window_do_move_resize_drag (window, current_root_x, current_root_y);
}
- else if (!_gdk_input_ignore_core)
+ else if (_gdk_input_ignore_core == 0)
{
event = gdk_event_new (GDK_MOTION_NOTIFY);
event->motion.window = window;
diff --git a/gdk/win32/gdkglobals-win32.c b/gdk/win32/gdkglobals-win32.c
index 0af85d6..35cc221 100644
--- a/gdk/win32/gdkglobals-win32.c
+++ b/gdk/win32/gdkglobals-win32.c
@@ -36,7 +36,7 @@ HDC _gdk_display_hdc;
HINSTANCE _gdk_dll_hinstance;
HINSTANCE _gdk_app_hmodule;
-gboolean _gdk_input_ignore_core;
+gint _gdk_input_ignore_core;
HKL _gdk_input_locale;
gboolean _gdk_input_locale_is_ime;
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index ccfc601..6834562 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -273,7 +273,7 @@ extern HDC _gdk_display_hdc;
extern HINSTANCE _gdk_dll_hinstance;
extern HINSTANCE _gdk_app_hmodule;
-extern gboolean _gdk_input_ignore_core;
+extern gint _gdk_input_ignore_core;
/* These are thread specific, but GDK/win32 works OK only when invoked
* from a single thread anyway.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]