This patch makes it possible to run wayland-fits without root.
This approach also stresses the evdev.c stack. (calling the notify_* api 
approach would
bypass the evdev.c stack)
Testing also the evdev.c can help code test coverage. Probably can catch more 
bugs
this way.

How it works. Basically, we make a pipe. Then we create evdev device and 
connect it
to the pipe. Then we play the events via the pipe. In the end we destroy both 
pipe
and the device.

What effects does the patch have?
This assumes weston sdk exports evdev.h
It uses evdev_device_create() and evdev_device_destroy() in the tested 
compositor.
In case the symbols are not available, wfits module will fail to be loaded.
---
 src/extensions/weston/Makefile.am      |    5 +-
 src/extensions/weston/weston-wfits.cpp |  166 +++++++++++++++++++++++---------
 2 files changed, 122 insertions(+), 49 deletions(-)

diff --git a/src/extensions/weston/Makefile.am 
b/src/extensions/weston/Makefile.am
index 4af2f1d..b65a93f 100644
--- a/src/extensions/weston/Makefile.am
+++ b/src/extensions/weston/Makefile.am
@@ -10,11 +10,14 @@ weston_wfits = weston-wfits.la
 AM_CXXFLAGS =                  \
        $(GCC_CFLAGS)                           \
        $(WAYLAND_SERVER_CFLAGS)                \
-       $(WESTON_CFLAGS)
+       $(WESTON_CFLAGS)                        \
+       -std=gnu++11
+
 weston_wfits_la_LDFLAGS = -module -avoid-version
 weston_wfits_la_LIBADD =                       \
        $(WAYLAND_SERVER_LIBS)                  \
        $(WESTON_LIBS)
+
 weston_wfits_la_SOURCES =                                              \
        weston-wfits.cpp                                                        
\
        $(top_srcdir)/src/extensions/protocol/wayland-fits-protocol.c
diff --git a/src/extensions/weston/weston-wfits.cpp 
b/src/extensions/weston/weston-wfits.cpp
index a54e0fe..96cf617 100644
--- a/src/extensions/weston/weston-wfits.cpp
+++ b/src/extensions/weston/weston-wfits.cpp
@@ -42,6 +42,10 @@ extern "C" {
 #undef private
 }
 
+extern "C" {
+#include <weston/evdev.h>
+}
+
 #include "config.h"
 #include "extensions/protocol/wayland-fits-server-protocol.h"
 #include "common/util.h"
@@ -76,8 +80,10 @@ struct x11_output {
 struct wfits {
        struct weston_compositor *compositor;
        struct wl_listener compositor_destroy_listener;
-       int input_fd; // file descriptor for our uinput device.
+       int pipe_fd[2]; // file descriptor for the pipe or the uinput fd twice
        bool is_headless; // whether weston is using a headless backend.
+       bool is_pipeston;
+       struct evdev_device *dev;
 };
 
 /**
@@ -153,14 +159,14 @@ global_size(struct wfits *wfits, int32_t *width, int32_t 
*height)
 
        output = get_output(wfits);
 
-       if (std::string(output->make) == "xwayland") {
-               x11_compositor = (struct x11_compositor*) wfits->compositor;
-               *width = x11_compositor->screen->width_in_pixels;
-               *height = x11_compositor->screen->height_in_pixels;
-       } else {
+//     if (std::string(output->make) == "xwayland") {
+//             x11_compositor = (struct x11_compositor*) wfits->compositor;
+//             *width = x11_compositor->screen->width_in_pixels;
+//             *height = x11_compositor->screen->height_in_pixels;
+//     } else {
                *width = output->width;
                *height = output->height;
-       }
+//     }
 }
 
 /**
@@ -226,6 +232,8 @@ write_event_to_fd(int fd, struct input_event *event)
 static void
 move_pointer(struct wfits *wfits, const int32_t x, const int32_t y)
 {
+       wfits->compositor->focus = 1;
+
        if (wfits->is_headless) {
                /**
                 * Weston is using a headless backend, so originate/trigger
@@ -247,24 +255,22 @@ move_pointer(struct wfits *wfits, const int32_t x, const 
int32_t y)
        struct input_event event;
        int32_t gx(x), gy(y);
 
-       compositor_to_global(wfits, &gx, &gy);
-
        memset(&event, 0, sizeof(event));
 
        event.type = EV_ABS;
        event.code = ABS_X;
        event.value = gx;
-       write_event_to_fd (wfits->input_fd, &event);
+       write_event_to_fd (wfits->pipe_fd[1], &event);
 
        event.type = EV_ABS;
        event.code = ABS_Y;
        event.value = gy;
-       write_event_to_fd (wfits->input_fd, &event);
+       write_event_to_fd (wfits->pipe_fd[1], &event);
 
        event.type = EV_SYN;
        event.code = SYN_REPORT;
        event.value = 0;
-       write_event_to_fd (wfits->input_fd, &event);
+       write_event_to_fd (wfits->pipe_fd[1], &event);
 }
 
 /**
@@ -285,6 +291,8 @@ input_move_pointer(struct wl_client *client, struct 
wl_resource *resource,
 static void
 key_send(struct wfits *wfits, const uint32_t key, const uint32_t state)
 {
+       wfits->compositor->focus = 1;
+
        if (wfits->is_headless) {
                /**
                 * Weston is using a headless backend, so originate/trigger the
@@ -292,8 +300,6 @@ key_send(struct wfits *wfits, const uint32_t key, const 
uint32_t state)
                 **/
                struct weston_seat *seat = get_seat(wfits);
 
-               wfits->compositor->focus = 1;
-
                if (key == BTN_LEFT or key == BTN_MIDDLE or key == BTN_RIGHT) {
                        notify_button(seat, 100, key,
                                static_cast<wl_pointer_button_state>(state));
@@ -317,12 +323,12 @@ key_send(struct wfits *wfits, const uint32_t key, const 
uint32_t state)
        event.type = EV_KEY;
        event.code = key;
        event.value = state;
-       write_event_to_fd(wfits->input_fd, &event);
+       write_event_to_fd(wfits->pipe_fd[1], &event);
 
        event.type = EV_SYN;
        event.code = SYN_REPORT;
        event.value = 0;
-       write_event_to_fd(wfits->input_fd, &event);
+       write_event_to_fd(wfits->pipe_fd[1], &event);
 }
 
 /**
@@ -384,56 +390,96 @@ bind_input(struct wl_client *client, void *data, uint32_t 
version, uint32_t id)
        resource->destroy = unbind_input_client;
 }
 
-static void
-create_input(struct wfits* wfits)
+static int
+create_input_pipeston(struct wfits* wfits)
+{
+       int32_t width;
+       int32_t height;
+
+       if (pipe(wfits->pipe_fd) < 0) {
+               return -1;
+       }
+
+       fcntl(wfits->pipe_fd[0], F_SETFD, fcntl(wfits->pipe_fd[0], F_GETFD) | 
FD_CLOEXEC);
+       fcntl(wfits->pipe_fd[0], F_SETFL, fcntl(wfits->pipe_fd[0], F_GETFL) | 
O_NONBLOCK);
+       fcntl(wfits->pipe_fd[1], F_SETFD, fcntl(wfits->pipe_fd[1], F_GETFD) | 
FD_CLOEXEC);
+
+       /*
+               create only 1 device on 1 seat for now.
+       */
+
+       wfits->dev = evdev_device_create(get_seat(wfits), "<mock-dev-path>", 
wfits->pipe_fd[0]);
+
+
+       if ((wfits->dev == NULL) || (wfits->dev == EVDEV_UNHANDLED_DEVICE)) {
+               weston_log("ERROR creating device\n");
+               wfits->dev = NULL;
+               return -2;
+       }
+
+       wfits->dev->output = get_output(wfits);
+       global_size(wfits, &width, &height);
+       weston_log("%dx%d\n", width, height);
+       wfits->dev->abs.max_x = width - 1;
+       wfits->dev->abs.max_y = height - 1;
+       wfits->dev->abs.min_x = 0;
+       wfits->dev->abs.min_y = 0;
+
+       wl_list_init(&wfits->dev->link);
+
+       wfits->is_pipeston = true;
+
+       return 0;
+}
+
+static int
+create_input_uinput(struct wfits* wfits)
 {
        struct uinput_user_dev device;
        struct weston_output *output = get_output(wfits);
        int32_t width;
        int32_t height;
-       
-       weston_log("weston-wfits: creating uinput device\n");
 
-       wfits->input_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
-       if (wfits->input_fd < 0) {
-               weston_log("weston-wfits: failed to create uinput device\n");
-               exit(EXIT_FAILURE);
+       wfits->pipe_fd[0] = wfits->pipe_fd[1] = open("/dev/uinput", O_WRONLY | 
O_NDELAY);
+       if (wfits->pipe_fd[1] < 0) {
+               return -1;
        }
 
-       if (ioctl(wfits->input_fd, UI_SET_EVBIT, EV_KEY) < 0) {
-               exit(EXIT_FAILURE);
+       if (ioctl(wfits->pipe_fd[1], UI_SET_EVBIT, EV_KEY) < 0) {
+               return -2;
        }
        
        for (int32_t i(0); i < 255; ++i) {
-               if (ioctl(wfits->input_fd, UI_SET_KEYBIT, i) < 0) {
-                       exit(EXIT_FAILURE);
+               if (ioctl(wfits->pipe_fd[1], UI_SET_KEYBIT, i) < 0) {
+                       return -3;
                }
        }
        
-       if (ioctl(wfits->input_fd, UI_SET_KEYBIT, BTN_LEFT) < 0) {
-               exit(EXIT_FAILURE);
+       if (ioctl(wfits->pipe_fd[1], UI_SET_KEYBIT, BTN_LEFT) < 0) {
+               return -4;
        }
 
-       if (ioctl(wfits->input_fd, UI_SET_KEYBIT, BTN_RIGHT) < 0) {
-               exit(EXIT_FAILURE);
+       if (ioctl(wfits->pipe_fd[1], UI_SET_KEYBIT, BTN_RIGHT) < 0) {
+               return -5;
        }
 
-       if (ioctl(wfits->input_fd, UI_SET_KEYBIT, BTN_MIDDLE) < 0) {
-               exit(EXIT_FAILURE);
+       if (ioctl(wfits->pipe_fd[1], UI_SET_KEYBIT, BTN_MIDDLE) < 0) {
+               return -6;
        }
 
-       if (ioctl(wfits->input_fd, UI_SET_EVBIT, EV_ABS) < 0) {
-               exit(EXIT_FAILURE);
+       if (ioctl(wfits->pipe_fd[1], UI_SET_EVBIT, EV_ABS) < 0) {
+               return -7;
        }
 
-       if (ioctl(wfits->input_fd, UI_SET_ABSBIT, ABS_X) < 0) {
-               exit(EXIT_FAILURE);
+       if (ioctl(wfits->pipe_fd[1], UI_SET_ABSBIT, ABS_X) < 0) {
+               return -8;
        }
 
-       if (ioctl(wfits->input_fd, UI_SET_ABSBIT, ABS_Y) < 0) {
-               exit(EXIT_FAILURE);
+       if (ioctl(wfits->pipe_fd[1], UI_SET_ABSBIT, ABS_Y) < 0) {
+               return -9;
        }
 
+
        memset(&device, 0, sizeof(device));
        snprintf(device.name, UINPUT_MAX_NAME_SIZE, "WFITS INPUT");
        device.id.bustype = BUS_USB;
@@ -450,13 +496,17 @@ create_input(struct wfits* wfits)
        device.absmin[ABS_Y] = 0;
        device.absmax[ABS_Y] = height - 1;
 
-       if (write(wfits->input_fd, &device, sizeof(device)) < 0) {
-               exit(EXIT_FAILURE);
+       if (write(wfits->pipe_fd[1], &device, sizeof(device)) < 0) {
+               return -10;
        }
 
-       if (ioctl(wfits->input_fd, UI_DEV_CREATE) < 0) {
-               exit(EXIT_FAILURE);
+       if (ioctl(wfits->pipe_fd[1], UI_DEV_CREATE) < 0) {
+               return -11;
        }
+
+       wfits->is_pipeston = false;
+
+       return 0;
 }
 
 static void
@@ -534,8 +584,15 @@ compositor_destroy(struct wl_listener *listener, void 
*data)
        if (not wfits->is_headless) {
                weston_log("weston-wfits: destroying uinput device\n");
 
-               if (ioctl(wfits->input_fd, UI_DEV_DESTROY) < 0) {
-                       weston_log("weston-wfits: failed to destroy uinput 
device\n");
+               if (not wfits->is_pipeston) {
+                       if (ioctl(wfits->pipe_fd[1], UI_DEV_DESTROY) < 0) {
+                               weston_log("weston-wfits: failed to destroy 
uinput device\n");
+                       }
+               } else {
+                       if (wfits->dev != NULL)
+                               evdev_device_destroy(wfits->dev);
+                       close(wfits->pipe_fd[1]);
+                       close(wfits->pipe_fd[0]);
                }
        }
 }
@@ -546,8 +603,21 @@ init_input(void *data)
        struct wfits *wfits = static_cast<struct wfits*>(data);
 
        if (not wfits->is_headless) {
-               create_input(wfits);
-               /* sync our input pointer device with weston */
+               int err1 = 0, err2 = 0;
+
+               if (err1 = create_input_uinput(wfits)) {
+                       weston_log("weston-wfits: creating pipeston device\n");
+                       err2 = create_input_pipeston(wfits);
+               } else {
+                       weston_log("weston-wfits: created uinput device\n");
+               }
+
+               if (err1 && err2) {
+                       weston_log("weston-wfits: create uinput failed: %i, "
+                                       "pipeston failed: %i\n", err1, err2);
+                       exit(EXIT_FAILURE);
+               }
+               /* sync our single input pointer device with weston */
                wl_fixed_t cx, cy;
                get_pointer_xy(wfits, &cx, &cy);
                move_pointer(wfits, wl_fixed_to_int(cx), wl_fixed_to_int(cy));
-- 
1.7.10.4

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to