forked from AuroraMiddleware/gtk
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
This commit is contained in:
parent
3c9b667d3e
commit
d7e2017c28
@ -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 (device_manager->dev_entered_proximity > 0)
|
||||
device_manager->dev_entered_proximity -= 1;
|
||||
|
||||
if ((source_device = gdk_device_manager_find_wintab_device (device_manager,
|
||||
(HCTX) msg->lParam,
|
||||
packet.pkCursor)) == NULL)
|
||||
return FALSE;
|
||||
(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)
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user