cursor: Turn new_from_surface() into new_from_texture()

Also turn all the arguments into read-only properties on the GdkCursor
object.
This commit is contained in:
Benjamin Otte 2017-11-03 01:59:15 +01:00
parent 0cad0caf7d
commit 5adf21a17d
14 changed files with 219 additions and 133 deletions

View File

@ -829,6 +829,9 @@ gdk_cursor_new_from_surface
gdk_cursor_new_from_name
gdk_cursor_get_display
gdk_cursor_get_name
gdk_cursor_get_hotspot_x
gdk_cursor_get_hotspot_y
gdk_cursor_get_texture
<SUBSECTION Standard>
GDK_TYPE_CURSOR_TYPE

View File

@ -76,16 +76,19 @@ _gdk_broadway_cursor_update_theme (GdkCursor *cursor)
}
GdkCursor *
_gdk_broadway_display_get_cursor_for_surface (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y)
_gdk_broadway_display_get_cursor_for_texture (GdkDisplay *display,
GdkTexture *texture,
int x,
int y)
{
GdkBroadwayCursor *private;
GdkCursor *cursor;
private = g_object_new (GDK_TYPE_BROADWAY_CURSOR,
"display", display,
"texture", texture,
"x", x,
"y", y,
NULL);
cursor = (GdkCursor *) private;

View File

@ -359,7 +359,7 @@ gdk_broadway_display_class_init (GdkBroadwayDisplayClass * class)
display_class->supports_shapes = gdk_broadway_display_supports_shapes;
display_class->supports_input_shapes = gdk_broadway_display_supports_input_shapes;
display_class->get_cursor_for_name = _gdk_broadway_display_get_cursor_for_name;
display_class->get_cursor_for_surface = _gdk_broadway_display_get_cursor_for_surface;
display_class->get_cursor_for_texture = _gdk_broadway_display_get_cursor_for_texture;
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->supports_cursor_alpha = _gdk_broadway_display_supports_cursor_alpha;

View File

@ -101,10 +101,10 @@ GdkDragProtocol _gdk_broadway_window_get_drag_protocol (GdkWindow *window,
GdkWindow **target);
GdkCursor*_gdk_broadway_display_get_cursor_for_name (GdkDisplay *display,
const gchar *name);
GdkCursor *_gdk_broadway_display_get_cursor_for_surface (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y);
GdkCursor *_gdk_broadway_display_get_cursor_for_texture (GdkDisplay *display,
GdkTexture *texture,
int x,
int y);
gboolean _gdk_broadway_display_supports_cursor_alpha (GdkDisplay *display);
gboolean _gdk_broadway_display_supports_cursor_color (GdkDisplay *display);
void _gdk_broadway_display_get_default_cursor_size (GdkDisplay *display,

View File

@ -66,7 +66,10 @@
enum {
PROP_0,
PROP_DISPLAY,
PROP_NAME
PROP_HOTSPOT_X,
PROP_HOTSPOT_Y,
PROP_NAME,
PROP_TEXTURE,
};
G_DEFINE_ABSTRACT_TYPE (GdkCursor, gdk_cursor, G_TYPE_OBJECT)
@ -84,9 +87,18 @@ gdk_cursor_get_property (GObject *object,
case PROP_DISPLAY:
g_value_set_object (value, cursor->display);
break;
case PROP_HOTSPOT_X:
g_value_set_int (value, cursor->hotspot_x);
break;
case PROP_HOTSPOT_Y:
g_value_set_int (value, cursor->hotspot_y);
break;
case PROP_NAME:
g_value_set_string (value, cursor->name);
break;
case PROP_TEXTURE:
g_value_set_object (value, cursor->texture);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -108,9 +120,18 @@ gdk_cursor_set_property (GObject *object,
/* check that implementations actually provide the display when constructing */
g_assert (cursor->display != NULL);
break;
case PROP_HOTSPOT_X:
cursor->hotspot_x = g_value_get_int (value);
break;
case PROP_HOTSPOT_Y:
cursor->hotspot_y = g_value_get_int (value);
break;
case PROP_NAME:
cursor->name = g_value_dup_string (value);
break;
case PROP_TEXTURE:
cursor->texture = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -123,6 +144,7 @@ gdk_cursor_finalize (GObject *object)
GdkCursor *cursor = GDK_CURSOR (object);
g_free (cursor->name);
g_clear_object (&cursor->texture);
G_OBJECT_CLASS (gdk_cursor_parent_class)->finalize (object);
}
@ -143,6 +165,20 @@ gdk_cursor_class_init (GdkCursorClass *cursor_class)
P_("Display of this cursor"),
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_HOTSPOT_X,
g_param_spec_int ("hotspot-x",
P_("Hotspot X"),
P_("Horizontal offset of the cursor hotspot"),
0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_HOTSPOT_Y,
g_param_spec_int ("hotspot-y",
P_("Hotspot Y"),
P_("Vertical offset of the cursor hotspot"),
0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_NAME,
g_param_spec_string ("name",
@ -150,6 +186,13 @@ gdk_cursor_class_init (GdkCursorClass *cursor_class)
P_("Name of this cursor"),
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_TEXTURE,
g_param_spec_object ("texture",
P_("Texture"),
P_("The texture displayed by this cursor"),
GDK_TYPE_TEXTURE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
static void
@ -255,7 +298,7 @@ gdk_cursor_new_from_pixbuf (GdkDisplay *display,
gint x,
gint y)
{
cairo_surface_t *surface;
GdkTexture *texture;
const char *option;
char *end;
gint64 value;
@ -286,23 +329,23 @@ gdk_cursor_new_from_pixbuf (GdkDisplay *display,
y = (gint) value;
}
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
texture = gdk_texture_new_for_pixbuf (pixbuf);
cursor = GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_surface (display, surface, x, y);
cursor = gdk_cursor_new_from_texture (display, texture, x, y);
cairo_surface_destroy (surface);
g_object_unref (texture);
return cursor;
}
/**
* gdk_cursor_new_from_surface:
* gdk_cursor_new_from_texture:
* @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
* @texture: the texture providing the pixel data
* @hotspot_x: the horizontal offset of the hotspot of the cursor
* @hotspot_y: the vertical offset of the hotspot of the cursor
*
* Creates a new cursor from a cairo image surface.
* Creates a new cursor from a #GdkTexture.
*
* Not all GDK backends support RGBA cursors. If they are not
* supported, a monochrome approximation will be displayed.
@ -318,22 +361,22 @@ gdk_cursor_new_from_pixbuf (GdkDisplay *display,
*
* Returns: a new #GdkCursor.
*
* Since: 3.10
* Since: 3.94
*/
GdkCursor *
gdk_cursor_new_from_surface (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y)
gdk_cursor_new_from_texture (GdkDisplay *display,
GdkTexture *texture,
int hotspot_x,
int hotspot_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);
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
g_return_val_if_fail (0 <= hotspot_x && hotspot_x < gdk_texture_get_width (texture), NULL);
g_return_val_if_fail (0 <= hotspot_y && hotspot_y < gdk_texture_get_height (texture), NULL);
return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_surface (display,
surface, x, y);
return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_texture (display,
texture,
hotspot_x, hotspot_y);
}
/**
@ -359,7 +402,7 @@ gdk_cursor_get_display (GdkCursor *cursor)
* @cursor: a #GdkCursor.
*
* Returns the name of the cursor. If the cursor is not a named cursor, %NULL
* will be returned and the surface property will be set.
* will be returned and the GdkCursor::texture property will be set.
*
* Returns: (transfer none): the name of the cursor or %NULL if it is not
* a named cursor
@ -374,3 +417,81 @@ gdk_cursor_get_name (GdkCursor *cursor)
return cursor->name;
}
/**
* gdk_cursor_get_texture:
* @cursor: a #GdkCursor.
*
* Returns the texture shown by the cursor. If the cursor is a named cursor,
* %NULL will be returned and the GdkCursor::name property will be set.
*
* Returns: (transfer none): the texture of the cursor or %NULL if it is
* a named cursor
*
* Since: 3.94
*/
GdkTexture *
gdk_cursor_get_texture (GdkCursor *cursor)
{
g_return_val_if_fail (GDK_IS_CURSOR (cursor), NULL);
return cursor->texture;
}
/**
* gdk_cursor_get_texture:
* @cursor: a #GdkCursor.
*
* Returns the texture for the cursor. If the cursor is a named cursor, %NULL
* will be returned and the GdkCursor::name property will be set.
*
* Returns: (transfer none): the texture for cursor or %NULL if it is a
* named cursor
*
* Since: 3.94
*/
GdkTexture *
gdk_cursor_get_texture (GdkCursor *cursor)
{
g_return_val_if_fail (GDK_IS_CURSOR (cursor), NULL);
return cursor->texture;
}
/**
* gdk_cursor_get_hotspot_x:
* @cursor: a #GdkCursor.
*
* Returns the horizontal offset of the hotspot. The hotspot indicates the
* pixel that will be directly above the cursor.
*
* Returns: the horizontal offset of the hotspot or 0 for named cursors
*
* Since: 3.94
*/
int
gdk_cursor_get_hotspot_x (GdkCursor *cursor)
{
g_return_val_if_fail (GDK_IS_CURSOR (cursor), 0);
return cursor->hotspot_x;
}
/**
* gdk_cursor_get_hotspot_y:
* @cursor: a #GdkCursor.
*
* Returns the vertical offset of the hotspot. The hotspot indicates the
* pixel that will be directly above the cursor.
*
* Returns: the vertical offset of the hotspot or 0 for named cursors
*
* Since: 3.94
*/
int
gdk_cursor_get_hotspot_y (GdkCursor *cursor)
{
g_return_val_if_fail (GDK_IS_CURSOR (cursor), 0);
return cursor->hotspot_y;
}

View File

@ -50,11 +50,11 @@ GdkCursor* gdk_cursor_new_from_pixbuf (GdkDisplay *display,
GdkPixbuf *pixbuf,
gint x,
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_3_94
GdkCursor* gdk_cursor_new_from_texture (GdkDisplay *display,
GdkTexture *texture,
int hotspot_x,
int hotspot_y);
GDK_AVAILABLE_IN_ALL
GdkCursor* gdk_cursor_new_from_name (GdkDisplay *display,
const gchar *name);
@ -62,6 +62,12 @@ GDK_AVAILABLE_IN_ALL
GdkDisplay* gdk_cursor_get_display (GdkCursor *cursor);
GDK_AVAILABLE_IN_3_94
const char *gdk_cursor_get_name (GdkCursor *cursor);
GDK_AVAILABLE_IN_3_94
GdkTexture *gdk_cursor_get_texture (GdkCursor *cursor);
GDK_AVAILABLE_IN_3_94
int gdk_cursor_get_hotspot_x (GdkCursor *cursor);
GDK_AVAILABLE_IN_3_94
int gdk_cursor_get_hotspot_y (GdkCursor *cursor);
G_END_DECLS

View File

@ -41,6 +41,9 @@ struct _GdkCursor
GdkDisplay *display;
char *name;
GdkTexture *texture;
int hotspot_x;
int hotspot_y;
};
struct _GdkCursorClass

View File

@ -147,10 +147,10 @@ struct _GdkDisplayClass
guint *height);
GdkCursor * (*get_cursor_for_name) (GdkDisplay *display,
const gchar *name);
GdkCursor * (*get_cursor_for_surface) (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y);
GdkCursor * (*get_cursor_for_texture) (GdkDisplay *display,
GdkTexture *texture,
int x,
int y);
GdkAppLaunchContext * (*get_app_launch_context) (GdkDisplay *display);

View File

@ -52,7 +52,6 @@ struct _GdkWaylandCursor
struct
{
int hotspot_x, hotspot_y;
int width, height, scale;
cairo_surface_t *cairo_surface;
} surface;
@ -239,9 +238,9 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
else if (gdk_cursor_get_name (cursor) == NULL) /* From surface */
{
*hotspot_x =
wayland_cursor->surface.hotspot_x / wayland_cursor->surface.scale;
gdk_cursor_get_hotspot_x (cursor) / wayland_cursor->surface.scale;
*hotspot_y =
wayland_cursor->surface.hotspot_y / wayland_cursor->surface.scale;
gdk_cursor_get_hotspot_y (cursor) / wayland_cursor->surface.scale;
*w = wayland_cursor->surface.width / wayland_cursor->surface.scale;
*h = wayland_cursor->surface.height / wayland_cursor->surface.scale;
@ -384,37 +383,25 @@ static const struct wl_buffer_listener buffer_listener = {
};
GdkCursor *
_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y)
_gdk_wayland_display_get_cursor_for_texture (GdkDisplay *display,
GdkTexture *texture,
int x,
int y)
{
GdkWaylandCursor *cursor;
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
struct wl_buffer *buffer;
cairo_t *cr;
cursor = g_object_new (GDK_TYPE_WAYLAND_CURSOR,
"display", display_wayland,
"texture", texture,
"x", x,
"y", y,
NULL);
cursor->surface.hotspot_x = x;
cursor->surface.hotspot_y = y;
cursor->surface.scale = 1;
if (surface)
{
double sx, sy;
cairo_surface_get_device_scale (surface, &sx, &sy);
cursor->surface.scale = (int)sx;
cursor->surface.width = cairo_image_surface_get_width (surface);
cursor->surface.height = cairo_image_surface_get_height (surface);
}
else
{
cursor->surface.width = 1;
cursor->surface.height = 1;
}
cursor->surface.width = gdk_texture_get_width (texture);
cursor->surface.height = gdk_texture_get_height (texture);
cursor->surface.cairo_surface =
_gdk_wayland_display_create_shm_surface (display_wayland,
@ -425,13 +412,10 @@ _gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
buffer = _gdk_wayland_shm_surface_get_wl_buffer (cursor->surface.cairo_surface);
wl_buffer_add_listener (buffer, &buffer_listener, cursor->surface.cairo_surface);
if (surface)
{
cr = cairo_create (cursor->surface.cairo_surface);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
}
gdk_texture_download (texture,
cairo_image_surface_get_data (cursor->surface.cairo_surface),
cairo_image_surface_get_stride (cursor->surface.cairo_surface));
cairo_surface_mark_dirty (cursor->surface.cairo_surface);
return GDK_CURSOR (cursor);
}

View File

@ -1037,7 +1037,7 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass *class)
display_class->get_default_cursor_size = _gdk_wayland_display_get_default_cursor_size;
display_class->get_maximal_cursor_size = _gdk_wayland_display_get_maximal_cursor_size;
display_class->get_cursor_for_name = _gdk_wayland_display_get_cursor_for_name;
display_class->get_cursor_for_surface = _gdk_wayland_display_get_cursor_for_surface;
display_class->get_cursor_for_texture = _gdk_wayland_display_get_cursor_for_texture;
display_class->supports_cursor_alpha = _gdk_wayland_display_supports_cursor_alpha;
display_class->supports_cursor_color = _gdk_wayland_display_supports_cursor_color;
display_class->get_next_serial = gdk_wayland_display_get_next_serial;

View File

@ -68,10 +68,10 @@ GdkCursor *_gdk_wayland_display_get_cursor_for_name_with_scale (GdkDisplay *d
guint scale);
GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
const gchar *name);
GdkCursor *_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y);
GdkCursor *_gdk_wayland_display_get_cursor_for_texture (GdkDisplay *display,
GdkTexture *texture,
int x,
int y);
void _gdk_wayland_display_get_default_cursor_size (GdkDisplay *display,
guint *width,
guint *height);

View File

@ -373,68 +373,31 @@ _gdk_x11_cursor_update_theme (GdkCursor *cursor)
#ifdef HAVE_XCURSOR
static void
get_surface_size (cairo_surface_t *surface,
int *width,
int *height)
{
double x_scale, y_scale;
x_scale = y_scale = 1;
cairo_surface_get_device_scale (surface, &x_scale, &y_scale);
/* 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)
create_cursor_image (GdkTexture *texture,
gint x,
gint y,
gint scale)
{
gint width, height;
XcursorImage *xcimage;
cairo_surface_t *surface;
cairo_t *cr;
get_surface_size (source_surface, &width, &height);
xcimage = XcursorImageCreate (gdk_texture_get_width (texture), gdk_texture_get_height (texture));
width *= scale;
height *= scale;
xcimage = XcursorImageCreate (width, height);
xcimage->xhot = x;
xcimage->yhot = y;
xcimage->xhot = x * scale;
xcimage->yhot = y * scale;
surface = cairo_image_surface_create_for_data ((guchar *) xcimage->pixels,
CAIRO_FORMAT_ARGB32,
width,
height,
width * 4);
cairo_surface_set_device_scale (surface, scale, scale);
cr = cairo_create (surface);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface (cr, source_surface, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
cairo_surface_destroy (surface);
gdk_texture_download (texture,
(guchar *) xcimage->pixels,
gdk_texture_get_width (texture) * 4);
return xcimage;
}
GdkCursor *
_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y)
_gdk_x11_display_get_cursor_for_texture (GdkDisplay *display,
GdkTexture *texture,
int x,
int y)
{
XcursorImage *xcimage;
Cursor xcursor;
@ -449,13 +412,16 @@ _gdk_x11_display_get_cursor_for_surface (GdkDisplay *display,
{
target_scale =
gdk_monitor_get_scale_factor (gdk_display_get_primary_monitor (display));
xcimage = create_cursor_image (surface, x, y, target_scale);
xcimage = create_cursor_image (texture, x, y, target_scale);
xcursor = XcursorImageLoadCursor (GDK_DISPLAY_XDISPLAY (display), xcimage);
XcursorImageDestroy (xcimage);
}
private = g_object_new (GDK_TYPE_X11_CURSOR,
"display", display,
"texture", texture,
"x", x,
"y", y,
NULL);
private->xcursor = xcursor;
private->serial = theme_serial;

View File

@ -3191,7 +3191,7 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
display_class->supports_input_shapes = gdk_x11_display_supports_input_shapes;
display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
display_class->get_cursor_for_name = _gdk_x11_display_get_cursor_for_name;
display_class->get_cursor_for_surface = _gdk_x11_display_get_cursor_for_surface;
display_class->get_cursor_for_texture = _gdk_x11_display_get_cursor_for_texture;
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->supports_cursor_alpha = _gdk_x11_display_supports_cursor_alpha;

View File

@ -232,10 +232,10 @@ gchar * _gdk_x11_display_manager_get_atom_name (GdkDisplayManager *manager,
GdkCursor *_gdk_x11_display_get_cursor_for_name (GdkDisplay *display,
const gchar *name);
GdkCursor *_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y);
GdkCursor *_gdk_x11_display_get_cursor_for_texture (GdkDisplay *display,
GdkTexture *texture,
int x,
int y);
gboolean _gdk_x11_display_supports_cursor_alpha (GdkDisplay *display);
gboolean _gdk_x11_display_supports_cursor_color (GdkDisplay *display);
void _gdk_x11_display_get_default_cursor_size (GdkDisplay *display,