2010-05-25 22:38:44 +00:00
|
|
|
/* GDK - The GIMP Drawing Kit
|
|
|
|
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <gdk/gdkwindow.h>
|
|
|
|
|
|
|
|
#include <windowsx.h>
|
|
|
|
#include <objbase.h>
|
|
|
|
|
2011-01-02 10:51:25 +00:00
|
|
|
#include "gdkdisplayprivate.h"
|
2010-05-25 22:38:44 +00:00
|
|
|
#include "gdkdevice-win32.h"
|
|
|
|
#include "gdkwin32.h"
|
|
|
|
|
|
|
|
static gboolean gdk_device_win32_get_history (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
guint32 start,
|
|
|
|
guint32 stop,
|
|
|
|
GdkTimeCoord ***events,
|
2010-10-19 11:30:42 +00:00
|
|
|
gint *n_events);
|
2010-05-25 22:38:44 +00:00
|
|
|
static void gdk_device_win32_get_state (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
gdouble *axes,
|
|
|
|
GdkModifierType *mask);
|
|
|
|
static void gdk_device_win32_set_window_cursor (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
GdkCursor *cursor);
|
|
|
|
static void gdk_device_win32_warp (GdkDevice *device,
|
|
|
|
GdkScreen *screen,
|
|
|
|
gint x,
|
|
|
|
gint y);
|
|
|
|
static gboolean gdk_device_win32_query_state (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
GdkWindow **root_window,
|
|
|
|
GdkWindow **child_window,
|
|
|
|
gint *root_x,
|
|
|
|
gint *root_y,
|
|
|
|
gint *win_x,
|
|
|
|
gint *win_y,
|
|
|
|
GdkModifierType *mask);
|
|
|
|
static GdkGrabStatus gdk_device_win32_grab (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
gboolean owner_events,
|
|
|
|
GdkEventMask event_mask,
|
|
|
|
GdkWindow *confine_to,
|
|
|
|
GdkCursor *cursor,
|
|
|
|
guint32 time_);
|
|
|
|
static void gdk_device_win32_ungrab (GdkDevice *device,
|
|
|
|
guint32 time_);
|
|
|
|
static GdkWindow * gdk_device_win32_window_at_position (GdkDevice *device,
|
|
|
|
gint *win_x,
|
|
|
|
gint *win_y,
|
|
|
|
GdkModifierType *mask,
|
|
|
|
gboolean get_toplevel);
|
|
|
|
static void gdk_device_win32_select_window_events (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
GdkEventMask event_mask);
|
|
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (GdkDeviceWin32, gdk_device_win32, GDK_TYPE_DEVICE)
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_device_win32_class_init (GdkDeviceWin32Class *klass)
|
|
|
|
{
|
|
|
|
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
|
|
|
|
|
|
|
device_class->get_history = gdk_device_win32_get_history;
|
|
|
|
device_class->get_state = gdk_device_win32_get_state;
|
|
|
|
device_class->set_window_cursor = gdk_device_win32_set_window_cursor;
|
|
|
|
device_class->warp = gdk_device_win32_warp;
|
|
|
|
device_class->query_state = gdk_device_win32_query_state;
|
|
|
|
device_class->grab = gdk_device_win32_grab;
|
|
|
|
device_class->ungrab = gdk_device_win32_ungrab;
|
|
|
|
device_class->window_at_position = gdk_device_win32_window_at_position;
|
|
|
|
device_class->select_window_events = gdk_device_win32_select_window_events;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_device_win32_init (GdkDeviceWin32 *device_win32)
|
|
|
|
{
|
|
|
|
GdkDevice *device;
|
|
|
|
|
|
|
|
device = GDK_DEVICE (device_win32);
|
|
|
|
|
|
|
|
_gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_X, 0, 0, 1);
|
|
|
|
_gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_Y, 0, 0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gdk_device_win32_get_history (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
guint32 start,
|
|
|
|
guint32 stop,
|
|
|
|
GdkTimeCoord ***events,
|
2010-10-19 11:30:42 +00:00
|
|
|
gint *n_events)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_device_win32_get_state (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
gdouble *axes,
|
|
|
|
GdkModifierType *mask)
|
|
|
|
{
|
|
|
|
gint x_int, y_int;
|
|
|
|
|
|
|
|
gdk_window_get_pointer (window, &x_int, &y_int, mask);
|
|
|
|
|
|
|
|
if (axes)
|
|
|
|
{
|
|
|
|
axes[0] = x_int;
|
|
|
|
axes[1] = y_int;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_device_win32_set_window_cursor (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
GdkCursor *cursor)
|
|
|
|
{
|
2011-01-02 10:51:25 +00:00
|
|
|
GdkWin32Cursor *cursor_private;
|
|
|
|
GdkWindow *parent_window;
|
2010-05-25 22:38:44 +00:00
|
|
|
GdkWindowImplWin32 *impl;
|
|
|
|
HCURSOR hcursor;
|
|
|
|
HCURSOR hprevcursor;
|
|
|
|
|
2011-01-02 10:51:25 +00:00
|
|
|
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
|
|
|
|
cursor_private = (GdkWin32Cursor*) cursor;
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
hprevcursor = impl->hcursor;
|
|
|
|
|
|
|
|
if (!cursor)
|
|
|
|
hcursor = NULL;
|
|
|
|
else
|
|
|
|
hcursor = cursor_private->hcursor;
|
|
|
|
|
|
|
|
if (hcursor != NULL)
|
|
|
|
{
|
|
|
|
/* If the pointer is over our window, set new cursor */
|
|
|
|
GdkWindow *curr_window = gdk_window_get_pointer (window, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
if (curr_window == window ||
|
|
|
|
(curr_window && window == gdk_window_get_toplevel (curr_window)))
|
|
|
|
SetCursor (hcursor);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Climb up the tree and find whether our window is the
|
|
|
|
* first ancestor that has cursor defined, and if so, set
|
|
|
|
* new cursor.
|
|
|
|
*/
|
2011-01-02 10:51:25 +00:00
|
|
|
while (curr_window && curr_window->impl &&
|
|
|
|
!GDK_WINDOW_IMPL_WIN32 (curr_window->impl)->hcursor)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
2011-01-02 10:51:25 +00:00
|
|
|
curr_window = curr_window->parent;
|
|
|
|
if (curr_window == GDK_WINDOW (window))
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
SetCursor (hcursor);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unset the previous cursor: Need to make sure it's no longer in
|
|
|
|
* use before we destroy it, in case we're not over our window but
|
|
|
|
* the cursor is still set to our old one.
|
|
|
|
*/
|
|
|
|
if (hprevcursor != NULL &&
|
|
|
|
GetCursor () == hprevcursor)
|
|
|
|
{
|
|
|
|
/* Look for a suitable cursor to use instead */
|
|
|
|
hcursor = NULL;
|
2011-01-02 10:51:25 +00:00
|
|
|
parent_window = GDK_WINDOW (window)->parent;
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
while (hcursor == NULL)
|
|
|
|
{
|
|
|
|
if (parent_window)
|
|
|
|
{
|
|
|
|
impl = GDK_WINDOW_IMPL_WIN32 (parent_window->impl);
|
|
|
|
hcursor = impl->hcursor;
|
|
|
|
parent_window = parent_window->parent;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
hcursor = LoadCursor (NULL, IDC_ARROW);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetCursor (hcursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_device_win32_warp (GdkDevice *device,
|
|
|
|
GdkScreen *screen,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
|
|
|
{
|
|
|
|
SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GdkModifierType
|
|
|
|
get_current_mask (void)
|
|
|
|
{
|
|
|
|
GdkModifierType mask;
|
|
|
|
BYTE kbd[256];
|
|
|
|
|
|
|
|
GetKeyboardState (kbd);
|
|
|
|
mask = 0;
|
|
|
|
if (kbd[VK_SHIFT] & 0x80)
|
|
|
|
mask |= GDK_SHIFT_MASK;
|
|
|
|
if (kbd[VK_CAPITAL] & 0x80)
|
|
|
|
mask |= GDK_LOCK_MASK;
|
|
|
|
if (kbd[VK_CONTROL] & 0x80)
|
|
|
|
mask |= GDK_CONTROL_MASK;
|
|
|
|
if (kbd[VK_MENU] & 0x80)
|
|
|
|
mask |= GDK_MOD1_MASK;
|
|
|
|
if (kbd[VK_LBUTTON] & 0x80)
|
|
|
|
mask |= GDK_BUTTON1_MASK;
|
|
|
|
if (kbd[VK_MBUTTON] & 0x80)
|
|
|
|
mask |= GDK_BUTTON2_MASK;
|
|
|
|
if (kbd[VK_RBUTTON] & 0x80)
|
|
|
|
mask |= GDK_BUTTON3_MASK;
|
|
|
|
|
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gdk_device_win32_query_state (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
GdkWindow **root_window,
|
|
|
|
GdkWindow **child_window,
|
|
|
|
gint *root_x,
|
|
|
|
gint *root_y,
|
|
|
|
gint *win_x,
|
|
|
|
gint *win_y,
|
|
|
|
GdkModifierType *mask)
|
|
|
|
{
|
|
|
|
gboolean return_val;
|
|
|
|
POINT point;
|
|
|
|
HWND hwnd, hwndc;
|
|
|
|
|
|
|
|
g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
|
|
|
|
|
|
|
|
return_val = TRUE;
|
|
|
|
|
|
|
|
hwnd = GDK_WINDOW_HWND (window);
|
|
|
|
GetCursorPos (&point);
|
|
|
|
|
|
|
|
if (root_x)
|
|
|
|
*root_x = point.x;
|
|
|
|
|
|
|
|
if (root_y)
|
|
|
|
*root_y = point.y;
|
|
|
|
|
|
|
|
ScreenToClient (hwnd, &point);
|
|
|
|
|
|
|
|
if (win_x)
|
|
|
|
*win_x = point.x;
|
|
|
|
|
|
|
|
if (win_y)
|
|
|
|
*win_y = point.y;
|
|
|
|
|
|
|
|
if (window == _gdk_root)
|
|
|
|
{
|
|
|
|
if (win_x)
|
|
|
|
*win_x += _gdk_offset_x;
|
|
|
|
|
|
|
|
if (win_y)
|
|
|
|
*win_y += _gdk_offset_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (child_window)
|
|
|
|
{
|
|
|
|
hwndc = ChildWindowFromPoint (hwnd, point);
|
|
|
|
|
|
|
|
if (hwndc && hwndc != hwnd)
|
2011-02-06 14:03:32 +00:00
|
|
|
*child_window = gdk_win32_handle_table_lookup (hwndc);
|
2010-05-25 22:38:44 +00:00
|
|
|
else
|
|
|
|
*child_window = NULL; /* Direct child unknown to gdk */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (root_window)
|
|
|
|
{
|
|
|
|
GdkScreen *screen;
|
|
|
|
|
2010-08-28 23:32:52 +00:00
|
|
|
screen = gdk_window_get_screen (window);
|
2010-05-25 22:38:44 +00:00
|
|
|
*root_window = gdk_screen_get_root_window (screen);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mask)
|
|
|
|
*mask = get_current_mask ();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GdkGrabStatus
|
|
|
|
gdk_device_win32_grab (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
gboolean owner_events,
|
|
|
|
GdkEventMask event_mask,
|
|
|
|
GdkWindow *confine_to,
|
|
|
|
GdkCursor *cursor,
|
|
|
|
guint32 time_)
|
|
|
|
{
|
2011-11-10 20:32:50 +00:00
|
|
|
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
|
|
|
|
HCURSOR hcursor;
|
|
|
|
GdkWin32Cursor *cursor_private;
|
|
|
|
|
|
|
|
cursor_private = (GdkWin32Cursor*) cursor;
|
|
|
|
|
2010-11-24 12:26:53 +00:00
|
|
|
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
|
2011-11-10 20:32:50 +00:00
|
|
|
{
|
|
|
|
if (!cursor)
|
|
|
|
hcursor = NULL;
|
|
|
|
else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL)
|
|
|
|
WIN32_API_FAILED ("CopyCursor");
|
|
|
|
|
|
|
|
if (_gdk_win32_grab_cursor != NULL)
|
|
|
|
{
|
|
|
|
if (GetCursor () == _gdk_win32_grab_cursor)
|
|
|
|
SetCursor (NULL);
|
|
|
|
DestroyCursor (_gdk_win32_grab_cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
_gdk_win32_grab_cursor = hcursor;
|
|
|
|
|
|
|
|
if (_gdk_win32_grab_cursor != NULL)
|
|
|
|
SetCursor (_gdk_win32_grab_cursor);
|
|
|
|
else if (impl->hcursor != NULL)
|
|
|
|
SetCursor (impl->hcursor);
|
|
|
|
else
|
|
|
|
SetCursor (LoadCursor (NULL, IDC_ARROW));
|
|
|
|
|
|
|
|
SetCapture (GDK_WINDOW_HWND (window));
|
|
|
|
}
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
return GDK_GRAB_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_device_win32_ungrab (GdkDevice *device,
|
|
|
|
guint32 time_)
|
|
|
|
{
|
2011-01-02 10:51:25 +00:00
|
|
|
GdkDeviceGrabInfo *info;
|
2010-05-25 22:38:44 +00:00
|
|
|
GdkDisplay *display;
|
|
|
|
|
|
|
|
display = gdk_device_get_display (device);
|
2011-01-02 10:51:25 +00:00
|
|
|
info = _gdk_display_get_last_device_grab (display, device);
|
|
|
|
|
|
|
|
if (info)
|
|
|
|
info->serial_end = 0;
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2010-11-24 12:26:53 +00:00
|
|
|
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
|
2011-11-10 20:32:50 +00:00
|
|
|
{
|
|
|
|
if (_gdk_win32_grab_cursor != NULL)
|
|
|
|
{
|
|
|
|
if (GetCursor () == _gdk_win32_grab_cursor)
|
|
|
|
SetCursor (NULL);
|
|
|
|
DestroyCursor (_gdk_win32_grab_cursor);
|
|
|
|
}
|
|
|
|
_gdk_win32_grab_cursor = NULL;
|
|
|
|
|
|
|
|
ReleaseCapture ();
|
|
|
|
}
|
2011-01-02 10:51:25 +00:00
|
|
|
|
|
|
|
_gdk_display_device_grab_update (display, device, NULL, 0);
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
|
|
|
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
static void
|
|
|
|
screen_to_client (HWND hwnd, POINT screen_pt, POINT *client_pt)
|
|
|
|
{
|
|
|
|
*client_pt = screen_pt;
|
|
|
|
ScreenToClient (hwnd, client_pt);
|
|
|
|
}
|
|
|
|
|
2010-05-25 22:38:44 +00:00
|
|
|
static GdkWindow *
|
|
|
|
gdk_device_win32_window_at_position (GdkDevice *device,
|
|
|
|
gint *win_x,
|
|
|
|
gint *win_y,
|
|
|
|
GdkModifierType *mask,
|
|
|
|
gboolean get_toplevel)
|
|
|
|
{
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
GdkWindow *window = NULL;
|
|
|
|
POINT screen_pt, client_pt;
|
2010-05-25 22:38:44 +00:00
|
|
|
HWND hwnd, hwndc;
|
|
|
|
RECT rect;
|
|
|
|
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
GetCursorPos (&screen_pt);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
if (get_toplevel)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
/* Only consider visible children of the desktop to avoid the various
|
|
|
|
* non-visible windows you often find on a running Windows box. These
|
|
|
|
* might overlap our windows and cause our walk to fail. As we assume
|
|
|
|
* WindowFromPoint() can find our windows, we follow similar logic
|
|
|
|
* here, and ignore invisible and disabled windows.
|
|
|
|
*/
|
|
|
|
hwnd = GetDesktopWindow ();
|
|
|
|
do {
|
|
|
|
window = gdk_win32_handle_table_lookup (hwnd);
|
|
|
|
|
|
|
|
if (window != NULL &&
|
|
|
|
GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT &&
|
|
|
|
GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
|
|
|
|
break;
|
|
|
|
|
|
|
|
screen_to_client (hwnd, screen_pt, &client_pt);
|
|
|
|
hwndc = ChildWindowFromPointEx (hwnd, client_pt, CWP_SKIPDISABLED |
|
|
|
|
CWP_SKIPINVISIBLE);
|
2011-10-19 14:15:17 +00:00
|
|
|
|
|
|
|
/* Verify that we're really inside the client area of the window */
|
|
|
|
if (hwndc != hwnd)
|
|
|
|
{
|
|
|
|
GetClientRect (hwndc, &rect);
|
|
|
|
screen_to_client (hwndc, screen_pt, &client_pt);
|
|
|
|
if (!PtInRect (&rect, client_pt))
|
|
|
|
hwndc = hwnd;
|
|
|
|
}
|
|
|
|
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
} while (hwndc != hwnd && (hwnd = hwndc, 1));
|
2010-05-25 22:38:44 +00:00
|
|
|
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
}
|
|
|
|
else
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
hwnd = WindowFromPoint (screen_pt);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2011-10-19 14:15:17 +00:00
|
|
|
/* Verify that we're really inside the client area of the window */
|
|
|
|
GetClientRect (hwnd, &rect);
|
|
|
|
screen_to_client (hwnd, screen_pt, &client_pt);
|
|
|
|
if (!PtInRect (&rect, client_pt))
|
|
|
|
hwnd = NULL;
|
|
|
|
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
/* If we didn't hit any window at that point, return the desktop */
|
|
|
|
if (hwnd == NULL)
|
|
|
|
{
|
|
|
|
if (win_x)
|
|
|
|
*win_x = screen_pt.x + _gdk_offset_x;
|
|
|
|
if (win_y)
|
|
|
|
*win_y = screen_pt.y + _gdk_offset_y;
|
|
|
|
return _gdk_root;
|
|
|
|
}
|
2010-05-25 22:38:44 +00:00
|
|
|
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
window = gdk_win32_handle_table_lookup (hwnd);
|
|
|
|
}
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
if (window && (win_x || win_y))
|
|
|
|
{
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
if (win_x)
|
2011-10-19 14:15:17 +00:00
|
|
|
*win_x = client_pt.x;
|
Win32: Fix _gdk_windowing_window_at_pointer to correctly return a toplevel
Commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 didn't add the correct
code to find the toplevel window. The WindowFromPoint() function does
not return the toplevel window in the hierarchy, it returns the deepest
non-disabled, non-invisible child. As we don't use invisible or disabled
windows, we don't actually need to use the ChildWindowFromPoint walk for
the non get_toplevel case, so we can remove that code path.
To find a toplevel, we need to start from the desktop and work up, using
ChildWindowFromPointEx (to ignore invisible and disabled windows). If we
don't ignore invisible and disabled windows (as is the case with the
ChildWindowFromPoint call, we are liable to get returns of hidden or
disabled children of the desktop which don't belong to us, but notionally
occupy the same area under the pointer.
An alternative might be to start our walk with one of the children of the
desktop owned by our process and thread - which we can enumerate using,
the EnumThreadWindows call, or (presumably) determine internally. This
would not work when we are inside a GtkSocket though, as the children of
the desktop would belong to the process owning the GtkPlug - we would
have to rely on our own list of windows.
For correctness, this commit adds tests to ensure that we don't try to
return either x or y window coordinates if that corresponding pointer is
NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=658842
2011-09-10 15:30:56 +00:00
|
|
|
if (win_y)
|
2011-10-19 14:15:17 +00:00
|
|
|
*win_y = client_pt.y;
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_device_win32_select_window_events (GdkDevice *device,
|
|
|
|
GdkWindow *window,
|
|
|
|
GdkEventMask event_mask)
|
|
|
|
{
|
|
|
|
}
|