win32: Make WINTAB support work

Lots of rework to make input events work in the csw world
This commit is contained in:
Alexander Larsson 2011-10-31 08:15:34 +01:00
parent 2cd09a6653
commit 8f6f64fe10
10 changed files with 409 additions and 503 deletions

View File

@ -672,6 +672,7 @@ gboolean _gdk_window_has_impl (GdkWindow *window);
GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
GdkWindow *_gdk_window_get_input_window_for_event (GdkWindow *native_window,
GdkEventType event_type,
GdkModifierType mask,
int x, int y,
gulong serial);
GdkRegion *_gdk_region_new_from_yxbanded_rects (GdkRectangle *rects, int n_rects);

View File

@ -11100,6 +11100,7 @@ static GdkWindow *
get_extension_event_window (GdkDisplay *display,
GdkWindow *pointer_window,
GdkEventType type,
GdkModifierType mask,
gulong serial)
{
guint evmask;
@ -11112,6 +11113,7 @@ get_extension_event_window (GdkDisplay *display,
if (grab != NULL && !grab->owner_events)
{
evmask = grab->event_mask;
evmask = update_evmask_for_button_motion (evmask, mask);
grab_window = grab->window;
@ -11125,6 +11127,7 @@ get_extension_event_window (GdkDisplay *display,
while (w != NULL)
{
evmask = w->extension_events;
evmask = update_evmask_for_button_motion (evmask, mask);
if (evmask & type_masks[type])
return (GdkWindow *)w;
@ -11136,6 +11139,7 @@ get_extension_event_window (GdkDisplay *display,
grab->owner_events)
{
evmask = grab->event_mask;
evmask = update_evmask_for_button_motion (evmask, mask);
if (evmask & type_masks[type])
return grab->window;
@ -11150,6 +11154,7 @@ get_extension_event_window (GdkDisplay *display,
GdkWindow *
_gdk_window_get_input_window_for_event (GdkWindow *native_window,
GdkEventType event_type,
GdkModifierType mask,
int x, int y,
gulong serial)
{
@ -11171,6 +11176,7 @@ _gdk_window_get_input_window_for_event (GdkWindow *native_window,
event_win = get_extension_event_window (display,
pointer_window,
event_type,
mask,
serial);
return event_win;

View File

@ -515,6 +515,9 @@ gdk_display_pointer_ungrab (GdkDisplay *display,
info->serial_end = 0;
ReleaseCapture ();
}
_gdk_input_ungrab_pointer (time);
/* TODO_CSW: cursor, confines, etc */
_gdk_display_pointer_grab_update (display, 0);
@ -1242,10 +1245,11 @@ send_crossing_event (GdkDisplay *display,
event->crossing.state = mask;
_gdk_win32_append_event (event);
if (type == GDK_ENTER_NOTIFY &&
((GdkWindowObject *) window)->extension_events != 0)
_gdk_input_enter_event ((GdkWindow *)window);
/*
if (((GdkWindowObject *) window)->extension_events != 0)
_gdk_input_crossing_event ((GdkWindow *)window, type == GDK_ENTER_NOTIFY);
*/
}
static GdkWindowObject *
@ -1526,8 +1530,7 @@ propagate (GdkWindow **window,
gboolean grab_owner_events,
gint grab_mask,
gboolean (*doesnt_want_it) (gint mask,
MSG *msg),
gboolean check_extended)
MSG *msg))
{
if (grab_window != NULL && !grab_owner_events)
{
@ -1536,13 +1539,6 @@ propagate (GdkWindow **window,
/* See if the event should be ignored because an extended input
* device is used
*/
if (check_extended &&
((GdkWindowObject *) grab_window)->extension_events != 0 &&
_gdk_input_ignore_core)
{
GDK_NOTE (EVENTS, g_print (" (ignored for grabber)"));
return FALSE;
}
if ((*doesnt_want_it) (grab_mask, msg))
{
GDK_NOTE (EVENTS, g_print (" (grabber doesn't want it)"));
@ -1561,13 +1557,6 @@ propagate (GdkWindow **window,
*/
while (TRUE)
{
if (check_extended &&
((GdkWindowObject *) *window)->extension_events != 0 &&
_gdk_input_ignore_core)
{
GDK_NOTE (EVENTS, g_print (" (ignored)"));
return FALSE;
}
if ((*doesnt_want_it) (((GdkWindowObject *) *window)->event_mask, msg))
{
/* Owner doesn't want it, propagate to parent. */
@ -1579,13 +1568,6 @@ propagate (GdkWindow **window,
{
/* Event source is grabbed with owner_events TRUE */
if (check_extended &&
((GdkWindowObject *) grab_window)->extension_events != 0 &&
_gdk_input_ignore_core)
{
GDK_NOTE (EVENTS, g_print (" (ignored for grabber)"));
return FALSE;
}
if ((*doesnt_want_it) (grab_mask, msg))
{
/* Grabber doesn't want it either */
@ -2267,7 +2249,7 @@ gdk_event_translate (MSG *msg,
_gdk_display->keyboard_grab.window,
_gdk_display->keyboard_grab.owner_events,
GDK_ALL_EVENTS_MASK,
doesnt_want_key, FALSE))
doesnt_want_key))
break;
if (GDK_WINDOW_DESTROYED (window))
@ -2375,7 +2357,7 @@ gdk_event_translate (MSG *msg,
_gdk_display->keyboard_grab.window,
_gdk_display->keyboard_grab.owner_events,
GDK_ALL_EVENTS_MASK,
doesnt_want_char, FALSE))
doesnt_want_char))
break;
if (GDK_WINDOW_DESTROYED (window))
@ -2439,7 +2421,7 @@ gdk_event_translate (MSG *msg,
GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
assign_object (&window, find_window_for_mouse_event (window, msg));
/* TODO_CSW?: there used to some synthesize and propagate */
if (GDK_WINDOW_DESTROYED (window))
break;
@ -2479,15 +2461,6 @@ gdk_event_translate (MSG *msg,
GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
assign_object (&window, find_window_for_mouse_event (window, msg));
#if 0
if (((GdkWindowObject *) window)->extension_events != 0 &&
_gdk_input_ignore_core)
{
GDK_NOTE (EVENTS, g_print (" (ignored)"));
break;
}
#endif
grab = _gdk_display_get_last_pointer_grab (_gdk_display);
if (grab != NULL && grab->implicit)
{
@ -2987,7 +2960,7 @@ gdk_event_translate (MSG *msg,
!GDK_WINDOW_DESTROYED (window))
_gdk_win32_emit_configure_event (window);
if (((GdkWindowObject *) window)->extension_events != 0)
if (((GdkWindowObject *) window)->input_window != NULL)
_gdk_input_configure_event (window);
}
@ -3483,8 +3456,7 @@ gdk_event_translate (MSG *msg,
wintab:
event = gdk_event_new (GDK_NOTHING);
event->any.window = window;
g_object_ref (window);
event->any.window = NULL;
if (_gdk_input_other_event (event, msg, window))
_gdk_win32_append_event (event);

View File

@ -58,16 +58,14 @@ static GList *wintab_contexts = NULL;
static GdkWindow *wintab_window = NULL;
static GdkWindow *x_grab_window = NULL; /* Window that currently holds
* the extended inputs grab
*/
static GdkEventMask x_grab_mask;
static gboolean x_grab_owner_events;
static GdkDevicePrivate *_gdk_device_in_proximity;
typedef UINT (WINAPI *t_WTInfoA) (UINT a, UINT b, LPVOID c);
typedef UINT (WINAPI *t_WTInfoW) (UINT a, UINT b, LPVOID c);
typedef BOOL (WINAPI *t_WTEnable) (HCTX a, BOOL b);
typedef HCTX (WINAPI *t_WTOpenA) (HWND a, LPLOGCONTEXTA b, BOOL c);
typedef BOOL (WINAPI *t_WTGetA) (HCTX a, LPLOGCONTEXTA b);
typedef BOOL (WINAPI *t_WTSetA) (HCTX a, LPLOGCONTEXTA b);
typedef BOOL (WINAPI *t_WTOverlap) (HCTX a, BOOL b);
typedef BOOL (WINAPI *t_WTPacket) (HCTX a, UINT b, LPVOID c);
typedef int (WINAPI *t_WTQueueSizeSet) (HCTX a, int b);
@ -76,6 +74,8 @@ static t_WTInfoA p_WTInfoA;
static t_WTInfoW p_WTInfoW;
static t_WTEnable p_WTEnable;
static t_WTOpenA p_WTOpenA;
static t_WTGetA p_WTGetA;
static t_WTSetA p_WTSetA;
static t_WTOverlap p_WTOverlap;
static t_WTPacket p_WTPacket;
static t_WTQueueSizeSet p_WTQueueSizeSet;
@ -384,6 +384,10 @@ _gdk_input_wintab_init_check (void)
return;
if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL)
return;
if ((p_WTGetA = (t_WTGetA) GetProcAddress (wintab32, "WTGetA")) == NULL)
return;
if ((p_WTSetA = (t_WTSetA) GetProcAddress (wintab32, "WTSetA")) == NULL)
return;
if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL)
return;
if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL)
@ -461,7 +465,7 @@ _gdk_input_wintab_init_check (void)
#if DEBUG_WINTAB
GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc)));
#endif
lc.lcOptions |= CXO_MESSAGES;
lc.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
lc.lcStatus = 0;
lc.lcMsgBase = WT_DEFBASE;
lc.lcPktRate = 0;
@ -471,8 +475,8 @@ _gdk_input_wintab_init_check (void)
lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
lc.lcOutOrgX = axis_x.axMin;
lc.lcOutOrgY = axis_y.axMin;
lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
lc.lcOutExtX = axis_x.axMax - axis_x.axMin + 1;
lc.lcOutExtY = axis_y.axMax - axis_y.axMin + 1;
lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
#if DEBUG_WINTAB
GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
@ -488,9 +492,7 @@ _gdk_input_wintab_init_check (void)
devix, *hctx));
wintab_contexts = g_list_append (wintab_contexts, hctx);
#if 0
(*p_WTEnable) (*hctx, TRUE);
#endif
(*p_WTOverlap) (*hctx, TRUE);
#if DEBUG_WINTAB
@ -502,7 +504,7 @@ _gdk_input_wintab_init_check (void)
* with a smaller queue size.
*/
GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
for (i = 32; i >= 1; i >>= 1)
for (i = 128; i >= 1; i >>= 1)
{
if ((*p_WTQueueSizeSet) (*hctx, i))
{
@ -663,41 +665,44 @@ decode_tilt (gint *axis_data,
static void
gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
GdkInputWindow *input_window,
GdkWindow *window,
gint *axis_data,
gdouble *axis_out,
gdouble *x_out,
gdouble *y_out)
{
GdkWindowObject *priv, *impl_window;
GdkWindowImplWin32 *root_impl;
GdkWindowObject *window_object;
int i;
int x_axis = 0;
int y_axis = 0;
double device_width, device_height;
double device_width, device_height, x_min, y_min;
double x_offset, y_offset, x_scale, y_scale;
window_object = GDK_WINDOW_OBJECT (input_window->window);
priv = (GdkWindowObject *) window;
impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
for (i=0; i<gdkdev->info.num_axes; i++)
{
switch (gdkdev->info.axes[i].use)
{
case GDK_AXIS_X:
x_axis = i;
break;
case GDK_AXIS_Y:
y_axis = i;
break;
default:
break;
}
{
case GDK_AXIS_X:
x_axis = i;
break;
case GDK_AXIS_Y:
y_axis = i;
break;
default:
break;
}
}
device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
x_min = gdkdev->axes[x_axis].min_value;
device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
y_min = gdkdev->axes[y_axis].min_value;
if (gdkdev->info.mode == GDK_MODE_SCREEN)
{
@ -705,56 +710,56 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
x_scale = GDK_WINDOW_OBJECT (_gdk_root)->width / device_width;
y_scale = GDK_WINDOW_OBJECT (_gdk_root)->height / device_height;
x_offset = - input_window->root_x;
y_offset = - input_window->root_y;
x_offset = - impl_window->input_window->root_x - priv->abs_x;
y_offset = - impl_window->input_window->root_y - priv->abs_y;
}
else /* GDK_MODE_WINDOW */
{
double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
(device_width*gdkdev->axes[x_axis].resolution);
double x_resolution = gdkdev->axes[x_axis].resolution;
double y_resolution = gdkdev->axes[y_axis].resolution;
double device_aspect = (device_height*y_resolution) / (device_width * x_resolution);
if (device_aspect * window_object->width >= window_object->height)
{
/* device taller than window */
x_scale = window_object->width / device_width;
y_scale = (x_scale * gdkdev->axes[x_axis].resolution) / gdkdev->axes[y_axis].resolution;
if (device_aspect * priv->width >= priv->height)
{
/* device taller than window */
x_scale = priv->width / device_width;
y_scale = (x_scale * x_resolution) / y_resolution;
x_offset = 0;
y_offset = -(device_height * y_scale - window_object->height) / 2;
}
x_offset = 0;
y_offset = -(device_height * y_scale - priv->height) / 2;
}
else
{
/* window taller than device */
y_scale = window_object->height / device_height;
x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
/ gdkdev->axes[x_axis].resolution;
{
/* window taller than device */
y_scale = priv->height / device_height;
x_scale = (y_scale * y_resolution) / x_resolution;
y_offset = 0;
x_offset = - (device_width * x_scale - window_object->width) / 2;
}
y_offset = 0;
x_offset = - (device_width * x_scale - priv->width) / 2;
}
}
for (i = 0; i < gdkdev->info.num_axes; i++)
{
switch (gdkdev->info.axes[i].use)
{
case GDK_AXIS_X:
axis_out[i] = x_offset + x_scale * axis_data[x_axis];
if (x_out)
*x_out = axis_out[i];
break;
case GDK_AXIS_Y:
axis_out[i] = y_offset + y_scale * axis_data[y_axis];
if (y_out)
*y_out = axis_out[i];
break;
default:
axis_out[i] =
(gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
(gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
break;
}
{
case GDK_AXIS_X:
axis_out[i] = x_offset + x_scale * axis_data[x_axis];
if (x_out)
*x_out = axis_out[i];
break;
case GDK_AXIS_Y:
axis_out[i] = y_offset + y_scale * axis_data[y_axis];
if (y_out)
*y_out = axis_out[i];
break;
default:
axis_out[i] =
(gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
(gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
break;
}
}
}
@ -763,25 +768,30 @@ gdk_input_get_root_relative_geometry (HWND w,
int *x_ret,
int *y_ret)
{
RECT rect;
POINT pt;
GetWindowRect (w, &rect);
pt.x = 0;
pt.y = 0;
ClientToScreen (w, &pt);
if (x_ret)
*x_ret = rect.left + _gdk_offset_x;
*x_ret = pt.x + _gdk_offset_x;
if (y_ret)
*y_ret = rect.top + _gdk_offset_y;
*y_ret = pt.y + _gdk_offset_y;
}
void
_gdk_input_configure_event (GdkWindow *window)
{
GdkInputWindow *input_window;
GdkWindowObject *impl_window;
int root_x, root_y;
input_window = _gdk_input_window_find (window);
g_return_if_fail (window != NULL);
impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
input_window = impl_window->input_window;
gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window),
&root_x, &root_y);
@ -789,21 +799,6 @@ _gdk_input_configure_event (GdkWindow *window)
input_window->root_y = root_y;
}
void
_gdk_input_enter_event (GdkWindow *window)
{
GdkInputWindow *input_window;
int root_x, root_y;
input_window = _gdk_input_window_find (window);
g_return_if_fail (window != NULL);
gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y);
input_window->root_x = root_x;
input_window->root_y = root_y;
}
/*
* Get the currently active keyboard modifiers (ignoring the mouse buttons)
* We could use gdk_window_get_pointer but that function does a lot of other
@ -829,6 +824,7 @@ get_modifier_key_state (void)
return state;
}
#if 0
static guint ignore_core_timer = 0;
static gboolean
@ -867,18 +863,78 @@ set_ignore_core (gboolean ignore)
ignore_core_timefunc, NULL);
}
#endif
void
_gdk_input_update_for_device_mode (GdkDevicePrivate *gdkdev)
{
LOGCONTEXT lc;
if (gdkdev != _gdk_device_in_proximity)
return;
if (p_WTGetA (gdkdev->hctx, &lc))
{
if (gdkdev->info.mode == GDK_MODE_SCREEN &&
(lc.lcOptions & CXO_SYSTEM) == 0)
{
lc.lcOptions |= CXO_SYSTEM;
p_WTSetA (gdkdev->hctx, &lc);
}
else if (gdkdev->info.mode == GDK_MODE_WINDOW &&
(lc.lcOptions & CXO_SYSTEM) != 0)
{
lc.lcOptions &= ~CXO_SYSTEM;
p_WTSetA (gdkdev->hctx, &lc);
}
}
}
static GdkWindow *
find_window_for_input_event (MSG* msg, int *x, int *y)
{
POINT pt;
GdkWindow *window;
HWND hwnd;
RECT rect;
pt = msg->pt;
window = NULL;
hwnd = WindowFromPoint (pt);
if (hwnd != NULL)
{
POINT client_pt = pt;
ScreenToClient (hwnd, &client_pt);
GetClientRect (hwnd, &rect);
if (PtInRect (&rect, client_pt))
window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
}
/* need to also adjust the coordinates to the new window */
if (window)
ScreenToClient (GDK_WINDOW_HWND (window), &pt);
*x = pt.x;
*y = pt.y;
if (window)
return window;
return _gdk_root;
}
gboolean
_gdk_input_other_event (GdkEvent *event,
MSG *msg,
GdkWindow *window)
{
GdkDisplay *display;
GdkWindowObject *obj, *grab_obj;
GdkWindowObject *obj, *impl_window;
GdkWindow *native_window;
GdkInputWindow *input_window;
GdkDevicePrivate *gdkdev = NULL;
GdkEventMask masktest;
guint key_state;
POINT pt;
PACKET packet;
gint k;
@ -889,31 +945,24 @@ _gdk_input_other_event (GdkEvent *event,
*/
static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7};
if (event->any.window != wintab_window)
if (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_drawable_get_display (window);
native_window = find_window_for_input_event (msg, &x, &y);
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)
g_print ("_gdk_input_other_event: native_window=%p %+d%+d\n",
GDK_WINDOW_HWND (native_window), x, y));
if (msg->message == WT_PACKET || msg->message == WT_CSRCHANGE)
{
if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet))
return FALSE;
}
obj = GDK_WINDOW_OBJECT (window);
switch (msg->message)
{
case WT_PACKET:
@ -925,11 +974,6 @@ _gdk_input_other_event (GdkEvent *event,
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n"));
return FALSE;
}
if (window == _gdk_root && x_grab_window == NULL)
{
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n"));
return FALSE;
}
if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam,
packet.pkCursor)) == NULL)
@ -979,104 +1023,50 @@ _gdk_input_other_event (GdkEvent *event,
}
if (!(translated_buttons & button_mask))
{
event->any.type = GDK_BUTTON_RELEASE;
masktest = GDK_BUTTON_RELEASE_MASK;
}
event->any.type = GDK_BUTTON_RELEASE;
else
{
event->any.type = GDK_BUTTON_PRESS;
masktest = GDK_BUTTON_PRESS_MASK;
}
event->any.type = GDK_BUTTON_PRESS;
gdkdev->button_state ^= button_mask;
}
else
{
event->any.type = GDK_MOTION_NOTIFY;
masktest = GDK_POINTER_MOTION_MASK;
if (gdkdev->button_state & (1 << 0))
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
if (gdkdev->button_state & (1 << 1))
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
if (gdkdev->button_state & (1 << 2))
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
}
/* See if input is grabbed */
/* FIXME: x_grab_owner_events should probably be handled somehow */
if (x_grab_window != NULL)
{
grab_obj = GDK_WINDOW_OBJECT (x_grab_window);
if (!GDK_WINDOW_IMPL_WIN32 (grab_obj->impl)->extension_events_selected
|| !(grab_obj->extension_events & masktest)
|| !(x_grab_mask && masktest))
{
GDK_NOTE (EVENTS_OR_INPUT,
g_print ("... grabber doesn't want it\n"));
return FALSE;
}
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... to grabber\n"));
if (native_window == _gdk_root)
return FALSE;
g_object_ref(x_grab_window);
g_object_unref(window);
window = x_grab_window;
obj = grab_obj;
}
/* Now we can check if the window wants the event, and
* propagate if necessary.
*/
loop:
if (!GDK_WINDOW_IMPL_WIN32 (obj->impl)->extension_events_selected
|| !(obj->extension_events & masktest))
{
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n"));
window = _gdk_window_get_input_window_for_event (native_window,
event->any.type,
gdkdev->button_state << 8,
x, y, 0);
if (obj->parent == GDK_WINDOW_OBJECT (_gdk_root))
return FALSE;
obj = GDK_WINDOW_OBJECT (window);
/* It is not good to propagate the extended events up to the parent
* if this window wants normal (not extended) motion/button events */
if (obj->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 = (GdkWindow *) obj->parent;
obj = GDK_WINDOW_OBJECT (window);
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));
goto loop;
}
input_window = _gdk_input_window_find (window);
if (window == NULL ||
obj->extension_events == 0)
return FALSE;
impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
input_window = impl_window->input_window;
g_assert (input_window != NULL);
if (gdkdev->info.mode == GDK_MODE_WINDOW
&& input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
if (gdkdev->info.mode == GDK_MODE_WINDOW &&
(obj->extension_events & GDK_ALL_DEVICES_MASK) == 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)
if (event->any.type == GDK_BUTTON_PRESS ||
event->any.type == GDK_BUTTON_RELEASE)
{
event->button.time = _gdk_win32_get_next_tick (msg->time);
event->button.device = &gdkdev->info;
event->button.axes = g_new(gdouble, gdkdev->info.num_axes);
gdk_input_translate_coordinates (gdkdev, input_window,
gdk_input_translate_coordinates (gdkdev, window,
gdkdev->last_axis_data,
event->button.axes,
&event->button.x,
@ -1107,7 +1097,7 @@ _gdk_input_other_event (GdkEvent *event,
event->motion.axes = g_new(gdouble, gdkdev->info.num_axes);
gdk_input_translate_coordinates (gdkdev, input_window,
gdk_input_translate_coordinates (gdkdev, window,
gdkdev->last_axis_data,
event->motion.axes,
&event->motion.x,
@ -1130,49 +1120,104 @@ _gdk_input_other_event (GdkEvent *event,
}
return TRUE;
case WT_PROXIMITY:
if (LOWORD (msg->lParam) == 0)
{
event->proximity.type = GDK_PROXIMITY_OUT;
set_ignore_core (FALSE);
}
else
case WT_CSRCHANGE:
if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam,
packet.pkCursor)) == NULL)
return FALSE;
_gdk_device_in_proximity = gdkdev;
_gdk_input_update_for_device_mode (gdkdev);
window = NULL;
if (native_window != _gdk_root)
window = _gdk_window_get_input_window_for_event (native_window,
GDK_PROXIMITY_IN,
0,
x, y, 0);
if (window)
{
event->proximity.type = GDK_PROXIMITY_IN;
set_ignore_core (TRUE);
event->proximity.window = window;
event->proximity.time = _gdk_win32_get_next_tick (msg->time);
event->proximity.device = &_gdk_device_in_proximity->info;
}
event->proximity.time = _gdk_win32_get_next_tick (msg->time);
event->proximity.device = &gdkdev->info;
GDK_NOTE (EVENTS_OR_INPUT,
g_print ("WINTAB proximity %s\n",
(event->proximity.type == GDK_PROXIMITY_IN ?
"in" : "out")));
g_print ("WINTAB proximity in\n"));
return TRUE;
case WT_PROXIMITY:
/* TODO: Set ignore_core if in input_window */
if (LOWORD (msg->lParam) == 0)
{
_gdk_input_in_proximity = FALSE;
window = NULL;
if (native_window != _gdk_root)
window = _gdk_window_get_input_window_for_event (native_window,
GDK_PROXIMITY_IN,
0,
x, y, 0);
if (window)
{
event->proximity.type = GDK_PROXIMITY_OUT;
event->proximity.window = window;
event->proximity.time = _gdk_win32_get_next_tick (msg->time);
event->proximity.device = &_gdk_device_in_proximity->info;
}
GDK_NOTE (EVENTS_OR_INPUT,
g_print ("WINTAB proximity out\n"));
return TRUE;
}
else
_gdk_input_in_proximity = TRUE;
_gdk_input_check_proximity ();
break;
}
return FALSE;
}
gboolean
_gdk_input_enable_window (GdkWindow *window,
GdkDevicePrivate *gdkdev)
void
_gdk_input_select_events (GdkWindow *impl_window)
{
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
guint event_mask;
GdkWindowObject *w;
GdkInputWindow *iw;
GList *l, *dev_list;
impl->extension_events_selected = TRUE;
iw = ((GdkWindowObject *)impl_window)->input_window;
return TRUE;
}
event_mask = 0;
for (dev_list = _gdk_input_devices; dev_list; dev_list = dev_list->next)
{
GdkDevicePrivate *gdkdev = dev_list->data;
gboolean
_gdk_input_disable_window (GdkWindow *window,
GdkDevicePrivate *gdkdev)
{
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
if (!GDK_IS_CORE (gdkdev) &&
gdkdev->info.mode != GDK_MODE_DISABLED &&
iw != NULL)
{
for (l = iw->windows; l != NULL; l = l->next)
{
w = l->data;
if (gdkdev->info.has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK))
event_mask |= w->extension_events;
}
}
}
event_mask &= ~GDK_ALL_DEVICES_MASK;
if (event_mask)
event_mask |=
GDK_PROXIMITY_OUT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
impl->extension_events_selected = FALSE;
return TRUE;
GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *)impl_window)->impl)->extension_events_mask = event_mask;
}
gint
@ -1182,131 +1227,20 @@ _gdk_input_grab_pointer (GdkWindow *window,
GdkWindow *confine_to,
guint32 time)
{
GdkInputWindow *input_window, *new_window;
gboolean need_ungrab;
GdkDevicePrivate *gdkdev;
GList *tmp_list;
tmp_list = _gdk_input_windows;
new_window = NULL;
need_ungrab = FALSE;
GDK_NOTE (INPUT, g_print ("_gdk_input_grab_pointer: %p %d %p\n",
GDK_WINDOW_HWND (window),
owner_events,
(confine_to ? GDK_WINDOW_HWND (confine_to) : 0)));
while (tmp_list)
{
input_window = (GdkInputWindow *)tmp_list->data;
if (input_window->window == window)
new_window = input_window;
else if (input_window->grabbed)
{
input_window->grabbed = FALSE;
need_ungrab = TRUE;
}
tmp_list = tmp_list->next;
}
if (new_window)
{
new_window->grabbed = TRUE;
x_grab_window = window;
x_grab_mask = event_mask;
x_grab_owner_events = owner_events;
/* FIXME: Do we need to handle confine_to and time? */
tmp_list = _gdk_input_devices;
while (tmp_list)
{
gdkdev = (GdkDevicePrivate *)tmp_list->data;
if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx)
{
#if 0
/* XXX */
gdk_input_common_find_events (window, gdkdev,
event_mask,
event_classes, &num_classes);
result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
GDK_WINDOW_XWINDOW (window),
owner_events, num_classes, event_classes,
GrabModeAsync, GrabModeAsync, time);
/* FIXME: if failure occurs on something other than the first
device, things will be badly inconsistent */
if (result != Success)
return result;
#endif
}
tmp_list = tmp_list->next;
}
}
else
{
x_grab_window = NULL;
#if 0
tmp_list = _gdk_input_devices;
while (tmp_list)
{
gdkdev = (GdkDevicePrivate *)tmp_list->data;
if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx &&
((gdkdev->button_state != 0) || need_ungrab))
{
#if 0
/* XXX */
XUngrabDevice (gdk_display, gdkdev->xdevice, time);
#endif
gdkdev->button_state = 0;
}
tmp_list = tmp_list->next;
}
#endif
}
return GDK_GRAB_SUCCESS;
}
void
_gdk_input_ungrab_pointer (guint32 time)
{
GdkInputWindow *input_window;
GdkDevicePrivate *gdkdev;
GList *tmp_list;
GDK_NOTE (INPUT, g_print ("_gdk_input_ungrab_pointer\n"));
tmp_list = _gdk_input_windows;
while (tmp_list)
{
input_window = (GdkInputWindow *)tmp_list->data;
if (input_window->grabbed)
break;
tmp_list = tmp_list->next;
}
if (tmp_list) /* we found a grabbed window */
{
input_window->grabbed = FALSE;
tmp_list = _gdk_input_devices;
while (tmp_list)
{
gdkdev = (GdkDevicePrivate *)tmp_list->data;
#if 0
/* XXX */
if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
XUngrabDevice (gdk_display, gdkdev->xdevice, time);
#endif
tmp_list = tmp_list->next;
}
}
x_grab_window = NULL;
}
gboolean
@ -1344,7 +1278,6 @@ gdk_device_get_state (GdkDevice *device,
else
{
GdkDevicePrivate *gdkdev;
GdkInputWindow *input_window;
gdkdev = (GdkDevicePrivate *)device;
/* For now just use the last known button and axis state of the device.
@ -1359,12 +1292,10 @@ gdk_device_get_state (GdkDevice *device,
| GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
| GDK_BUTTON5_MASK));
}
input_window = _gdk_input_window_find (window);
g_return_if_fail (input_window != NULL);
/* For some reason, input_window is sometimes NULL when I use The GIMP 2
* (bug #141543?). Avoid crashing if debugging is disabled. */
if (axes && gdkdev->last_axis_data && input_window)
gdk_input_translate_coordinates (gdkdev, input_window,
if (axes && gdkdev->last_axis_data)
gdk_input_translate_coordinates (gdkdev, window,
gdkdev->last_axis_data,
axes, NULL, NULL);
}
@ -1397,7 +1328,6 @@ _gdk_input_set_tablet_active (void)
void
_gdk_input_init (GdkDisplay *display)
{
_gdk_input_ignore_core = FALSE;
_gdk_input_devices = NULL;
_gdk_init_input_core (display);

View File

@ -70,24 +70,19 @@ struct _GdkDevicePrivate
AXIS orientation_axes[2];
};
/* Addition used for extension_events mask */
#define GDK_ALL_DEVICES_MASK (1<<30)
struct _GdkInputWindow
{
/* gdk window */
GdkWindow *window;
GList *windows; /* GdkWindow:s with extension_events set */
/* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */
GdkExtensionMode mode;
GdkWindow *impl_window; /* an impl window */
/* position relative to root window */
gint root_x;
gint root_y;
/* rectangles relative to window of windows obscuring this one */
GdkRectangle *obscuring;
gint num_obscuring;
/* Is there a pointer grab for this window ? */
gint grabbed;
};
/* Global data */
@ -97,7 +92,7 @@ struct _GdkInputWindow
extern GList *_gdk_input_devices;
extern GList *_gdk_input_windows;
extern gint _gdk_input_ignore_core;
extern gboolean _gdk_input_in_proximity;
/* Function declarations */
void _gdk_init_input_core (GdkDisplay *display);
@ -109,7 +104,6 @@ GdkTimeCoord ** _gdk_device_allocate_history (GdkDevice *device,
* (just wintab for now)
*/
void _gdk_input_configure_event (GdkWindow *window);
void _gdk_input_enter_event (GdkWindow *window);
gboolean _gdk_input_other_event (GdkEvent *event,
MSG *msg,
GdkWindow *window);
@ -124,10 +118,7 @@ GdkInputWindow *_gdk_input_window_find (GdkWindow *window);
void _gdk_input_window_destroy (GdkWindow *window);
gint _gdk_input_enable_window (GdkWindow *window,
GdkDevicePrivate *gdkdev);
gint _gdk_input_disable_window (GdkWindow *window,
GdkDevicePrivate *gdkdev);
void _gdk_input_select_events (GdkWindow *impl_window);
gint _gdk_input_grab_pointer (GdkWindow *window,
gint owner_events,
GdkEventMask event_mask,
@ -143,5 +134,7 @@ gboolean _gdk_device_get_history (GdkDevice *device,
void _gdk_input_wintab_init_check (void);
void _gdk_input_set_tablet_active (void);
void _gdk_input_update_for_device_mode (GdkDevicePrivate *gdkdev);
void _gdk_input_check_proximity (void);
#endif /* __GDK_INPUT_WIN32_H__ */

View File

@ -46,10 +46,10 @@ static GdkDeviceAxis gdk_input_core_axes[] = {
/* Global variables */
gint _gdk_input_ignore_core;
GList *_gdk_input_devices;
GList *_gdk_input_windows;
gboolean _gdk_input_in_proximity = 0;
gboolean _gdk_input_inside_input_window = 0;
void
_gdk_init_input_core (GdkDisplay *display)
@ -291,30 +291,63 @@ gdk_device_free_history (GdkTimeCoord **events,
g_free (events);
}
GdkInputWindow *
_gdk_input_window_find(GdkWindow *window)
{
GList *tmp_list;
for (tmp_list=_gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
if (((GdkInputWindow *)(tmp_list->data))->window == window)
return (GdkInputWindow *)(tmp_list->data);
return NULL; /* Not found */
}
/* FIXME: this routine currently needs to be called between creation
and the corresponding configure event (because it doesn't get the
root_relative_geometry). This should work with
gtk_window_set_extension_events, but will likely fail in other
cases */
static void
unset_extension_events (GdkWindow *window)
{
GdkWindowObject *window_private;
GdkWindowObject *impl_window;
GdkInputWindow *iw;
window_private = (GdkWindowObject*) window;
impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
iw = impl_window->input_window;
if (window_private->extension_events != 0)
{
g_assert (iw != NULL);
g_assert (g_list_find (iw->windows, window) != NULL);
iw->windows = g_list_remove (iw->windows, window);
if (iw->windows == NULL)
{
impl_window->input_window = NULL;
_gdk_input_windows = g_list_remove(_gdk_input_windows,iw);
g_free (iw);
}
}
window_private->extension_events = 0;
}
static void
gdk_input_get_root_relative_geometry (HWND w,
int *x_ret,
int *y_ret)
{
POINT pt;
pt.x = 0;
pt.y = 0;
ClientToScreen (w, &pt);
if (x_ret)
*x_ret = pt.x + _gdk_offset_x;
if (y_ret)
*y_ret = pt.y + _gdk_offset_y;
}
void
gdk_input_set_extension_events (GdkWindow *window, gint mask,
GdkExtensionMode mode)
{
GdkWindowObject *window_private;
GList *tmp_list;
GdkWindowObject *impl_window;
GdkInputWindow *iw;
g_return_if_fail (window != NULL);
@ -324,68 +357,81 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
if (GDK_WINDOW_DESTROYED (window))
return;
impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
if (mode == GDK_EXTENSION_EVENTS_ALL && mask != 0)
mask |= GDK_ALL_DEVICES_MASK;
if (mode == GDK_EXTENSION_EVENTS_NONE)
mask = 0;
iw = impl_window->input_window;
if (mask != 0)
{
_gdk_input_wintab_init_check ();
iw = g_new(GdkInputWindow,1);
if (!iw)
{
iw = g_new0 (GdkInputWindow,1);
iw->window = window;
iw->mode = mode;
iw->impl_window = (GdkWindow *)impl_window;
iw->obscuring = NULL;
iw->num_obscuring = 0;
iw->grabbed = FALSE;
iw->windows = NULL;
_gdk_input_windows = g_list_append(_gdk_input_windows,iw);
_gdk_input_windows = g_list_append(_gdk_input_windows, iw);
gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &iw->root_x, &iw->root_y);
impl_window->input_window = iw;
}
if (window_private->extension_events == 0)
iw->windows = g_list_append (iw->windows, window);
window_private->extension_events = mask;
/* Add enter window events to the event mask */
if (g_list_length (_gdk_input_devices) > 1)
gdk_window_set_events (window,
gdk_window_get_events (window) |
GDK_ENTER_NOTIFY_MASK);
}
else
{
iw = _gdk_input_window_find (window);
if (iw)
{
_gdk_input_windows = g_list_remove(_gdk_input_windows,iw);
g_free(iw);
}
window_private->extension_events = 0;
unset_extension_events (window);
}
for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
{
GdkDevicePrivate *gdkdev = tmp_list->data;
if (!GDK_IS_CORE (gdkdev))
{
if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
&& (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
_gdk_input_enable_window (window,gdkdev);
else
_gdk_input_disable_window (window,gdkdev);
}
}
_gdk_input_select_events ((GdkWindow *)impl_window);
}
void
_gdk_input_window_destroy (GdkWindow *window)
{
GdkInputWindow *input_window;
unset_extension_events (window);
}
input_window = _gdk_input_window_find (window);
g_return_if_fail (input_window != NULL);
void
_gdk_input_check_proximity (void)
{
GList *l;
gboolean new_proximity = FALSE;
_gdk_input_windows = g_list_remove (_gdk_input_windows,input_window);
g_free(input_window);
if (!_gdk_input_inside_input_window)
{
_gdk_display->ignore_core_events = FALSE;
return;
}
for (l = _gdk_input_devices; l != NULL; l = l->next)
{
GdkDevicePrivate *gdkdev = l->data;
if (gdkdev->info.mode != GDK_MODE_DISABLED &&
!GDK_IS_CORE (gdkdev))
{
if (_gdk_input_in_proximity)
{
new_proximity = TRUE;
break;
}
}
}
_gdk_display->ignore_core_events = new_proximity;
}
void
@ -394,53 +440,27 @@ _gdk_input_crossing_event (GdkWindow *window,
{
if (enter)
{
#if 0 /* No idea what to do... */
GdkWindowObject *priv = (GdkWindowObject *)window;
GdkInputWindow *input_window;
gint root_x, root_y;
#if 0
gdk_input_check_proximity(display);
#endif
_gdk_input_inside_input_window = TRUE;
input_window = priv->input_window;
if (input_window != NULL)
{
_gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window),
&root_x, &root_y);
input_window->root_x = root_x;
input_window->root_y = root_y;
}
#endif
}
else
_gdk_input_ignore_core = FALSE;
}
void
_gdk_input_exit (void)
{
GList *tmp_list;
GdkDevicePrivate *gdkdev;
for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
{
gdkdev = (GdkDevicePrivate *)(tmp_list->data);
if (!GDK_IS_CORE (gdkdev))
{
gdk_device_set_mode (&gdkdev->info, GDK_MODE_DISABLED);
g_free(gdkdev->info.name);
g_free(gdkdev->axes);
g_free(gdkdev->info.axes);
g_free(gdkdev->info.keys);
g_free(gdkdev);
}
_gdk_input_inside_input_window = FALSE;
}
g_list_free(_gdk_input_devices);
for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
g_free(tmp_list->data);
g_list_free(_gdk_input_windows);
_gdk_input_check_proximity ();
}
gboolean
@ -473,7 +493,6 @@ gdk_device_set_mode (GdkDevice *device,
{
GList *tmp_list;
GdkDevicePrivate *gdkdev;
GdkInputMode old_mode;
GdkInputWindow *input_window;
if (GDK_IS_CORE (device))
@ -484,39 +503,21 @@ gdk_device_set_mode (GdkDevice *device,
if (device->mode == mode)
return TRUE;
old_mode = device->mode;
device->mode = mode;
if (mode == GDK_MODE_WINDOW)
{
device->has_cursor = FALSE;
for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
{
input_window = (GdkInputWindow *)tmp_list->data;
if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
_gdk_input_enable_window (input_window->window, gdkdev);
else
if (old_mode != GDK_MODE_DISABLED)
_gdk_input_disable_window (input_window->window, gdkdev);
}
}
device->has_cursor = FALSE;
else if (mode == GDK_MODE_SCREEN)
device->has_cursor = TRUE;
for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
{
device->has_cursor = TRUE;
for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
_gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
gdkdev);
}
else /* mode == GDK_MODE_DISABLED */
{
for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
{
input_window = (GdkInputWindow *)tmp_list->data;
if (old_mode != GDK_MODE_WINDOW ||
input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
_gdk_input_disable_window (input_window->window, gdkdev);
}
input_window = (GdkInputWindow *)tmp_list->data;
_gdk_input_select_events (input_window->impl_window);
}
if (!GDK_IS_CORE (gdkdev))
_gdk_input_update_for_device_mode (gdkdev);
return TRUE;
}

View File

@ -494,7 +494,8 @@ gboolean _gdk_win32_pixbuf_to_hicon_supports_alpha (void);
void _gdk_win32_append_event (GdkEvent *event);
void _gdk_win32_emit_configure_event (GdkWindow *window);
GdkWindow *_gdk_win32_find_window_for_mouse_event (GdkWindow* reported_window,
MSG* msg);
/* Initialization */
void _gdk_windowing_window_init (GdkScreen *screen);

View File

@ -125,7 +125,7 @@ gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
impl->hicon_small = NULL;
impl->hint_flags = 0;
impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
impl->extension_events_selected = FALSE;
impl->extension_events_mask = 0;
impl->transient_owner = NULL;
impl->transient_children = NULL;
impl->num_transients = 0;
@ -558,7 +558,7 @@ _gdk_window_impl_new (GdkWindow *window,
if (attributes_mask & GDK_WA_VISUAL)
g_assert (visual == attributes->visual);
impl->extension_events_selected = FALSE;
impl->extension_events_mask = 0;
impl->override_redirect = override_redirect;
/* wclass is not any longer set always, but if is ... */

View File

@ -84,7 +84,7 @@ struct _GdkWindowImplWin32
GdkWindowTypeHint type_hint;
gboolean extension_events_selected;
GdkEventMask extension_events_mask;
GdkWindow *transient_owner;
GSList *transient_children;

View File

@ -266,6 +266,8 @@ _gdk_input_other_event (GdkEvent *event,
else
window = _gdk_window_get_input_window_for_event (event_window,
event_type,
/* TODO: Seems wrong, but the code used to ignore button motion handling here... */
0,
x, y,
xevent->xany.serial);
priv = (GdkWindowObject *)window;