mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-13 05:50:10 +00:00
gdk: Add gdk_cursor_new_from_surface
We need this to be able to handle scaled cursor images. We implement the new _from_pixbuf by converting to a surface and assuming the scale was 1.
This commit is contained in:
parent
71fe43543c
commit
b2113b7384
@ -118,10 +118,10 @@ _gdk_broadway_cursor_update_theme (GdkCursor *cursor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GdkCursor *
|
GdkCursor *
|
||||||
_gdk_broadway_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
_gdk_broadway_display_get_cursor_for_surface (GdkDisplay *display,
|
||||||
GdkPixbuf *pixbuf,
|
cairo_surface_t *surface,
|
||||||
gint x,
|
gdouble x,
|
||||||
gint y)
|
gdouble y)
|
||||||
{
|
{
|
||||||
GdkBroadwayCursor *private;
|
GdkBroadwayCursor *private;
|
||||||
GdkCursor *cursor;
|
GdkCursor *cursor;
|
||||||
|
@ -375,7 +375,7 @@ gdk_broadway_display_class_init (GdkBroadwayDisplayClass * class)
|
|||||||
display_class->list_devices = gdk_broadway_display_list_devices;
|
display_class->list_devices = gdk_broadway_display_list_devices;
|
||||||
display_class->get_cursor_for_type = _gdk_broadway_display_get_cursor_for_type;
|
display_class->get_cursor_for_type = _gdk_broadway_display_get_cursor_for_type;
|
||||||
display_class->get_cursor_for_name = _gdk_broadway_display_get_cursor_for_name;
|
display_class->get_cursor_for_name = _gdk_broadway_display_get_cursor_for_name;
|
||||||
display_class->get_cursor_for_pixbuf = _gdk_broadway_display_get_cursor_for_pixbuf;
|
display_class->get_cursor_for_surface = _gdk_broadway_display_get_cursor_for_surface;
|
||||||
display_class->get_default_cursor_size = _gdk_broadway_display_get_default_cursor_size;
|
display_class->get_default_cursor_size = _gdk_broadway_display_get_default_cursor_size;
|
||||||
display_class->get_maximal_cursor_size = _gdk_broadway_display_get_maximal_cursor_size;
|
display_class->get_maximal_cursor_size = _gdk_broadway_display_get_maximal_cursor_size;
|
||||||
display_class->supports_cursor_alpha = _gdk_broadway_display_supports_cursor_alpha;
|
display_class->supports_cursor_alpha = _gdk_broadway_display_supports_cursor_alpha;
|
||||||
|
@ -125,10 +125,10 @@ GdkCursor*_gdk_broadway_display_get_cursor_for_type (GdkDisplay *display,
|
|||||||
GdkCursorType cursor_type);
|
GdkCursorType cursor_type);
|
||||||
GdkCursor*_gdk_broadway_display_get_cursor_for_name (GdkDisplay *display,
|
GdkCursor*_gdk_broadway_display_get_cursor_for_name (GdkDisplay *display,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
GdkCursor *_gdk_broadway_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
GdkCursor *_gdk_broadway_display_get_cursor_for_surface (GdkDisplay *display,
|
||||||
GdkPixbuf *pixbuf,
|
cairo_surface_t *surface,
|
||||||
gint x,
|
gdouble x,
|
||||||
gint y);
|
gdouble y);
|
||||||
gboolean _gdk_broadway_display_supports_cursor_alpha (GdkDisplay *display);
|
gboolean _gdk_broadway_display_supports_cursor_alpha (GdkDisplay *display);
|
||||||
gboolean _gdk_broadway_display_supports_cursor_color (GdkDisplay *display);
|
gboolean _gdk_broadway_display_supports_cursor_color (GdkDisplay *display);
|
||||||
void _gdk_broadway_display_get_default_cursor_size (GdkDisplay *display,
|
void _gdk_broadway_display_get_default_cursor_size (GdkDisplay *display,
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "gdkinternals.h"
|
#include "gdkinternals.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:cursors
|
* SECTION:cursors
|
||||||
@ -351,12 +352,81 @@ gdk_cursor_new_from_pixbuf (GdkDisplay *display,
|
|||||||
gint x,
|
gint x,
|
||||||
gint y)
|
gint y)
|
||||||
{
|
{
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
const char *option;
|
||||||
|
char *end;
|
||||||
|
gint64 value;
|
||||||
|
|
||||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
||||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
||||||
|
|
||||||
return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_pixbuf (display, pixbuf, x, y);
|
if (x == -1 && (option = gdk_pixbuf_get_option (pixbuf, "x_hot")))
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
end = NULL;
|
||||||
|
value = g_ascii_strtoll (option, &end, 10);
|
||||||
|
if (errno == 0 &&
|
||||||
|
end != option &&
|
||||||
|
value >= 0 && value < G_MAXINT)
|
||||||
|
x = (gint) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y == -1 && (option = gdk_pixbuf_get_option (pixbuf, "y_hot")))
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
end = NULL;
|
||||||
|
value = g_ascii_strtoll (option, &end, 10);
|
||||||
|
if (errno == 0 &&
|
||||||
|
end != option &&
|
||||||
|
value >= 0 && value < G_MAXINT)
|
||||||
|
y = (gint) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
|
||||||
|
|
||||||
|
return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_surface (display, surface, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_cursor_new_from_surface:
|
||||||
|
* @display: the #GdkDisplay for which the cursor will be created
|
||||||
|
* @surface: the cairo image surface containing the cursor pixel data
|
||||||
|
* @x: the horizontal offset of the 'hotspot' of the cursor.
|
||||||
|
* @y: the vertical offset of the 'hotspot' of the cursor.
|
||||||
|
*
|
||||||
|
* Creates a new cursor from a pixbuf.
|
||||||
|
*
|
||||||
|
* Not all GDK backends support RGBA cursors. If they are not
|
||||||
|
* supported, a monochrome approximation will be displayed.
|
||||||
|
* The functions gdk_display_supports_cursor_alpha() and
|
||||||
|
* gdk_display_supports_cursor_color() can be used to determine
|
||||||
|
* whether RGBA cursors are supported;
|
||||||
|
* gdk_display_get_default_cursor_size() and
|
||||||
|
* gdk_display_get_maximal_cursor_size() give information about
|
||||||
|
* cursor sizes.
|
||||||
|
*
|
||||||
|
* On the X backend, support for RGBA cursors requires a
|
||||||
|
* sufficently new version of the X Render extension.
|
||||||
|
*
|
||||||
|
* Returns: a new #GdkCursor.
|
||||||
|
*
|
||||||
|
* Since: 3.10
|
||||||
|
*/
|
||||||
|
GdkCursor *
|
||||||
|
gdk_cursor_new_from_surface (GdkDisplay *display,
|
||||||
|
cairo_surface_t *surface,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
||||||
|
g_return_val_if_fail (surface != NULL, NULL);
|
||||||
|
g_return_val_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
|
||||||
|
g_return_val_if_fail (0 <= x && x < cairo_image_surface_get_width (surface), NULL);
|
||||||
|
g_return_val_if_fail (0 <= y && y < cairo_image_surface_get_height (surface), NULL);
|
||||||
|
|
||||||
|
return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_surface (display,
|
||||||
|
surface, x, y);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* gdk_cursor_get_display:
|
* gdk_cursor_get_display:
|
||||||
* @cursor: a #GdkCursor.
|
* @cursor: a #GdkCursor.
|
||||||
|
@ -228,6 +228,11 @@ GdkCursor* gdk_cursor_new_from_pixbuf (GdkDisplay *display,
|
|||||||
GdkPixbuf *pixbuf,
|
GdkPixbuf *pixbuf,
|
||||||
gint x,
|
gint x,
|
||||||
gint y);
|
gint y);
|
||||||
|
GDK_AVAILABLE_IN_3_10
|
||||||
|
GdkCursor* gdk_cursor_new_from_surface (GdkDisplay *display,
|
||||||
|
cairo_surface_t *surface,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y);
|
||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
GdkCursor* gdk_cursor_new_from_name (GdkDisplay *display,
|
GdkCursor* gdk_cursor_new_from_name (GdkDisplay *display,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
|
@ -170,10 +170,10 @@ struct _GdkDisplayClass
|
|||||||
GdkCursorType type);
|
GdkCursorType type);
|
||||||
GdkCursor * (*get_cursor_for_name) (GdkDisplay *display,
|
GdkCursor * (*get_cursor_for_name) (GdkDisplay *display,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
GdkCursor * (*get_cursor_for_pixbuf) (GdkDisplay *display,
|
GdkCursor * (*get_cursor_for_surface) (GdkDisplay *display,
|
||||||
GdkPixbuf *pixbuf,
|
cairo_surface_t *surface,
|
||||||
gint x,
|
gdouble x,
|
||||||
gint y);
|
gdouble y);
|
||||||
|
|
||||||
GList * (*list_devices) (GdkDisplay *display);
|
GList * (*list_devices) (GdkDisplay *display);
|
||||||
GdkAppLaunchContext * (*get_app_launch_context) (GdkDisplay *display);
|
GdkAppLaunchContext * (*get_app_launch_context) (GdkDisplay *display);
|
||||||
|
@ -55,9 +55,9 @@ struct _GdkWaylandCursor
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int hotspot_x, hotspot_y;
|
int hotspot_x, hotspot_y;
|
||||||
int width, height;
|
int width, height, scale;
|
||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
} pixbuf;
|
} surface;
|
||||||
|
|
||||||
struct wl_cursor *wl_cursor;
|
struct wl_cursor *wl_cursor;
|
||||||
};
|
};
|
||||||
@ -168,8 +168,8 @@ gdk_wayland_cursor_finalize (GObject *object)
|
|||||||
GdkWaylandCursor *cursor = GDK_WAYLAND_CURSOR (object);
|
GdkWaylandCursor *cursor = GDK_WAYLAND_CURSOR (object);
|
||||||
|
|
||||||
g_free (cursor->name);
|
g_free (cursor->name);
|
||||||
if (cursor->pixbuf.buffer)
|
if (cursor->surface.buffer)
|
||||||
wl_buffer_destroy (cursor->pixbuf.buffer);
|
wl_buffer_destroy (cursor->surface.buffer);
|
||||||
|
|
||||||
G_OBJECT_CLASS (_gdk_wayland_cursor_parent_class)->finalize (object);
|
G_OBJECT_CLASS (_gdk_wayland_cursor_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
@ -188,7 +188,8 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
|||||||
int *hotspot_x,
|
int *hotspot_x,
|
||||||
int *hotspot_y,
|
int *hotspot_y,
|
||||||
int *w,
|
int *w,
|
||||||
int *h)
|
int *h,
|
||||||
|
int *scale)
|
||||||
{
|
{
|
||||||
GdkWaylandCursor *wayland_cursor = GDK_WAYLAND_CURSOR (cursor);
|
GdkWaylandCursor *wayland_cursor = GDK_WAYLAND_CURSOR (cursor);
|
||||||
|
|
||||||
@ -211,18 +212,20 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
|||||||
|
|
||||||
*w = image->width;
|
*w = image->width;
|
||||||
*h = image->height;
|
*h = image->height;
|
||||||
|
*scale = 1;
|
||||||
|
|
||||||
return wl_cursor_image_get_buffer (image);
|
return wl_cursor_image_get_buffer (image);
|
||||||
}
|
}
|
||||||
else /* From pixbuf */
|
else /* From surface */
|
||||||
{
|
{
|
||||||
*hotspot_x = wayland_cursor->pixbuf.hotspot_x;
|
*hotspot_x = wayland_cursor->surface.hotspot_x;
|
||||||
*hotspot_y = wayland_cursor->pixbuf.hotspot_y;
|
*hotspot_y = wayland_cursor->surface.hotspot_y;
|
||||||
|
|
||||||
*w = wayland_cursor->pixbuf.width;
|
*w = wayland_cursor->surface.width / wayland_cursor->surface.scale;
|
||||||
*h = wayland_cursor->pixbuf.height;
|
*h = wayland_cursor->surface.height / wayland_cursor->surface.scale;
|
||||||
|
*scale = wayland_cursor->surface.scale;
|
||||||
|
|
||||||
return wayland_cursor->pixbuf.buffer;
|
return wayland_cursor->surface.buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,60 +271,6 @@ _gdk_wayland_cursor_init (GdkWaylandCursor *cursor)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to implement from_pixbuf below */
|
|
||||||
static void
|
|
||||||
set_pixbuf (gpointer argb_pixels, int width, int height, GdkPixbuf *pixbuf)
|
|
||||||
{
|
|
||||||
int stride, i, n_channels;
|
|
||||||
unsigned char *pixels, *end, *s, *d;
|
|
||||||
|
|
||||||
stride = gdk_pixbuf_get_rowstride(pixbuf);
|
|
||||||
pixels = gdk_pixbuf_get_pixels(pixbuf);
|
|
||||||
n_channels = gdk_pixbuf_get_n_channels(pixbuf);
|
|
||||||
|
|
||||||
#define MULT(_d,c,a,t) \
|
|
||||||
do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
|
|
||||||
|
|
||||||
if (n_channels == 4)
|
|
||||||
{
|
|
||||||
for (i = 0; i < height; i++)
|
|
||||||
{
|
|
||||||
s = pixels + i * stride;
|
|
||||||
end = s + width * 4;
|
|
||||||
d = argb_pixels + i * width * 4;
|
|
||||||
while (s < end)
|
|
||||||
{
|
|
||||||
unsigned int t;
|
|
||||||
|
|
||||||
MULT(d[0], s[2], s[3], t);
|
|
||||||
MULT(d[1], s[1], s[3], t);
|
|
||||||
MULT(d[2], s[0], s[3], t);
|
|
||||||
d[3] = s[3];
|
|
||||||
s += 4;
|
|
||||||
d += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (n_channels == 3)
|
|
||||||
{
|
|
||||||
for (i = 0; i < height; i++)
|
|
||||||
{
|
|
||||||
s = pixels + i * stride;
|
|
||||||
end = s + width * 3;
|
|
||||||
d = argb_pixels + i * width * 4;
|
|
||||||
while (s < end)
|
|
||||||
{
|
|
||||||
d[0] = s[2];
|
|
||||||
d[1] = s[1];
|
|
||||||
d[2] = s[0];
|
|
||||||
d[3] = 0xff;
|
|
||||||
s += 3;
|
|
||||||
d += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GdkCursor *
|
GdkCursor *
|
||||||
_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display,
|
_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display,
|
||||||
GdkCursorType cursor_type)
|
GdkCursorType cursor_type)
|
||||||
@ -382,10 +331,10 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GdkCursor *
|
GdkCursor *
|
||||||
_gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
|
||||||
GdkPixbuf *pixbuf,
|
cairo_surface_t *surface,
|
||||||
gint x,
|
gdouble x,
|
||||||
gint y)
|
gdouble y)
|
||||||
{
|
{
|
||||||
GdkWaylandCursor *cursor;
|
GdkWaylandCursor *cursor;
|
||||||
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display);
|
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display);
|
||||||
@ -393,11 +342,8 @@ _gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
|||||||
size_t size;
|
size_t size;
|
||||||
gpointer data;
|
gpointer data;
|
||||||
struct wl_shm_pool *pool;
|
struct wl_shm_pool *pool;
|
||||||
|
cairo_surface_t *buffer_surface;
|
||||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
cairo_t *cr;
|
||||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
|
||||||
g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL);
|
|
||||||
g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL);
|
|
||||||
|
|
||||||
cursor = g_object_new (GDK_TYPE_WAYLAND_CURSOR,
|
cursor = g_object_new (GDK_TYPE_WAYLAND_CURSOR,
|
||||||
"cursor-type", GDK_CURSOR_IS_PIXMAP,
|
"cursor-type", GDK_CURSOR_IS_PIXMAP,
|
||||||
@ -405,35 +351,55 @@ _gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
|||||||
NULL);
|
NULL);
|
||||||
cursor->name = NULL;
|
cursor->name = NULL;
|
||||||
cursor->serial = theme_serial;
|
cursor->serial = theme_serial;
|
||||||
cursor->pixbuf.hotspot_x = x;
|
cursor->surface.hotspot_x = x;
|
||||||
cursor->pixbuf.hotspot_y = y;
|
cursor->surface.hotspot_y = y;
|
||||||
|
|
||||||
if (pixbuf)
|
cursor->surface.scale = 1;
|
||||||
|
|
||||||
|
if (surface)
|
||||||
{
|
{
|
||||||
cursor->pixbuf.width = gdk_pixbuf_get_width (pixbuf);
|
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
|
||||||
cursor->pixbuf.height = gdk_pixbuf_get_height (pixbuf);
|
{
|
||||||
|
double sx, sy;
|
||||||
|
cairo_surface_get_device_scale (surface, &sx, &sy);
|
||||||
|
cursor->surface.scale = (int)sx;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cursor->surface.width = cairo_image_surface_get_width (surface);
|
||||||
|
cursor->surface.height = cairo_image_surface_get_height (surface);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cursor->pixbuf.width = 1;
|
cursor->surface.width = 1;
|
||||||
cursor->pixbuf.height = 1;
|
cursor->surface.height = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = _create_shm_pool (wayland_display->shm,
|
pool = _create_shm_pool (wayland_display->shm,
|
||||||
cursor->pixbuf.width,
|
cursor->surface.width,
|
||||||
cursor->pixbuf.height,
|
cursor->surface.height,
|
||||||
&size,
|
&size,
|
||||||
&data);
|
&data);
|
||||||
|
|
||||||
if (pixbuf)
|
if (surface)
|
||||||
set_pixbuf (data, cursor->pixbuf.width, cursor->pixbuf.height, pixbuf);
|
{
|
||||||
|
buffer_surface = cairo_image_surface_create_for_data (data,
|
||||||
|
CAIRO_FORMAT_ARGB32,
|
||||||
|
cursor->surface.width,
|
||||||
|
cursor->surface.height,
|
||||||
|
cursor->surface.width * 4);
|
||||||
|
cr = cairo_create (buffer_surface);
|
||||||
|
cairo_set_source_surface (cr, surface, 0, 0);
|
||||||
|
cairo_paint (cr);
|
||||||
|
cairo_destroy (cr);
|
||||||
|
cairo_surface_destroy (buffer_surface);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
memset (data, 0, 4);
|
memset (data, 0, 4);
|
||||||
|
|
||||||
stride = cursor->pixbuf.width * 4;
|
stride = cursor->surface.width * 4;
|
||||||
cursor->pixbuf.buffer = wl_shm_pool_create_buffer (pool, 0,
|
cursor->surface.buffer = wl_shm_pool_create_buffer (pool, 0,
|
||||||
cursor->pixbuf.width,
|
cursor->surface.width,
|
||||||
cursor->pixbuf.height,
|
cursor->surface.height,
|
||||||
stride,
|
stride,
|
||||||
WL_SHM_FORMAT_ARGB8888);
|
WL_SHM_FORMAT_ARGB8888);
|
||||||
|
|
||||||
|
@ -161,16 +161,17 @@ static gboolean
|
|||||||
gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
|
gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
|
||||||
{
|
{
|
||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
int x, y, w, h;
|
int x, y, w, h, scale;
|
||||||
guint next_image_index, next_image_delay;
|
guint next_image_index, next_image_delay;
|
||||||
|
|
||||||
buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, wd->cursor_image_index,
|
buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, wd->cursor_image_index,
|
||||||
&x, &y, &w, &h);
|
&x, &y, &w, &h, &scale);
|
||||||
wl_pointer_set_cursor (wd->wl_pointer,
|
wl_pointer_set_cursor (wd->wl_pointer,
|
||||||
wd->enter_serial,
|
wd->enter_serial,
|
||||||
wd->pointer_surface,
|
wd->pointer_surface,
|
||||||
x, y);
|
x, y);
|
||||||
wl_surface_attach (wd->pointer_surface, buffer, 0, 0);
|
wl_surface_attach (wd->pointer_surface, buffer, 0, 0);
|
||||||
|
wl_surface_set_buffer_scale (wd->pointer_surface, scale);
|
||||||
wl_surface_damage (wd->pointer_surface, 0, 0, w, h);
|
wl_surface_damage (wd->pointer_surface, 0, 0, w, h);
|
||||||
wl_surface_commit (wd->pointer_surface);
|
wl_surface_commit (wd->pointer_surface);
|
||||||
|
|
||||||
|
@ -587,7 +587,7 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass * class)
|
|||||||
display_class->get_maximal_cursor_size = _gdk_wayland_display_get_maximal_cursor_size;
|
display_class->get_maximal_cursor_size = _gdk_wayland_display_get_maximal_cursor_size;
|
||||||
display_class->get_cursor_for_type = _gdk_wayland_display_get_cursor_for_type;
|
display_class->get_cursor_for_type = _gdk_wayland_display_get_cursor_for_type;
|
||||||
display_class->get_cursor_for_name = _gdk_wayland_display_get_cursor_for_name;
|
display_class->get_cursor_for_name = _gdk_wayland_display_get_cursor_for_name;
|
||||||
display_class->get_cursor_for_pixbuf = _gdk_wayland_display_get_cursor_for_pixbuf;
|
display_class->get_cursor_for_surface = _gdk_wayland_display_get_cursor_for_surface;
|
||||||
display_class->supports_cursor_alpha = _gdk_wayland_display_supports_cursor_alpha;
|
display_class->supports_cursor_alpha = _gdk_wayland_display_supports_cursor_alpha;
|
||||||
display_class->supports_cursor_color = _gdk_wayland_display_supports_cursor_color;
|
display_class->supports_cursor_color = _gdk_wayland_display_supports_cursor_color;
|
||||||
display_class->before_process_all_updates = gdk_wayland_display_before_process_all_updates;
|
display_class->before_process_all_updates = gdk_wayland_display_before_process_all_updates;
|
||||||
|
@ -63,10 +63,10 @@ GdkCursor *_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display,
|
|||||||
GdkCursorType cursor_type);
|
GdkCursorType cursor_type);
|
||||||
GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
GdkCursor *_gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
GdkCursor *_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
|
||||||
GdkPixbuf *pixbuf,
|
cairo_surface_t *surface,
|
||||||
gint x,
|
gdouble x,
|
||||||
gint y);
|
gdouble y);
|
||||||
void _gdk_wayland_display_get_default_cursor_size (GdkDisplay *display,
|
void _gdk_wayland_display_get_default_cursor_size (GdkDisplay *display,
|
||||||
guint *width,
|
guint *width,
|
||||||
guint *height);
|
guint *height);
|
||||||
@ -81,7 +81,8 @@ struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
|||||||
int *hotspot_x,
|
int *hotspot_x,
|
||||||
int *hotspot_y,
|
int *hotspot_y,
|
||||||
int *w,
|
int *w,
|
||||||
int *h);
|
int *h,
|
||||||
|
int *scale);
|
||||||
guint _gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor,
|
guint _gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor,
|
||||||
guint current_image_index,
|
guint current_image_index,
|
||||||
guint *next_image_delay);
|
guint *next_image_delay);
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
struct _GdkX11Cursor
|
struct _GdkX11Cursor
|
||||||
{
|
{
|
||||||
@ -514,23 +515,46 @@ _gdk_x11_cursor_update_theme (GdkCursor *cursor)
|
|||||||
|
|
||||||
#ifdef HAVE_XCURSOR
|
#ifdef HAVE_XCURSOR
|
||||||
|
|
||||||
static XcursorImage*
|
static void
|
||||||
create_cursor_image (GdkPixbuf *pixbuf,
|
get_surface_size (cairo_surface_t *surface,
|
||||||
gint x,
|
int *width,
|
||||||
gint y)
|
int *height)
|
||||||
{
|
{
|
||||||
guint width, height;
|
double x_scale, y_scale;
|
||||||
|
|
||||||
|
x_scale = y_scale = 1;
|
||||||
|
|
||||||
|
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
|
||||||
|
cairo_surface_get_device_scale (surface, &x_scale, &y_scale);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Assume any set scaling is icon scale */
|
||||||
|
*width =
|
||||||
|
ceil (cairo_image_surface_get_width (surface) / x_scale);
|
||||||
|
*height =
|
||||||
|
ceil (cairo_image_surface_get_height (surface) / y_scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XcursorImage*
|
||||||
|
create_cursor_image (cairo_surface_t *source_surface,
|
||||||
|
gint x,
|
||||||
|
gint y,
|
||||||
|
gint scale)
|
||||||
|
{
|
||||||
|
gint width, height;
|
||||||
XcursorImage *xcimage;
|
XcursorImage *xcimage;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
|
||||||
width = gdk_pixbuf_get_width (pixbuf);
|
get_surface_size (source_surface, &width, &height);
|
||||||
height = gdk_pixbuf_get_height (pixbuf);
|
|
||||||
|
width *= scale;
|
||||||
|
height *= scale;
|
||||||
|
|
||||||
xcimage = XcursorImageCreate (width, height);
|
xcimage = XcursorImageCreate (width, height);
|
||||||
|
|
||||||
xcimage->xhot = x;
|
xcimage->xhot = x * scale;
|
||||||
xcimage->yhot = y;
|
xcimage->yhot = y * scale;
|
||||||
|
|
||||||
surface = cairo_image_surface_create_for_data ((guchar *) xcimage->pixels,
|
surface = cairo_image_surface_create_for_data ((guchar *) xcimage->pixels,
|
||||||
CAIRO_FORMAT_ARGB32,
|
CAIRO_FORMAT_ARGB32,
|
||||||
@ -538,53 +562,30 @@ create_cursor_image (GdkPixbuf *pixbuf,
|
|||||||
height,
|
height,
|
||||||
width * 4);
|
width * 4);
|
||||||
|
|
||||||
|
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
|
||||||
|
cairo_surface_set_device_scale (surface, scale, scale);
|
||||||
|
#endif
|
||||||
|
|
||||||
cr = cairo_create (surface);
|
cr = cairo_create (surface);
|
||||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
cairo_set_source_surface (cr, source_surface, 0, 0);
|
||||||
cairo_paint (cr);
|
cairo_paint (cr);
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
|
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
|
|
||||||
return xcimage;
|
return xcimage;
|
||||||
}
|
}
|
||||||
|
|
||||||
GdkCursor *
|
GdkCursor *
|
||||||
_gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display,
|
||||||
GdkPixbuf *pixbuf,
|
cairo_surface_t *surface,
|
||||||
gint x,
|
gdouble x,
|
||||||
gint y)
|
gdouble y)
|
||||||
{
|
{
|
||||||
XcursorImage *xcimage;
|
XcursorImage *xcimage;
|
||||||
Cursor xcursor;
|
Cursor xcursor;
|
||||||
GdkX11Cursor *private;
|
GdkX11Cursor *private;
|
||||||
const char *option;
|
int target_scale;
|
||||||
char *end;
|
|
||||||
gint64 value;
|
|
||||||
|
|
||||||
if (x == -1 && (option = gdk_pixbuf_get_option (pixbuf, "x_hot")))
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
end = NULL;
|
|
||||||
value = g_ascii_strtoll (option, &end, 10);
|
|
||||||
if (errno == 0 &&
|
|
||||||
end != option &&
|
|
||||||
value >= 0 && value < G_MAXINT)
|
|
||||||
x = (gint) value;
|
|
||||||
}
|
|
||||||
if (y == -1 && (option = gdk_pixbuf_get_option (pixbuf, "y_hot")))
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
end = NULL;
|
|
||||||
value = g_ascii_strtoll (option, &end, 10);
|
|
||||||
if (errno == 0 &&
|
|
||||||
end != option &&
|
|
||||||
value >= 0 && value < G_MAXINT)
|
|
||||||
y = (gint) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL);
|
|
||||||
g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL);
|
|
||||||
|
|
||||||
if (gdk_display_is_closed (display))
|
if (gdk_display_is_closed (display))
|
||||||
{
|
{
|
||||||
@ -592,7 +593,9 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xcimage = create_cursor_image (pixbuf, x, y);
|
target_scale =
|
||||||
|
gdk_screen_get_monitor_scale_factor (gdk_display_get_default_screen (display), 0);
|
||||||
|
xcimage = create_cursor_image (surface, x, y, target_scale);
|
||||||
xcursor = XcursorImageLoadCursor (GDK_DISPLAY_XDISPLAY (display), xcimage);
|
xcursor = XcursorImageLoadCursor (GDK_DISPLAY_XDISPLAY (display), xcimage);
|
||||||
XcursorImageDestroy (xcimage);
|
XcursorImageDestroy (xcimage);
|
||||||
}
|
}
|
||||||
@ -714,10 +717,10 @@ gdk_cursor_new_from_pixmap (GdkDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GdkCursor *
|
GdkCursor *
|
||||||
_gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display,
|
||||||
GdkPixbuf *pixbuf,
|
cairo_surface_t *surface,
|
||||||
gint x,
|
gdouble x,
|
||||||
gint y)
|
gdouble y)
|
||||||
{
|
{
|
||||||
GdkCursor *cursor;
|
GdkCursor *cursor;
|
||||||
cairo_surface_t *pixmap, *mask;
|
cairo_surface_t *pixmap, *mask;
|
||||||
@ -728,13 +731,18 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
|||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
cairo_surface_t *image;
|
cairo_surface_t *image;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
|
||||||
width = gdk_pixbuf_get_width (pixbuf);
|
width = cairo_image_surface_get_width (surface);
|
||||||
height = gdk_pixbuf_get_height (pixbuf);
|
height = cairo_image_surface_get_height (surface);
|
||||||
|
|
||||||
g_return_val_if_fail (0 <= x && x < width, NULL);
|
g_return_val_if_fail (0 <= x && x < width, NULL);
|
||||||
g_return_val_if_fail (0 <= y && y < height, NULL);
|
g_return_val_if_fail (0 <= y && y < height, NULL);
|
||||||
|
|
||||||
|
/* Note: This does not support scaled surfaced, if you need that you
|
||||||
|
want XCursor anyway */
|
||||||
|
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
|
||||||
|
|
||||||
n_channels = gdk_pixbuf_get_n_channels (pixbuf);
|
n_channels = gdk_pixbuf_get_n_channels (pixbuf);
|
||||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||||
@ -766,6 +774,8 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_object_unref (pixbuf);
|
||||||
|
|
||||||
screen = gdk_display_get_default_screen (display);
|
screen = gdk_display_get_default_screen (display);
|
||||||
|
|
||||||
pixmap = _gdk_x11_window_create_bitmap_surface (gdk_screen_get_root_window (screen),
|
pixmap = _gdk_x11_window_create_bitmap_surface (gdk_screen_get_root_window (screen),
|
||||||
|
@ -2825,7 +2825,7 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
|
|||||||
display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
|
display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
|
||||||
display_class->get_cursor_for_type = _gdk_x11_display_get_cursor_for_type;
|
display_class->get_cursor_for_type = _gdk_x11_display_get_cursor_for_type;
|
||||||
display_class->get_cursor_for_name = _gdk_x11_display_get_cursor_for_name;
|
display_class->get_cursor_for_name = _gdk_x11_display_get_cursor_for_name;
|
||||||
display_class->get_cursor_for_pixbuf = _gdk_x11_display_get_cursor_for_pixbuf;
|
display_class->get_cursor_for_surface = _gdk_x11_display_get_cursor_for_surface;
|
||||||
display_class->get_default_cursor_size = _gdk_x11_display_get_default_cursor_size;
|
display_class->get_default_cursor_size = _gdk_x11_display_get_default_cursor_size;
|
||||||
display_class->get_maximal_cursor_size = _gdk_x11_display_get_maximal_cursor_size;
|
display_class->get_maximal_cursor_size = _gdk_x11_display_get_maximal_cursor_size;
|
||||||
display_class->supports_cursor_alpha = _gdk_x11_display_supports_cursor_alpha;
|
display_class->supports_cursor_alpha = _gdk_x11_display_supports_cursor_alpha;
|
||||||
|
@ -259,10 +259,10 @@ GdkCursor *_gdk_x11_display_get_cursor_for_type (GdkDisplay *display,
|
|||||||
GdkCursorType type);
|
GdkCursorType type);
|
||||||
GdkCursor *_gdk_x11_display_get_cursor_for_name (GdkDisplay *display,
|
GdkCursor *_gdk_x11_display_get_cursor_for_name (GdkDisplay *display,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
GdkCursor *_gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
|
GdkCursor *_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display,
|
||||||
GdkPixbuf *pixbuf,
|
cairo_surface_t *surface,
|
||||||
gint x,
|
gdouble x,
|
||||||
gint y);
|
gdouble y);
|
||||||
gboolean _gdk_x11_display_supports_cursor_alpha (GdkDisplay *display);
|
gboolean _gdk_x11_display_supports_cursor_alpha (GdkDisplay *display);
|
||||||
gboolean _gdk_x11_display_supports_cursor_color (GdkDisplay *display);
|
gboolean _gdk_x11_display_supports_cursor_color (GdkDisplay *display);
|
||||||
void _gdk_x11_display_get_default_cursor_size (GdkDisplay *display,
|
void _gdk_x11_display_get_default_cursor_size (GdkDisplay *display,
|
||||||
|
Loading…
Reference in New Issue
Block a user