Commit e8b38fed authored by Alexander Larsson's avatar Alexander Larsson

gdk: Convert mouse position to doubles, add new getters

We've long had double precision mouse coordinates on wayland (e.g.
when rotating a window) but with the new scaling we even have it on
X (and, its also in Xinput2), so convert all the internal mouse/device
position getters to use doubles and add new accessors for the
public APIs that take doubles instead of ints.
parent 867ba1df
......@@ -38,16 +38,16 @@ static void gdk_broadway_device_set_window_cursor (GdkDevice *device,
GdkCursor *cursor);
static void gdk_broadway_device_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y);
gdouble x,
gdouble y);
static void gdk_broadway_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_broadway_device_grab (GdkDevice *device,
GdkWindow *window,
......@@ -59,8 +59,8 @@ static GdkGrabStatus gdk_broadway_device_grab (GdkDevice *device,
static void gdk_broadway_device_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_broadway_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_broadway_device_select_window_events (GdkDevice *device,
......@@ -114,14 +114,14 @@ gdk_broadway_device_get_state (GdkDevice *device,
gdouble *axes,
GdkModifierType *mask)
{
gint x_int, y_int;
gdouble x, y;
gdk_window_get_device_position (window, device, &x_int, &y_int, mask);
gdk_window_get_device_position_double (window, device, &x, &y, mask);
if (axes)
{
axes[0] = x_int;
axes[1] = y_int;
axes[0] = x;
axes[1] = y;
}
}
......@@ -135,8 +135,8 @@ gdk_broadway_device_set_window_cursor (GdkDevice *device,
static void
gdk_broadway_device_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)
gdouble x,
gdouble y)
{
}
......@@ -145,10 +145,10 @@ gdk_broadway_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkWindow *toplevel;
......@@ -335,8 +335,8 @@ gdk_broadway_device_ungrab (GdkDevice *device,
static GdkWindow *
gdk_broadway_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
......
......@@ -750,8 +750,8 @@ gdk_broadway_window_get_frame_extents (GdkWindow *window,
static gboolean
gdk_window_broadway_get_device_state (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
GdkWindow *child;
......
......@@ -24,6 +24,9 @@
#include "gdkinternals.h"
#include "gdkintl.h"
/* for the use of round() */
#include "fallback-c89.c"
/**
* SECTION:gdkdevice
* @Short_description: Object representing an input device
......@@ -406,28 +409,28 @@ gdk_device_get_state (GdkDevice *device,
}
/**
* gdk_device_get_position:
* gdk_device_get_position_double:
* @device: pointer device to query status about.
* @screen: (out) (transfer none) (allow-none): location to store the #GdkScreen
* the @device is on, or %NULL.
* @x: (out) (allow-none): location to store root window X coordinate of @device, or %NULL.
* @y: (out) (allow-none): location to store root window Y coordinate of @device, or %NULL.
*
* Gets the current location of @device. As a slave device
* Gets the current location of @device in double precision. As a slave device
* coordinates are those of its master pointer, This function
* may not be called on devices of type %GDK_DEVICE_TYPE_SLAVE,
* unless there is an ongoing grab on them, see gdk_device_grab().
*
* Since: 3.0
* Since: 3.10
**/
void
gdk_device_get_position (GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y)
gdk_device_get_position_double (GdkDevice *device,
GdkScreen **screen,
gdouble *x,
gdouble *y)
{
GdkDisplay *display;
gint tmp_x, tmp_y;
gdouble tmp_x, tmp_y;
GdkScreen *default_screen;
GdkWindow *root;
......@@ -456,15 +459,47 @@ gdk_device_get_position (GdkDevice *device,
}
/**
* gdk_device_get_window_at_position:
* gdk_device_get_position:
* @device: pointer device to query status about.
* @screen: (out) (transfer none) (allow-none): location to store the #GdkScreen
* the @device is on, or %NULL.
* @x: (out) (allow-none): location to store root window X coordinate of @device, or %NULL.
* @y: (out) (allow-none): location to store root window Y coordinate of @device, or %NULL.
*
* Gets the current location of @device. As a slave device
* coordinates are those of its master pointer, This function
* may not be called on devices of type %GDK_DEVICE_TYPE_SLAVE,
* unless there is an ongoing grab on them, see gdk_device_grab().
*
* Since: 3.0
**/
void
gdk_device_get_position (GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y)
{
gdouble tmp_x, tmp_y;
gdk_device_get_position_double (device, screen, &tmp_x, &tmp_y);
if (x)
*x = round (tmp_x);
if (y)
*y = round (tmp_y);
}
/**
* gdk_device_get_window_at_position_double:
* @device: pointer #GdkDevice to query info to.
* @win_x: (out) (allow-none): return location for the X coordinate of the device location,
* relative to the window origin, or %NULL.
* @win_y: (out) (allow-none): return location for the Y coordinate of the device location,
* relative to the window origin, or %NULL.
*
* Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
* %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
* Obtains the window underneath @device, returning the location of the device in @win_x and @win_y in
* double precision. Returns %NULL if the window tree under @device is not known to GDK (for example,
* belongs to another application).
*
* As a slave device coordinates are those of its master pointer, This
* function may not be called on devices of type %GDK_DEVICE_TYPE_SLAVE,
......@@ -475,11 +510,11 @@ gdk_device_get_position (GdkDevice *device,
* Since: 3.0
**/
GdkWindow *
gdk_device_get_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y)
gdk_device_get_window_at_position_double (GdkDevice *device,
gdouble *win_x,
gdouble *win_y)
{
gint tmp_x, tmp_y;
gdouble tmp_x, tmp_y;
GdkWindow *window;
g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
......@@ -492,15 +527,9 @@ gdk_device_get_window_at_position (GdkDevice *device,
/* This might need corrections, as the native window returned
may contain client side children */
if (window)
{
double xx, yy;
window = _gdk_window_find_descendant_at (window,
tmp_x, tmp_y,
&xx, &yy);
tmp_x = floor (xx + 0.5);
tmp_y = floor (yy + 0.5);
}
window = _gdk_window_find_descendant_at (window,
tmp_x, tmp_y,
&tmp_x, &tmp_y);
if (win_x)
*win_x = tmp_x;
......@@ -510,6 +539,44 @@ gdk_device_get_window_at_position (GdkDevice *device,
return window;
}
/**
* gdk_device_get_window_at_position:
* @device: pointer #GdkDevice to query info to.
* @win_x: (out) (allow-none): return location for the X coordinate of the device location,
* relative to the window origin, or %NULL.
* @win_y: (out) (allow-none): return location for the Y coordinate of the device location,
* relative to the window origin, or %NULL.
*
* Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
* %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
*
* As a slave device coordinates are those of its master pointer, This
* function may not be called on devices of type %GDK_DEVICE_TYPE_SLAVE,
* unless there is an ongoing grab on them, see gdk_device_grab().
*
* Returns: (transfer none): the #GdkWindow under the device position, or %NULL.
*
* Since: 3.0
**/
GdkWindow *
gdk_device_get_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y)
{
gdouble tmp_x, tmp_y;
GdkWindow *window;
window =
gdk_device_get_window_at_position_double (device, &tmp_x, &tmp_y);
if (win_x)
*win_x = round (tmp_x);
if (win_y)
*win_y = round (tmp_y);
return window;
}
/**
* gdk_device_get_history: (skip)
* @device: a #GdkDevice
......@@ -1535,8 +1602,8 @@ _gdk_device_translate_window_coord (GdkDevice *device,
gboolean
_gdk_device_translate_screen_coord (GdkDevice *device,
GdkWindow *window,
gint window_root_x,
gint window_root_y,
gdouble window_root_x,
gdouble window_root_y,
guint index_,
gdouble value,
gdouble *axis_value)
......@@ -1616,10 +1683,10 @@ _gdk_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GDK_DEVICE_GET_CLASS (device)->query_state (device,
......@@ -1635,8 +1702,8 @@ _gdk_device_query_state (GdkDevice *device,
GdkWindow *
_gdk_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
......
......@@ -198,6 +198,17 @@ GdkWindow *
(GdkDevice *device,
gint *win_x,
gint *win_y);
GDK_AVAILABLE_IN_3_10
void gdk_device_get_position_double (GdkDevice *device,
GdkScreen **screen,
gdouble *x,
gdouble *y);
GDK_AVAILABLE_IN_3_10
GdkWindow *
gdk_device_get_window_at_position_double
(GdkDevice *device,
gdouble *win_x,
gdouble *win_y);
GDK_AVAILABLE_IN_ALL
gboolean gdk_device_get_history (GdkDevice *device,
GdkWindow *window,
......
......@@ -80,16 +80,16 @@ struct _GdkDeviceClass
void (* warp) (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y);
gdouble x,
gdouble y);
void (* query_state) (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
GdkGrabStatus (* grab) (GdkDevice *device,
GdkWindow *window,
......@@ -102,8 +102,8 @@ struct _GdkDeviceClass
guint32 time_);
GdkWindow * (* window_at_position) (GdkDevice *device,
gint *win_x,
gint *win_y,
double *win_x,
double *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
void (* select_window_events) (GdkDevice *device,
......@@ -140,8 +140,8 @@ gboolean _gdk_device_translate_window_coord (GdkDevice *device,
gboolean _gdk_device_translate_screen_coord (GdkDevice *device,
GdkWindow *window,
gint window_root_x,
gint window_root_y,
gdouble window_root_x,
gdouble window_root_y,
guint index,
gdouble value,
gdouble *axis_value);
......@@ -162,14 +162,14 @@ void _gdk_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
GdkWindow * _gdk_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
......
......@@ -32,8 +32,11 @@
#include "gdkmarshalers.h"
#include "gdkscreen.h"
#include <math.h>
#include <glib.h>
/* for the use of round() */
#include "fallback-c89.c"
/**
* SECTION:gdkdisplay
......@@ -546,7 +549,7 @@ gdk_display_get_pointer (GdkDisplay *display,
{
GdkScreen *default_screen;
GdkWindow *root;
gint tmp_x, tmp_y;
gdouble tmp_x, tmp_y;
GdkModifierType tmp_mask;
g_return_if_fail (GDK_IS_DISPLAY (display));
......@@ -569,9 +572,9 @@ gdk_display_get_pointer (GdkDisplay *display,
if (screen)
*screen = gdk_window_get_screen (root);
if (x)
*x = tmp_x;
*x = round (tmp_x);
if (y)
*y = tmp_y;
*y = round (tmp_y);
if (mask)
*mask = tmp_mask;
}
......@@ -792,7 +795,7 @@ synthesize_crossing_events (GdkDisplay *display,
{
GdkWindow *src_toplevel, *dest_toplevel;
GdkModifierType state;
int x, y;
double x, y;
if (src_window)
src_toplevel = gdk_window_get_toplevel (src_window);
......@@ -810,9 +813,9 @@ synthesize_crossing_events (GdkDisplay *display,
src_toplevel == dest_toplevel)
{
/* Same toplevels */
gdk_window_get_device_position (dest_toplevel,
device,
&x, &y, &state);
gdk_window_get_device_position_double (dest_toplevel,
device,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
dest_window,
......@@ -825,9 +828,9 @@ synthesize_crossing_events (GdkDisplay *display,
}
else if (dest_toplevel == NULL)
{
gdk_window_get_device_position (src_toplevel,
device,
&x, &y, &state);
gdk_window_get_device_position_double (src_toplevel,
device,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
NULL,
......@@ -841,9 +844,9 @@ synthesize_crossing_events (GdkDisplay *display,
else
{
/* Different toplevels */
gdk_window_get_device_position (src_toplevel,
device,
&x, &y, &state);
gdk_window_get_device_position_double (src_toplevel,
device,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
NULL,
......@@ -853,9 +856,9 @@ synthesize_crossing_events (GdkDisplay *display,
time,
NULL,
serial, FALSE);
gdk_window_get_device_position (dest_toplevel,
device,
&x, &y, &state);
gdk_window_get_device_position_double (dest_toplevel,
device,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
NULL,
dest_window,
......@@ -876,7 +879,7 @@ get_current_toplevel (GdkDisplay *display,
GdkModifierType *state_out)
{
GdkWindow *pointer_window;
int x, y;
gdouble x, y;
GdkModifierType state;
pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
......@@ -887,8 +890,8 @@ get_current_toplevel (GdkDisplay *display,
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
pointer_window = NULL;
*x_out = x;
*y_out = y;
*x_out = round (x);
*y_out = round (y);
*state_out = state;
return pointer_window;
......
......@@ -358,7 +358,7 @@ void _gdk_window_invalidate_for_expose (GdkWindow *window,
cairo_region_t *region);
GdkWindow * _gdk_window_find_child_at (GdkWindow *window,
int x, int y);
double x, double y);
GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel,
double x, double y,
double *found_x,
......@@ -380,8 +380,8 @@ void _gdk_synthesize_crossing_events (GdkDisplay *display,
GdkDevice *device,
GdkDevice *source_device,
GdkCrossingMode mode,
gint toplevel_x,
gint toplevel_y,
gdouble toplevel_x,
gdouble toplevel_y,
GdkModifierType mask,
guint32 time_,
GdkEvent *event_in_queue,
......
......@@ -280,12 +280,12 @@ gdk_offscreen_window_get_root_coords (GdkWindow *window,
static gboolean
gdk_offscreen_window_get_device_state (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
GdkOffscreenWindow *offscreen;
int tmpx, tmpy;
double tmpx, tmpy;
double dtmpx, dtmpy;
GdkModifierType tmpmask;
......@@ -296,18 +296,18 @@ gdk_offscreen_window_get_device_state (GdkWindow *window,
offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
if (offscreen->embedder != NULL)
{
gdk_window_get_device_position (offscreen->embedder, device, &tmpx, &tmpy, &tmpmask);
gdk_window_get_device_position_double (offscreen->embedder, device, &tmpx, &tmpy, &tmpmask);
from_embedder (window,
tmpx, tmpy,
&dtmpx, &dtmpy);
tmpx = floor (dtmpx + 0.5);
tmpy = floor (dtmpy + 0.5);
tmpx = dtmpx;
tmpy = dtmpy;
}
if (x)
*x = tmpx;
*x = round (tmpx);
if (y)
*y = tmpy;
*y = round (tmpy);
if (mask)
*mask = tmpmask;
return TRUE;
......
......@@ -4426,30 +4426,30 @@ gdk_window_get_pointer (GdkWindow *window,
}
/**
* gdk_window_get_device_position:
* gdk_window_get_device_position_double:
* @window: a #GdkWindow.
* @device: pointer #GdkDevice to query to.
* @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
* @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
* @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
*
* Obtains the current device position and modifier state.
* Obtains the current device position in doubles and modifier state.
* The position is given in coordinates relative to the upper left
* corner of @window.
*
* Return value: (transfer none): The window underneath @device (as with
* gdk_device_get_window_at_position()), or %NULL if the window is not known to GDK.
*
* Since: 3.0
* Since: 3.10
**/
GdkWindow *
gdk_window_get_device_position (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
GdkModifierType *mask)
gdk_window_get_device_position_double (GdkWindow *window,
GdkDevice *device,
double *x,
double *y,
GdkModifierType *mask)
{
gint tmp_x, tmp_y;
gdouble tmp_x, tmp_y;
GdkModifierType tmp_mask;
gboolean normal_child;
......@@ -4479,6 +4479,44 @@ gdk_window_get_device_position (GdkWindow *window,
return NULL;
}
/**
* gdk_window_get_device_position:
* @window: a #GdkWindow.
* @device: pointer #GdkDevice to query to.
* @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
* @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
* @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
*
* Obtains the current device position and modifier state.
* The position is given in coordinates relative to the upper left
* corner of @window.
*
* Use gdk_window_get_device_position_double() if you need subpixel precision.
*
* Return value: (transfer none): The window underneath @device (as with
* gdk_device_get_window_at_position()), or %NULL if the window is not known to GDK.
*
* Since: 3.0
**/
GdkWindow *
gdk_window_get_device_position (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
GdkModifierType *mask)
{
gdouble tmp_x, tmp_y;
window = gdk_window_get_device_position_double (window, device,
&tmp_x, &tmp_y, mask);
if (x)
*x = round (tmp_x);
if (y)
*y = round (tmp_y);
return window;
}
/**
* gdk_get_default_root_window:
*
......@@ -6954,8 +6992,8 @@ pick_embedded_child (GdkWindow *window,
GdkWindow *
_gdk_window_find_child_at (GdkWindow *window,
int x,
int y)
double x,
double y)
{
GdkWindow *sub;
double child_x, child_y;
......@@ -7396,8 +7434,8 @@ send_crossing_event (GdkDisplay *display,
GdkWindow *subwindow,
GdkDevice *device,
GdkDevice *source_device,
gint toplevel_x,
gint toplevel_y,
gdouble toplevel_x,
gdouble toplevel_y,
GdkModifierType mask,
guint32 time_,
GdkEvent *event_in_queue,
......@@ -7512,8 +7550,8 @@ _gdk_synthesize_crossing_events (GdkDisplay *display,
GdkDevice *device,
GdkDevice *source_device,
GdkCrossingMode mode,
gint toplevel_x,
gint toplevel_y,
double toplevel_x,
double toplevel_y,
GdkModifierType mask,
guint32 time_,
GdkEvent *event_in_queue,
......
......@@ -845,6 +845,12 @@ GdkWindow * gdk_window_get_device_position (GdkWindow *window,
gint *x,
gint *y,
GdkModifierType *mask);
GDK_AVAILABLE_IN_3_10
GdkWindow * gdk_window_get_device_position_double (GdkWindow *window,
GdkDevice *device,
gdouble *x,
gdouble *y,
GdkModifierType *mask);
GDK_AVAILABLE_IN_ALL
GdkWindow * gdk_window_get_parent (GdkWindow *window);
GDK_AVAILABLE_IN_ALL
......
......@@ -98,8 +98,8 @@ struct _GdkWindowImplClass
gint *root_y);
gboolean (* get_device_state) (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask);
gboolean (* begin_paint_region) (GdkWindow *window,
const cairo_region_t *region);
......
......@@ -58,10 +58,10 @@ static void gdk_quartz_device_core_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_quartz_device_core_grab (GdkDevice *device,
GdkWindow *window,
......@@ -73,8 +73,8 @@ static GdkGrabStatus gdk_quartz_device_core_grab (GdkDevice *device,
static void gdk_quartz_device_core_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_quartz_device_core_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_quartz_device_core_select_window_events (GdkDevice *device,
......@@ -181,8 +181,8 @@ gdk_quartz_device_core_set_window_cursor (GdkDevice *device,
static void
gdk_quartz_device_core_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)