mirror of
https://github.com/brl/mutter.git
synced 2025-02-14 04:14:10 +00:00
wayland: Use wl_cursor_theme to provide a buffer for the Wayland cursor
This change switches to the new mechanism for loading a cursor into a buffer. It no longer relies on having a PNG stored in a known location and instead loads from the Wayland cursor theme. Signed-off-by: Rob Bradford <rob@linux.intel.com>
This commit is contained in:
parent
d4c7f2ecf4
commit
fce43c420e
@ -48,6 +48,7 @@
|
|||||||
#include "cogl/clutter-stage-cogl.h"
|
#include "cogl/clutter-stage-cogl.h"
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
@ -76,6 +77,12 @@ clutter_backend_wayland_dispose (GObject *gobject)
|
|||||||
backend_wayland->cursor_buffer = NULL;
|
backend_wayland->cursor_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (backend_wayland->cursor_theme)
|
||||||
|
{
|
||||||
|
wl_cursor_theme_destroy (backend_wayland->cursor_theme);
|
||||||
|
backend_wayland->cursor_theme = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_backend_wayland_parent_class)->dispose (gobject);
|
G_OBJECT_CLASS (clutter_backend_wayland_parent_class)->dispose (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,175 +284,30 @@ clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass)
|
|||||||
backend_class->get_display = clutter_backend_wayland_get_display;
|
backend_class->get_display = clutter_backend_wayland_get_display;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* clutter_backend_wayland_load_cursor and the two functions below were copied
|
|
||||||
* from GTK+ and adapted for clutter
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
set_pixbuf (GdkPixbuf *pixbuf,
|
|
||||||
unsigned char *map,
|
|
||||||
int width,
|
|
||||||
int height)
|
|
||||||
{
|
|
||||||
int stride, i, n_channels;
|
|
||||||
unsigned char *pixels, *end, *argb_pixels, *s, *d;
|
|
||||||
|
|
||||||
stride = gdk_pixbuf_get_rowstride (pixbuf);
|
|
||||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
|
||||||
n_channels = gdk_pixbuf_get_n_channels (pixbuf);
|
|
||||||
argb_pixels = map;
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wl_buffer *
|
|
||||||
create_cursor (ClutterBackendWayland *backend_wayland,
|
|
||||||
GdkPixbuf *pixbuf)
|
|
||||||
{
|
|
||||||
int stride, fd;
|
|
||||||
char *filename;
|
|
||||||
GError *error = NULL;
|
|
||||||
struct wl_shm_pool *pool;
|
|
||||||
struct wl_buffer *buffer;
|
|
||||||
gint width, height;
|
|
||||||
gsize size;
|
|
||||||
unsigned char *map;
|
|
||||||
|
|
||||||
width = gdk_pixbuf_get_width (pixbuf);
|
|
||||||
height = gdk_pixbuf_get_height (pixbuf);
|
|
||||||
stride = width * 4;
|
|
||||||
size = stride * height;
|
|
||||||
|
|
||||||
fd = g_file_open_tmp ("wayland-shm-XXXXXX", &filename, &error);
|
|
||||||
if (fd < 0)
|
|
||||||
{
|
|
||||||
g_critical (G_STRLOC ": Opening temporary file failed: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlink (filename);
|
|
||||||
g_free (filename);
|
|
||||||
|
|
||||||
if (ftruncate (fd, size) < 0)
|
|
||||||
{
|
|
||||||
g_critical (G_STRLOC ": Setting the size of temporary file failed: %s", g_strerror (errno));
|
|
||||||
close (fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
map = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
|
|
||||||
if (map == MAP_FAILED)
|
|
||||||
{
|
|
||||||
g_critical (G_STRLOC ": Memory mapping file failed: %s", g_strerror (errno));
|
|
||||||
close (fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_pixbuf (pixbuf, map, width, height);
|
|
||||||
|
|
||||||
pool = wl_shm_create_pool (backend_wayland->wayland_shm, fd, size);
|
|
||||||
close (fd);
|
|
||||||
buffer = wl_shm_pool_create_buffer (pool,
|
|
||||||
0,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
stride,
|
|
||||||
WL_SHM_FORMAT_ARGB8888);
|
|
||||||
wl_shm_pool_destroy (pool);
|
|
||||||
munmap (map, size);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_wayland_load_cursor (ClutterBackendWayland *backend_wayland)
|
clutter_backend_wayland_load_cursor (ClutterBackendWayland *backend_wayland)
|
||||||
{
|
{
|
||||||
const gchar * const *directories;
|
struct wl_cursor *cursor;
|
||||||
gint j;
|
|
||||||
GdkPixbuf *pixbuf = NULL;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
directories = g_get_system_data_dirs();
|
backend_wayland->cursor_theme =
|
||||||
|
wl_cursor_theme_load (NULL, /* default */
|
||||||
|
32,
|
||||||
|
backend_wayland->wayland_shm);
|
||||||
|
|
||||||
for (j = 0; directories[j] != NULL; j++)
|
cursor = wl_cursor_theme_get_cursor (backend_wayland->cursor_theme,
|
||||||
{
|
"left_ptr");
|
||||||
gchar *filename;
|
|
||||||
filename = g_build_filename (directories[j],
|
|
||||||
"weston",
|
|
||||||
"left_ptr.png",
|
|
||||||
NULL);
|
|
||||||
if (g_file_test (filename, G_FILE_TEST_EXISTS))
|
|
||||||
{
|
|
||||||
pixbuf = gdk_pixbuf_new_from_file (filename, &error);
|
|
||||||
|
|
||||||
if (error != NULL)
|
backend_wayland->cursor_buffer =
|
||||||
{
|
wl_cursor_image_get_buffer (cursor->images[0]);
|
||||||
g_warning ("Failed to load cursor: %s: %s",
|
|
||||||
filename, error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pixbuf)
|
|
||||||
return;
|
|
||||||
|
|
||||||
backend_wayland->cursor_buffer = create_cursor (backend_wayland, pixbuf);
|
|
||||||
|
|
||||||
if (backend_wayland->cursor_buffer)
|
if (backend_wayland->cursor_buffer)
|
||||||
{
|
{
|
||||||
backend_wayland->cursor_x = 0;
|
backend_wayland->cursor_x = cursor->images[0]->hotspot_x;
|
||||||
backend_wayland->cursor_y = 0;
|
backend_wayland->cursor_y = cursor->images[0]->hotspot_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
backend_wayland->cursor_surface =
|
backend_wayland->cursor_surface =
|
||||||
wl_compositor_create_surface (backend_wayland->wayland_compositor);
|
wl_compositor_create_surface (backend_wayland->wayland_compositor);
|
||||||
|
|
||||||
g_object_unref (pixbuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -32,6 +32,9 @@
|
|||||||
#include <clutter/clutter-backend.h>
|
#include <clutter/clutter-backend.h>
|
||||||
#include <clutter/clutter-device-manager.h>
|
#include <clutter/clutter-device-manager.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
#include "clutter-backend-private.h"
|
#include "clutter-backend-private.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@ -59,6 +62,7 @@ struct _ClutterBackendWayland
|
|||||||
struct wl_surface *cursor_surface;
|
struct wl_surface *cursor_surface;
|
||||||
struct wl_buffer *cursor_buffer;
|
struct wl_buffer *cursor_buffer;
|
||||||
struct wl_output *wayland_output;
|
struct wl_output *wayland_output;
|
||||||
|
struct wl_cursor_theme *cursor_theme;
|
||||||
|
|
||||||
gint cursor_x, cursor_y;
|
gint cursor_x, cursor_y;
|
||||||
gint output_width, output_height;
|
gint output_width, output_height;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user