commit c5c473b

Michael Forney  ·  2013-09-13 03:00:27 +0000 UTC
parent e672b60
Implement cursor surfaces
8 files changed,  +195, -3
+1, -0
1@@ -12,6 +12,7 @@ libswc_la_SOURCES = \
2     plane.c plane.h \
3     surface.c surface.h \
4     compositor_surface.c compositor_surface.h \
5+    cursor_surface.c cursor_surface.h \
6     region.c region.h \
7     renderer.c renderer.h \
8     input_focus.c input_focus.h \
+27, -0
 1@@ -5,6 +5,7 @@
 2 
 3 #include "compositor.h"
 4 #include "compositor_surface.h"
 5+#include "cursor_surface.h"
 6 #include "tty.h"
 7 #include "output.h"
 8 #include "surface.h"
 9@@ -300,6 +301,27 @@ static void handle_drm_event(struct wl_listener * listener, void * data)
10     }
11 }
12 
13+static void handle_pointer_event(struct wl_listener * listener, void * data)
14+{
15+    struct swc_event * event = data;
16+    struct swc_pointer_event_data * event_data = event->data;
17+    struct swc_compositor * compositor;
18+
19+    compositor = swc_container_of(listener, typeof(*compositor),
20+                                  pointer_listener);
21+
22+    switch (event->type)
23+    {
24+        case SWC_POINTER_CURSOR_CHANGED:
25+            if (event_data->old)
26+                swc_surface_set_class(event_data->old, NULL);
27+
28+            if (event_data->new)
29+                swc_surface_set_class(event_data->new, &compositor->cursor_class);
30+            break;
31+    }
32+}
33+
34 static void handle_terminate(uint32_t time, uint32_t value, void * data)
35 {
36     struct wl_display * display = data;
37@@ -381,10 +403,13 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
38     compositor->display = display;
39     compositor->tty_listener.notify = &handle_tty_event;
40     compositor->drm_listener.notify = &handle_drm_event;
41+    compositor->pointer_listener.notify = &handle_pointer_event;
42     compositor->scheduled_updates = 0;
43     compositor->pending_flips = 0;
44     compositor->compositor_class.interface
45         = &swc_compositor_class_implementation;
46+    compositor->cursor_class.interface = &swc_cursor_class_implementation;
47+
48 
49     compositor->udev = udev_new();
50 
51@@ -415,6 +440,8 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
52     swc_seat_add_event_sources(&compositor->seat, event_loop);
53     compositor->seat.keyboard.handler = &keyboard_handler;
54     compositor->seat.pointer.handler = &pointer_handler;
55+    wl_signal_add(&compositor->seat.pointer.event_signal,
56+                  &compositor->pointer_listener);
57 
58     /* TODO: configurable seat */
59     if (!swc_drm_initialize(&compositor->drm, compositor->udev, default_seat))
+2, -0
 1@@ -40,9 +40,11 @@ struct swc_compositor
 2     };
 3 
 4     struct swc_surface_class compositor_class;
 5+    struct swc_surface_class cursor_class;
 6 
 7     struct wl_listener tty_listener;
 8     struct wl_listener drm_listener;
 9+    struct wl_listener pointer_listener;
10 
11     struct wl_signal destroy_signal;
12 };
+112, -0
  1@@ -0,0 +1,112 @@
  2+/* swc: cursor_surface.c
  3+ *
  4+ * Copyright (c) 2013 Michael Forney
  5+ *
  6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
  7+ * of this software and associated documentation files (the "Software"), to deal
  8+ * in the Software without restriction, including without limitation the rights
  9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10+ * copies of the Software, and to permit persons to whom the Software is
 11+ * furnished to do so, subject to the following conditions:
 12+ *
 13+ * The above copyright notice and this permission notice shall be included in
 14+ * all copies or substantial portions of the Software.
 15+ *
 16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 22+ * SOFTWARE.
 23+ */
 24+
 25+#include "cursor_surface.h"
 26+#include "compositor.h"
 27+
 28+#include <string.h>
 29+#include <wld/wld.h>
 30+
 31+/* Cursor class */
 32+static const uint32_t cursor_buffer_size = 64 * 64 * 4;
 33+
 34+static void update_plane(struct swc_plane * plane, void * data)
 35+{
 36+    struct wld_drawable * drawable = swc_plane_get_buffer(plane);
 37+
 38+    wld_write(drawable, data, cursor_buffer_size);
 39+    swc_plane_flip(plane);
 40+}
 41+
 42+static void attach(struct swc_surface * surface,
 43+                   struct wl_resource * resource)
 44+{
 45+    struct swc_compositor * compositor = swc_container_of
 46+        (surface->class, typeof(*compositor), cursor_class);
 47+
 48+    if (pixman_region32_not_empty(&surface->state.damage))
 49+    {
 50+        struct wl_shm_buffer * buffer = wl_shm_buffer_get(resource);
 51+        uint32_t width, height;
 52+
 53+        if (!buffer)
 54+            return;
 55+
 56+        width = wl_shm_buffer_get_width(buffer);
 57+        height = wl_shm_buffer_get_height(buffer);
 58+
 59+        if (width <= 64 && height <= 64)
 60+        {
 61+            struct swc_output * output;
 62+            char data[cursor_buffer_size];
 63+
 64+            memset(data, 0, sizeof data);
 65+            pixman_blt(wl_shm_buffer_get_data(buffer), (uint32_t *) data,
 66+                       wl_shm_buffer_get_stride(buffer) >> 2, 64, 32, 32,
 67+                       0, 0, 0, 0, width, height);
 68+            wl_buffer_send_release(resource);
 69+            pixman_region32_clear(&surface->state.damage);
 70+
 71+            wl_list_for_each(output, &compositor->outputs, link)
 72+            {
 73+                if (swc_rectangle_overlap(&output->geometry,
 74+                                          &surface->geometry))
 75+                {
 76+                    update_plane(&output->cursor_plane, data);
 77+                }
 78+            }
 79+        }
 80+    }
 81+}
 82+
 83+static void update(struct swc_surface * surface)
 84+{
 85+    swc_surface_send_frame_callbacks(surface, swc_time());
 86+}
 87+
 88+static void move(struct swc_surface * surface, int32_t x, int32_t y)
 89+{
 90+    struct swc_compositor * compositor = swc_container_of
 91+        (surface->class, typeof(*compositor), cursor_class);
 92+    struct swc_output * output;
 93+
 94+    surface->geometry.x = x;
 95+    surface->geometry.y = y;
 96+
 97+    wl_list_for_each(output, &compositor->outputs, link)
 98+    {
 99+        if (swc_rectangle_overlap(&output->geometry, &surface->geometry))
100+        {
101+            swc_plane_move(&output->cursor_plane,
102+                           surface->geometry.x - output->geometry.x,
103+                           surface->geometry.y - output->geometry.y);
104+        }
105+    }
106+}
107+
108+const struct swc_surface_class_interface swc_cursor_class_implementation = {
109+    .attach = &attach,
110+    .update = &update,
111+    .move = &move
112+};
113+
+33, -0
 1@@ -0,0 +1,33 @@
 2+/* swc: cursor_surface.h
 3+ *
 4+ * Copyright (c) 2013 Michael Forney
 5+ *
 6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
 7+ * of this software and associated documentation files (the "Software"), to deal
 8+ * in the Software without restriction, including without limitation the rights
 9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#ifndef SWC_CURSOR_SURFACE_H
26+#define SWC_CURSOR_SURFACE_H 1
27+
28+#include "surface.h"
29+
30+extern const struct swc_surface_class_interface
31+    swc_cursor_class_implementation;
32+
33+#endif
34+
+5, -2
 1@@ -88,8 +88,9 @@ static void set_cursor(struct wl_client * client,
 2 {
 3     struct swc_pointer * pointer = wl_resource_get_user_data(resource);
 4     struct swc_surface * surface;
 5+    struct swc_pointer_event_data data;
 6 
 7-    printf("set_cursor\n");
 8+    data.old = pointer->cursor.surface;
 9 
10     if (pointer->cursor.surface)
11         wl_list_remove(&pointer->cursor.destroy_listener.link);
12@@ -109,7 +110,9 @@ static void set_cursor(struct wl_client * client,
13     pointer->cursor.hotspot_x = hotspot_x;
14     pointer->cursor.hotspot_y = hotspot_y;
15 
16-    swc_send_event(&pointer->event_signal, SWC_POINTER_CURSOR_CHANGED, pointer);
17+    data.new = pointer->cursor.surface;
18+
19+    swc_send_event(&pointer->event_signal, SWC_POINTER_CURSOR_CHANGED, &data);
20 }
21 
22 struct wl_pointer_interface pointer_implementation = {
+6, -1
 1@@ -16,11 +16,16 @@ struct swc_pointer_handler
 2                     uint32_t button, uint32_t state);
 3 };
 4 
 5-enum swc_pointer_event
 6+enum swc_pointer_event_type
 7 {
 8     SWC_POINTER_CURSOR_CHANGED
 9 };
10 
11+struct swc_pointer_event_data
12+{
13+    struct swc_surface * old, * new;
14+};
15+
16 struct swc_pointer
17 {
18     struct swc_input_focus focus;
+9, -0
 1@@ -2,6 +2,7 @@
 2 #define SWC_UTIL_H 1
 3 
 4 #include <stdbool.h>
 5+#include <sys/time.h>
 6 #include <sys/param.h>
 7 #include <wayland-server.h>
 8 #include <pixman.h>
 9@@ -17,6 +18,14 @@
10 
11 void swc_remove_resource(struct wl_resource * resource);
12 
13+static inline uint32_t swc_time()
14+{
15+    struct timeval timeval;
16+
17+    gettimeofday(&timeval, NULL);
18+    return timeval.tv_sec * 1000 + timeval.tv_usec / 1000;
19+}
20+
21 static inline bool swc_rectangle_contains_point
22     (pixman_rectangle32_t * rectangle, int32_t x, int32_t y)
23 {