wayland: Load a buffer from well known location for the cursor
Semantic changes to Wayland means that we cannot rely on the compositor setting a pointer buffer for us if set it to nil. The first part of fixing this is to create an shm buffer containing the bytes for our cursor. The best way to do this currently is to load the cursor from the well known location where weston instals its cursor images. The code to implemente this was derivedlifted from the Wayland backend in GTK+.
This commit is contained in:
parent
3c99fd2ddb
commit
e1434cebdb
@ -32,6 +32,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@ -48,12 +49,15 @@
|
||||
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#define clutter_backend_wayland_get_type _clutter_backend_wayland_get_type
|
||||
|
||||
G_DEFINE_TYPE (ClutterBackendWayland, clutter_backend_wayland, CLUTTER_TYPE_BACKEND);
|
||||
|
||||
static void clutter_backend_wayland_load_cursor (ClutterBackendWayland *backend_wayland);
|
||||
|
||||
static void
|
||||
clutter_backend_wayland_dispose (GObject *gobject)
|
||||
{
|
||||
@ -65,6 +69,12 @@ clutter_backend_wayland_dispose (GObject *gobject)
|
||||
backend_wayland->device_manager = NULL;
|
||||
}
|
||||
|
||||
if (backend_wayland->cursor_buffer)
|
||||
{
|
||||
wl_buffer_destroy (backend_wayland->cursor_buffer);
|
||||
backend_wayland->cursor_buffer = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_backend_wayland_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@ -142,6 +152,9 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend,
|
||||
backend_wayland->wayland_shell))
|
||||
wl_display_roundtrip (backend_wayland->wayland_display);
|
||||
|
||||
/* We need the shm object before we can create the cursor */
|
||||
clutter_backend_wayland_load_cursor (backend_wayland);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -212,6 +225,172 @@ clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass)
|
||||
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_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);
|
||||
|
||||
buffer = wl_shm_create_buffer (backend_wayland->wayland_shm,
|
||||
fd,
|
||||
width,
|
||||
height,
|
||||
stride,
|
||||
WL_SHM_FORMAT_ARGB32);
|
||||
|
||||
close(fd);
|
||||
munmap (map, size);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_wayland_load_cursor (ClutterBackendWayland *backend_wayland)
|
||||
{
|
||||
const gchar * const *directories;
|
||||
gint j;
|
||||
GdkPixbuf *pixbuf = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
directories = g_get_system_data_dirs();
|
||||
|
||||
for (j = 0; directories[j] != NULL; j++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
backend_wayland->cursor_x = 15;
|
||||
backend_wayland->cursor_y = 15;
|
||||
}
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_wayland_init (ClutterBackendWayland *backend_wayland)
|
||||
{
|
||||
|
@ -56,6 +56,9 @@ struct _ClutterBackendWayland
|
||||
struct wl_compositor *wayland_compositor;
|
||||
struct wl_shell *wayland_shell;
|
||||
struct wl_shm *wayland_shm;
|
||||
struct wl_buffer *cursor_buffer;
|
||||
gint cursor_x, cursor_y;
|
||||
|
||||
GSource *wayland_source;
|
||||
|
||||
/* event timer */
|
||||
|
Loading…
Reference in New Issue
Block a user