wayland-fits protocol: add new features, impl some
authorU. Artie Eoff <ullysses.a.eoff@intel.com>
Thu, 24 Jan 2013 23:19:21 +0000 (15:19 -0800)
committerU. Artie Eoff <ullysses.a.eoff@intel.com>
Thu, 24 Jan 2013 23:19:21 +0000 (15:19 -0800)
Signed-off-by: U. Artie Eoff <ullysses.a.eoff@intel.com>
src/Makefile.am
src/extensions/protocol/.gitignore [new file with mode: 0644]
src/extensions/protocol/Makefile.am
src/extensions/protocol/wayland-fits.xml
src/extensions/weston/.gitignore
src/extensions/weston/Makefile.am
src/extensions/weston/weston-wfits.c

index 1a949d7..7e069c7 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = common core efl extensions
+SUBDIRS = common extensions core efl
 
 TESTS = wfits
 
diff --git a/src/extensions/protocol/.gitignore b/src/extensions/protocol/.gitignore
new file mode 100644 (file)
index 0000000..a6bd975
--- /dev/null
@@ -0,0 +1,4 @@
+wayland-fits-client-protocol.h
+wayland-fits-protocol.c
+wayland-fits-server-protocol.h
+
index 82ef692..fa87ac0 100644 (file)
@@ -1,2 +1,11 @@
 EXTRA_DIST =                   \
        wayland-fits.xml
+
+BUILT_SOURCES =                                        \
+       wayland-fits-protocol.c                 \
+       wayland-fits-server-protocol.h          \
+       wayland-fits-client-protocol.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
+@wayland_scanner_rules@
index 1911375..c01084d 100644 (file)
     THIS SOFTWARE.
   </copyright>
 
-  <interface name="wfits_uinput" version="1">
+  <interface name="wfits_input" version="1">
     <request name="move_pointer">
       <arg name="x" type="int"/>
       <arg name="y" type="int"/>
     </request>
   </interface>
-</protocol>
\ No newline at end of file
+  <interface name="wfits_query" version="1">
+    <request name="surface_geometry">
+      <arg name="surface" type="object" interface="wl_surface"/>
+    </request>
+    <event name="surface_geometry">
+      <arg name="x" type="fixed"/>
+      <arg name="y" type="fixed"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </event>
+    <request name="pointer_position"/>
+    <event name="pointer_position">
+      <arg name="x" type="fixed"/>
+      <arg name="y" type="fixed"/>
+    </event>
+</protocol>
index a6bd975..8b13789 100644 (file)
@@ -1,4 +1 @@
-wayland-fits-client-protocol.h
-wayland-fits-protocol.c
-wayland-fits-server-protocol.h
 
index 04b9cf7..5d49542 100644 (file)
@@ -1,3 +1,5 @@
+INCLUDES = -I$(top_srcdir)/src
+
 moduledir = @libdir@/weston
 module_LTLIBRARIES =                           \
        $(weston_wfits)
@@ -14,16 +16,6 @@ weston_wfits_la_CFLAGS =                     \
 
 weston_wfits_la_LDFLAGS = -module -avoid-version
 weston_wfits_la_LIBADD = $(WAYLAND_SERVER_LIBS)
-weston_wfits_la_SOURCES =                      \
-       weston-wfits.c                  \
-       wayland-fits-protocol.c                 \
-       wayland-fits-server-protocol.h
-
-BUILT_SOURCES =                                        \
-       wayland-fits-protocol.c                 \
-       wayland-fits-server-protocol.h          \
-       wayland-fits-client-protocol.h
-
-CLEANFILES = $(BUILT_SOURCES)
-
-@wayland_scanner_rules@
+weston_wfits_la_SOURCES =                                              \
+       weston-wfits.c                                                  \
+       $(top_srcdir)/src/extensions/protocol/wayland-fits-protocol.c
index 56e7d66..1f0c932 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2012 Intel Corporation
+ * Copyright © 2013 Intel Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation for any purpose is hereby granted without fee, provided
 
 #include <stdlib.h>
 #include <string.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include <xcb/xcb.h>
+#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+
 #include <wayland-server.h>
 #include <weston/src/compositor.h>
-#include "wayland-fits-server-protocol.h"
+
+#include "extensions/protocol/wayland-fits-server-protocol.h"
+
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+
+struct x11_compositor {
+       struct weston_compositor base;
+       Display *dpy;
+       xcb_connection_t *conn;
+};
+
+struct x11_output {
+       struct weston_output base;
+       xcb_window_t window;
+};
 
 struct wfits {
        struct weston_compositor *compositor;
+       struct wl_listener compositor_destroy_listener;
+       int pointer_fd;
 };
 
+static struct weston_seat *
+get_seat(struct wfits *wfits)
+{
+       struct wl_list *seat_list;
+       struct weston_seat *seat;
+
+       seat_list = &wfits->compositor->seat_list;
+       assert(wl_list_length(seat_list) == 1);
+       seat = container_of(seat_list->next, struct weston_seat, link);
+
+       return seat;
+}
+
+static void
+global_to_compositor(struct wfits* wfits, int32_t *x, int32_t *y)
+{
+       struct weston_output *output, *next;
+       struct x11_compositor *x11_compositor = NULL;
+       struct x11_output *x11_output = NULL;
+       xcb_get_geometry_reply_t *geom;
+       xcb_translate_coordinates_reply_t *trans;
+
+       wl_list_for_each_safe(output, next, &wfits->compositor->output_list, link) {
+               if (strcmp(output->make, "xwayland") == 0) {
+                       x11_compositor = (struct x11_compositor*) wfits->compositor;
+                       x11_output = (struct x11_output*) output;
+               }
+       }
+
+       weston_log("weston-wfits: %p %p\n", x11_compositor, x11_output);
+       if (x11_compositor && x11_output) {
+               geom = xcb_get_geometry_reply(
+                       x11_compositor->conn,
+                       xcb_get_geometry(
+                               x11_compositor->conn,
+                               x11_output->window
+                       ),
+                       NULL
+               );
+
+               trans = xcb_translate_coordinates_reply(
+                       x11_compositor->conn,
+                       xcb_translate_coordinates(
+                               x11_compositor->conn,
+                               x11_output->window,
+                               geom->root,
+                               -(geom->border_width),
+                               -(geom->border_width)
+                       ),
+                       NULL
+               );
+
+               weston_log("%d %d :: %d %d\n", *x, *y, trans->dst_x, trans->dst_y);
+               *x += (int16_t)trans->dst_x;
+               *y += (int16_t)trans->dst_y;
+
+               free(trans);
+               free(geom);
+       }
+}
+
 static void
-move_pointer(struct wl_client *client, struct wl_resource *resource,
+input_move_pointer(struct wl_client *client, struct wl_resource *resource,
             int32_t x, int32_t y)
 {
        struct wfits *wfits = resource->data;
+       struct input_event event;
+
+       global_to_compositor(wfits, &x, &y);
+
+       weston_log("weston-wfits: moving pointer to %d %d\n", x, y);
+
+       memset(&event, 0, sizeof(event));
+
+       event.type = EV_ABS;
+       event.code = ABS_X;
+       event.value = x;
+       write(wfits->pointer_fd, &event, sizeof(event));
+
+       event.type = EV_ABS;
+       event.code = ABS_Y;
+       event.value = y;
+       write(wfits->pointer_fd, &event, sizeof(event));
+
+       event.type = EV_SYN;
+       event.code = SYN_REPORT;
+       event.value = 0;
+       write(wfits->pointer_fd, &event, sizeof(event));
 }
 
-static const struct wfits_uinput_interface wfits_uinput_implementation = {
-       move_pointer,
+static const struct wfits_input_interface wfits_input_implementation = {
+       input_move_pointer,
 };
 
 static void
-bind_uinput(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+bind_input(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 {
        struct wfits *wfits = data;
        struct wl_resource *resource;
 
-       resource = wl_client_add_object(client, &wfits_uinput_interface,
-                                       &wfits_uinput_implementation, id, wfits);
+       resource = wl_client_add_object(client, &wfits_input_interface,
+                                       &wfits_input_implementation, id, wfits);
+}
+
+static void
+create_pointer(struct wfits* wfits)
+{
+       struct uinput_user_dev device;
+
+       weston_log("weston-wfits: creating uinput device\n");
+
+       wfits->pointer_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
+       if (wfits->pointer_fd < 0) {
+               weston_log("weston-wfits: failed to create uinput device\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (ioctl(wfits->pointer_fd, UI_SET_EVBIT, EV_KEY) < 0) {
+               exit(EXIT_FAILURE);
+       }
+
+       if (ioctl(wfits->pointer_fd, UI_SET_KEYBIT, BTN_LEFT) < 0) {
+               exit(EXIT_FAILURE);
+       }
+
+       if (ioctl(wfits->pointer_fd, UI_SET_KEYBIT, BTN_RIGHT) < 0) {
+               exit(EXIT_FAILURE);
+       }
+
+       if (ioctl(wfits->pointer_fd, UI_SET_EVBIT, EV_ABS) < 0) {
+               exit(EXIT_FAILURE);
+       }
+
+       if (ioctl(wfits->pointer_fd, UI_SET_ABSBIT, ABS_X) < 0) {
+               exit(EXIT_FAILURE);
+       }
+
+       if (ioctl(wfits->pointer_fd, UI_SET_ABSBIT, ABS_Y) < 0) {
+               exit(EXIT_FAILURE);
+       }
+
+       memset(&device, 0, sizeof(device));
+       snprintf(device.name, UINPUT_MAX_NAME_SIZE, "WFITS ABS POINTER");
+       device.id.bustype = BUS_USB;
+       device.id.vendor  = 0x1;
+       device.id.product = 0x1;
+       device.id.version = 1;
+       /* FIXME: This should be the compositor output geometry?? Otherwise, it seems
+        * to skew/scale absolute x,y pointer movements. What about multidisplay?
+        */
+       device.absmin[ABS_X] = 0;
+       device.absmax[ABS_X] = 1440;
+       device.absmin[ABS_Y] = 0;
+       device.absmax[ABS_Y] = 900;
+
+       if (write(wfits->pointer_fd, &device, sizeof(device)) < 0) {
+               exit(EXIT_FAILURE);
+       }
+
+       if (ioctl(wfits->pointer_fd, UI_DEV_CREATE) < 0) {
+               exit(EXIT_FAILURE);
+       }
+}
+
+static void
+query_surface_geometry(struct wl_client *client, struct wl_resource *resource,
+            struct wl_resource *surface_resource)
+{
+       struct wfits *wfits = resource->data;
+       struct weston_surface *surface = surface_resource->data;
+
+       wfits_query_send_surface_geometry(resource,
+                                         wl_fixed_from_double(surface->geometry.x),
+                                         wl_fixed_from_double(surface->geometry.y),
+                                         surface->geometry.width,
+                                         surface->geometry.height);
+}
+
+static void
+query_pointer_position(struct wl_client *client, struct wl_resource *resource)
+{
+       struct wfits *wfits = resource->data;
+       struct weston_seat *seat = get_seat(wfits);
+
+       wfits_query_send_pointer_position(resource, seat->pointer.x,
+                                         seat->pointer.y);
+}
+
+static const struct wfits_query_interface wfits_query_implementation = {
+       query_surface_geometry,
+       query_pointer_position,
+};
+
+static void
+bind_query(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+       struct wfits *wfits = data;
+       struct wl_resource *resource;
+
+       resource = wl_client_add_object(client, &wfits_query_interface,
+                                       &wfits_query_implementation, id, wfits);
+}
+
+static void
+compositor_destroy(struct wl_listener *listener, void *data)
+{
+       struct wfits *wfits = container_of(listener, struct wfits,
+                                          compositor_destroy_listener);
+
+       weston_log("weston-wfits: destroying uinput device\n");
+
+       if (ioctl(wfits->pointer_fd, UI_DEV_DESTROY) < 0) {
+               weston_log("weston-wfits: failed to destroy uinput device\n");
+       }
 }
 
 WL_EXPORT int
 module_init(struct weston_compositor *compositor)
 {
        struct wfits *wfits;
-
-       weston_log("in weston-wfits::module_init\n");
+       struct wl_event_loop *loop;
 
        wfits = malloc(sizeof *wfits);
        if (wfits == NULL)
@@ -65,8 +284,21 @@ module_init(struct weston_compositor *compositor)
        memset(wfits, 0, sizeof *wfits);
        wfits->compositor = compositor;
 
-       if (wl_display_add_global(compositor->wl_display, &wfits_uinput_interface,
-                                 wfits, bind_uinput) == NULL)
+       if (wl_display_add_global(compositor->wl_display,
+                                 &wfits_input_interface,
+                                 wfits, bind_input) == NULL)
                return -1;
+
+       if (wl_display_add_global(compositor->wl_display,
+                                 &wfits_query_interface,
+                                 wfits, bind_query) == NULL)
+               return -1;
+       
+       create_pointer(wfits);
+
+       wfits->compositor_destroy_listener.notify = compositor_destroy;
+       wl_signal_add(&compositor->destroy_signal,
+                     &wfits->compositor_destroy_listener);
+
        return 0;
 }