summaryrefslogtreecommitdiff
path: root/hw/xfree86/xwayland/xwayland-cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/xwayland/xwayland-cursor.c')
-rw-r--r--hw/xfree86/xwayland/xwayland-cursor.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/hw/xfree86/xwayland/xwayland-cursor.c b/hw/xfree86/xwayland/xwayland-cursor.c
new file mode 100644
index 000000000..2b3cb5e63
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-cursor.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include "xorg-config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <wayland-client.h>
+
+#include <cursorstr.h>
+#include <xf86Crtc.h>
+#include <mipointrst.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "xserver-client-protocol.h"
+
+static void
+expand_source_and_mask(CursorPtr cursor, void *data)
+{
+ CARD32 *argb, *p, d, fg, bg;
+ CursorBitsPtr bits = cursor->bits;
+ int size;
+ int x, y, stride, i, bit;
+
+ size = bits->width * bits->height * 4;
+ argb = malloc(size);
+ if (argb == NULL)
+ return;
+
+ p = argb;
+ fg = ((cursor->foreRed & 0xff00) << 8) |
+ (cursor->foreGreen & 0xff00) | (cursor->foreGreen >> 8);
+ bg = ((cursor->backRed & 0xff00) << 8) |
+ (cursor->backGreen & 0xff00) | (cursor->backGreen >> 8);
+ stride = (bits->width / 8 + 3) & ~3;
+ for (y = 0; y < bits->height; y++)
+ for (x = 0; x < bits->width; x++) {
+ i = y * stride + x / 8;
+ bit = 1 << (x & 7);
+ if (bits->source[i] & bit)
+ d = fg;
+ else
+ d = bg;
+ if (bits->mask[i] & bit)
+ d |= 0xff000000;
+ else
+ d = 0x00000000;
+
+ *p++ = d;
+ }
+
+ memcpy(data, argb, size);
+ free(argb);
+}
+
+static Bool
+xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
+{
+ struct xwl_screen *xwl_screen;
+ int size;
+ char filename[] = "/tmp/wayland-shm-XXXXXX";
+ int fd;
+ struct wl_shm_pool *pool;
+ struct wl_buffer *buffer;
+ void *data;
+
+ xwl_screen = xwl_screen_get(screen);
+ size = cursor->bits->width * cursor->bits->height * 4;
+
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ ErrorF("open %s failed: %s", filename, strerror(errno));
+ return FALSE;
+ }
+ if (ftruncate(fd, size) < 0) {
+ ErrorF("ftruncate failed: %s", strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+
+ data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ unlink(filename);
+
+ if (data == MAP_FAILED) {
+ ErrorF("mmap failed: %s", strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+
+ if (cursor->bits->argb)
+ memcpy(data, cursor->bits->argb, size);
+ else
+ expand_source_and_mask(cursor, data);
+ munmap(data, size);
+
+ pool = wl_shm_create_pool(xwl_screen->shm, fd, size);
+ close(fd);
+ buffer = wl_shm_pool_create_buffer(pool, 0,
+ cursor->bits->width, cursor->bits->height,
+ cursor->bits->width * 4,
+ WL_SHM_FORMAT_ARGB8888);
+ wl_shm_pool_destroy(pool);
+
+ dixSetPrivate(&cursor->devPrivates,
+ &xwl_screen->cursor_private_key, buffer);
+
+ return TRUE;
+}
+
+static Bool
+xwl_unrealize_cursor(DeviceIntPtr device,
+ ScreenPtr screen, CursorPtr cursor)
+{
+ struct wl_buffer *buffer;
+ struct xwl_screen *xwl_screen;
+
+ xwl_screen = xwl_screen_get(screen);
+ buffer = dixGetPrivate(&cursor->devPrivates,
+ &xwl_screen->cursor_private_key);
+ wl_buffer_destroy(buffer);
+
+ return TRUE;
+}
+
+void
+xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
+{
+ struct wl_buffer *buffer;
+
+ if (!xwl_seat->wl_pointer)
+ return;
+
+ if (!xwl_seat->x_cursor) {
+ wl_pointer_set_cursor(xwl_seat->wl_pointer,
+ xwl_seat->pointer_enter_serial,
+ NULL, 0, 0);
+ return;
+ }
+
+ buffer = dixGetPrivate(&xwl_seat->x_cursor->devPrivates,
+ &xwl_seat->xwl_screen->cursor_private_key);
+
+ wl_pointer_set_cursor(xwl_seat->wl_pointer,
+ xwl_seat->pointer_enter_serial,
+ xwl_seat->cursor,
+ xwl_seat->x_cursor->bits->xhot,
+ xwl_seat->x_cursor->bits->yhot);
+ wl_surface_attach(xwl_seat->cursor, buffer, 0, 0);
+ wl_surface_damage(xwl_seat->cursor, 0, 0,
+ xwl_seat->x_cursor->bits->width,
+ xwl_seat->x_cursor->bits->height);
+ wl_surface_commit(xwl_seat->cursor);
+}
+
+static void
+xwl_set_cursor(DeviceIntPtr device,
+ ScreenPtr screen, CursorPtr cursor, int x, int y)
+{
+ struct xwl_screen *xwl_screen;
+ struct xwl_seat *xwl_seat;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ if (!xwl_screen || xorg_list_is_empty(&xwl_screen->seat_list))
+ return;
+
+ xwl_seat = xorg_list_first_entry(&xwl_screen->seat_list,
+ struct xwl_seat, link);
+
+ xwl_seat->x_cursor = cursor;
+ xwl_seat_set_cursor(xwl_seat);
+}
+
+static void
+xwl_move_cursor(DeviceIntPtr device, ScreenPtr screen, int x, int y)
+{
+}
+
+static Bool
+xwl_device_cursor_initialize(DeviceIntPtr device, ScreenPtr screen)
+{
+ struct xwl_screen *xwl_screen;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ return xwl_screen->sprite_funcs->DeviceCursorInitialize(device,
+ screen);
+}
+
+static void
+xwl_device_cursor_cleanup(DeviceIntPtr device, ScreenPtr screen)
+{
+ struct xwl_screen *xwl_screen;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ xwl_screen->sprite_funcs->DeviceCursorCleanup(device, screen);
+}
+
+static miPointerSpriteFuncRec xwl_pointer_sprite_funcs =
+{
+ xwl_realize_cursor,
+ xwl_unrealize_cursor,
+ xwl_set_cursor,
+ xwl_move_cursor,
+ xwl_device_cursor_initialize,
+ xwl_device_cursor_cleanup
+};
+
+int
+xwl_screen_init_cursor(struct xwl_screen *xwl_screen, ScreenPtr screen)
+{
+ miPointerScreenPtr pointer_priv;
+
+ if (!dixRegisterPrivateKey(&xwl_screen->cursor_private_key,
+ PRIVATE_CURSOR, 0))
+ return BadAlloc;
+
+ pointer_priv = dixLookupPrivate(&screen->devPrivates, miPointerScreenKey);
+ xwl_screen->sprite_funcs = pointer_priv->spriteFuncs;
+ pointer_priv->spriteFuncs = &xwl_pointer_sprite_funcs;
+
+ return Success;
+}