aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xwayland/xwayland-cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xwayland/xwayland-cursor.c')
-rw-r--r--xorg-server/hw/xwayland/xwayland-cursor.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/xorg-server/hw/xwayland/xwayland-cursor.c b/xorg-server/hw/xwayland/xwayland-cursor.c
new file mode 100644
index 000000000..5a9d1fe70
--- /dev/null
+++ b/xorg-server/hw/xwayland/xwayland-cursor.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * 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.
+ */
+
+#include "xwayland.h"
+
+#include <mipointer.h>
+
+static DevPrivateKeyRec xwl_cursor_private_key;
+
+static void
+expand_source_and_mask(CursorPtr cursor, CARD32 *data)
+{
+ CARD32 *p, d, fg, bg;
+ CursorBitsPtr bits = cursor->bits;
+ int x, y, stride, i, bit;
+
+ p = data;
+ 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;
+ }
+}
+
+static Bool
+xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
+{
+ PixmapPtr pixmap;
+
+ pixmap = xwl_shm_create_pixmap(screen, cursor->bits->width,
+ cursor->bits->height, 32, 0);
+ dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, pixmap);
+
+ return TRUE;
+}
+
+static Bool
+xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
+{
+ PixmapPtr pixmap;
+
+ pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
+
+ return xwl_shm_destroy_pixmap(pixmap);
+}
+
+void
+xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
+{
+ PixmapPtr pixmap;
+ CursorPtr cursor;
+ int stride;
+
+ 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;
+ }
+
+ cursor = xwl_seat->x_cursor;
+ pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
+ stride = cursor->bits->width * 4;
+ if (cursor->bits->argb)
+ memcpy(pixmap->devPrivate.ptr,
+ cursor->bits->argb, cursor->bits->height * stride);
+ else
+ expand_source_and_mask(cursor, pixmap->devPrivate.ptr);
+
+ 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,
+ xwl_shm_pixmap_get_wl_buffer(pixmap), 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_seat *xwl_seat;
+
+ xwl_seat = device->public.devicePrivate;
+ if (xwl_seat == NULL)
+ return;
+
+ 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)
+{
+ return TRUE;
+}
+
+static void
+xwl_device_cursor_cleanup(DeviceIntPtr device, ScreenPtr 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
+};
+
+static Bool
+xwl_cursor_off_screen(ScreenPtr *ppScreen, int *x, int *y)
+{
+ return FALSE;
+}
+
+static void
+xwl_cross_screen(ScreenPtr pScreen, Bool entering)
+{
+}
+
+static void
+xwl_pointer_warp_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+}
+
+static miPointerScreenFuncRec xwl_pointer_screen_funcs = {
+ xwl_cursor_off_screen,
+ xwl_cross_screen,
+ xwl_pointer_warp_cursor
+};
+
+Bool
+xwl_screen_init_cursor(struct xwl_screen *xwl_screen)
+{
+ if (!dixRegisterPrivateKey(&xwl_cursor_private_key, PRIVATE_CURSOR_BITS, 0))
+ return FALSE;
+
+ return miPointerInitialize(xwl_screen->screen,
+ &xwl_pointer_sprite_funcs,
+ &xwl_pointer_screen_funcs, TRUE);
+}