diff --git a/configure.ac b/configure.ac index e67ad50d..754469fe 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,7 @@ AC_ARG_ENABLE(android-compositor, AM_CONDITIONAL(ENABLE_ANDROID_COMPOSITOR, test x$enable_android_compositor = xyes) if test x$enable_android_compositor = xyes; then AC_DEFINE([BUILD_ANDROID_COMPOSITOR], [1], [Build the compositor for Android 4.0]) + PKG_CHECK_MODULES(ANDROID_COMPOSITOR, [mtdev >= 1.1.0]) fi diff --git a/src/Makefile.am b/src/Makefile.am index 2cf9d6b5..8096849d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -124,12 +124,18 @@ endif if ENABLE_ANDROID_COMPOSITOR android_backend = android-backend.la android_backend_la_LDFLAGS = -module -avoid-version -android_backend_la_LIBADD = $(COMPOSITOR_LIBS) -android_backend_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) +android_backend_la_LIBADD = $(COMPOSITOR_LIBS) $(ANDROID_COMPOSITOR_LIBS) +android_backend_la_CFLAGS = \ + $(GCC_CFLAGS) \ + $(COMPOSITOR_CFLAGS) \ + $(ANDROID_COMPOSITOR_CFLAGS) android_backend_la_CXXFLAGS = $(GCC_CXXFLAGS) $(COMPOSITOR_CFLAGS) -android_backend_la_SOURCES = \ - compositor-android.c \ - android-framebuffer.cpp \ +android_backend_la_SOURCES = \ + compositor-android.c \ + evdev.c \ + evdev.h \ + evdev-touchpad.c \ + android-framebuffer.cpp \ android-framebuffer.h endif diff --git a/src/compositor-android.c b/src/compositor-android.c index a61c5ea4..5d1eeee7 100644 --- a/src/compositor-android.c +++ b/src/compositor-android.c @@ -20,16 +20,24 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define _GNU_SOURCE + #include #include #include #include +#include +#include +#include +#include +#include #include #include #include "compositor.h" #include "android-framebuffer.h" +#include "evdev.h" struct android_compositor; @@ -44,6 +52,7 @@ struct android_output { struct android_seat { struct weston_seat base; + struct wl_list devices_list; }; struct android_compositor { @@ -58,6 +67,12 @@ to_android_output(struct weston_output *base) return container_of(base, struct android_output, base); } +static inline struct android_seat * +to_android_seat(struct weston_seat *base) +{ + return container_of(base, struct android_seat, base); +} + static inline struct android_compositor * to_android_compositor(struct weston_compositor *base) { @@ -228,9 +243,86 @@ android_compositor_add_output(struct android_compositor *compositor, wl_list_insert(compositor->base.output_list.prev, &output->base.link); } +static void +android_led_update(struct weston_seat *seat_base, enum weston_led leds) +{ + struct android_seat *seat = to_android_seat(seat_base); + + evdev_led_update(&seat->devices_list, leds); +} + +static void +android_seat_open_device(struct android_seat *seat, const char *devnode) +{ + struct evdev_input_device *device; + int fd; + + /* XXX: check the Android excluded list */ + + fd = open(devnode, O_RDWR | O_NONBLOCK | O_CLOEXEC); + if (fd < 0) { + weston_log_continue("opening '%s' failed: %s\n", devnode, + strerror(errno)); + return; + } + + device = evdev_input_device_create(&seat->base, devnode, fd); + if (!device) { + close(fd); + return; + } + + wl_list_insert(seat->devices_list.prev, &device->link); +} + +static int +is_dot_or_dotdot(const char *str) +{ + return (str[0] == '.' && + (str[1] == 0 || (str[1] == '.' && str[2] == 0))); +} + +static void +android_seat_scan_devices(struct android_seat *seat, const char *dirpath) +{ + int ret; + DIR *dir; + struct dirent *dent; + char *devnode = NULL; + + dir = opendir(dirpath); + if (!dir) { + weston_log("Could not open input device directory '%s': %s\n", + dirpath, strerror(errno)); + return; + } + + while ((dent = readdir(dir)) != NULL) { + if (is_dot_or_dotdot(dent->d_name)) + continue; + + ret = asprintf(&devnode, "%s/%s", dirpath, dent->d_name); + if (ret < 0) + continue; + + android_seat_open_device(seat, devnode); + free(devnode); + } + + closedir(dir); +} + static void android_seat_destroy(struct android_seat *seat) { + struct evdev_input_device *device, *next; + + wl_list_for_each_safe(device, next, &seat->devices_list, link) + evdev_input_device_destroy(device); + + if (seat->base.seat.keyboard) + notify_keyboard_focus_out(&seat->base.seat); + weston_seat_release(&seat->base); free(seat); } @@ -245,8 +337,19 @@ android_seat_create(struct android_compositor *compositor) return NULL; weston_seat_init(&seat->base, &compositor->base); + seat->base.led_update = android_led_update; + wl_list_init(&seat->devices_list); compositor->base.seat = &seat->base; + android_seat_scan_devices(seat, "/dev/input"); + + evdev_notify_keyboard_focus(&seat->base, &seat->devices_list); + + if (wl_list_empty(&seat->devices_list)) + weston_log("Warning: no input devices found.\n"); + + /* XXX: implement hotplug support */ + return seat; } @@ -412,6 +515,8 @@ android_compositor_create(struct wl_display *display, int argc, char *argv[], struct android_compositor *compositor; struct android_output *output; + weston_log("initializing android backend\n"); + compositor = calloc(1, sizeof *compositor); if (compositor == NULL) return NULL;