diff --git a/egl-compositor.c b/egl-compositor.c index 731396a6..49afe16f 100644 --- a/egl-compositor.c +++ b/egl-compositor.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -55,6 +57,7 @@ struct egl_input_device { int32_t x, y; struct egl_compositor *ec; struct egl_surface *pointer_surface; + struct wl_list link; int grab; struct egl_surface *grab_surface; @@ -73,8 +76,7 @@ struct egl_compositor { struct egl_surface *overlay; double overlay_y, overlay_target, overlay_previous; - struct egl_input_device *input_device; - + struct wl_list input_device_list; struct wl_list surface_list; /* Repaint state. */ @@ -571,6 +573,7 @@ repaint(void *data) { struct egl_compositor *ec = data; struct egl_surface *es; + struct egl_input_device *eid; struct timespec ts; uint32_t msecs; @@ -592,7 +595,14 @@ repaint(void *data) draw_surface(ec->overlay); - draw_surface(ec->input_device->pointer_surface); + eid = container_of(ec->input_device_list.next, + struct egl_input_device, link); + while (&eid->link != &ec->input_device_list) { + draw_surface(eid->pointer_surface); + + eid = container_of(eid->link.next, + struct egl_input_device, link); + } eglSwapBuffers(ec->display, ec->surface); ec->repaint_needed = 0; @@ -747,6 +757,9 @@ pick_surface(struct egl_input_device *device) struct egl_compositor *ec = device->ec; struct egl_surface *es; + if (device->grab > 0) + return device->grab_surface; + es = container_of(ec->surface_list.prev, struct egl_surface, link); while (&es->link != &ec->surface_list) { @@ -770,10 +783,7 @@ notify_motion(struct egl_input_device *device, int x, int y) const int hotspot_x = 16, hotspot_y = 16; int32_t sx, sy; - if (device->grab > 0) - es = device->grab_surface; - else - es = pick_surface(device); + es = pick_surface(device); if (es) { sx = (x - es->map.x) * es->width / es->map.width; @@ -795,6 +805,7 @@ notify_button(struct egl_input_device *device, int32_t button, int32_t state) { struct egl_surface *es; + int32_t sx, sy; es = pick_surface(device); if (es) { @@ -808,9 +819,13 @@ notify_button(struct egl_input_device *device, device->grab--; } + sx = (device->x - es->map.x) * es->width / es->map.width; + sy = (device->y - es->map.y) * es->height / es->map.height; + /* FIXME: Swallow click on raise? */ wl_surface_post_event(es->wl_surface, &device->base, - WL_INPUT_BUTTON, button, state); + WL_INPUT_BUTTON, button, state, + device->x, device->y, sx, sy); schedule_repaint(device->ec); } @@ -851,11 +866,6 @@ static const struct wl_compositor_interface interface = { notify_commit, }; -static const char pointer_device_file[] = - "/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-mouse"; -static const char keyboard_device_file[] = - "/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-kbd"; - struct evdev_input_device * evdev_input_device_create(struct egl_input_device *device, struct wl_display *display, const char *path); @@ -864,34 +874,42 @@ void egl_device_get_position(struct egl_input_device *device, int32_t *x, int32_t *y); static void -create_input_devices(struct egl_compositor *ec) +create_input_device(struct egl_compositor *ec, const char *glob) { struct egl_input_device *device; - const char *path; + struct dirent *de; + char path[PATH_MAX]; + const char *by_path_dir = "/dev/input/by-path"; + DIR *dir; device = malloc(sizeof *device); if (device == NULL) return; + memset(device, 0, sizeof *device); device->base.interface = wl_input_device_get_interface(); wl_display_add_object(ec->wl_display, &device->base); - ec->input_device = device; device->x = 100; device->y = 100; device->pointer_surface = pointer_create(device->x, device->y, 64, 64); device->ec = ec; - path = getenv("WAYLAND_POINTER"); - if (path == NULL) - path = pointer_device_file; + dir = opendir(by_path_dir); + if (dir == NULL) { + fprintf(stderr, "couldn't read dir %s\n", by_path_dir); + return; + } - evdev_input_device_create(device, ec->wl_display, path); + while (de = readdir(dir), de != NULL) { + if (fnmatch(glob, de->d_name, 0)) + continue; - path = getenv("WAYLAND_KEYBOARD"); - if (path == NULL) - path = keyboard_device_file; + snprintf(path, sizeof path, "%s/%s", by_path_dir, de->d_name); + evdev_input_device_create(device, ec->wl_display, path); + } + closedir(dir); - evdev_input_device_create(device, ec->wl_display, path); + wl_list_insert(ec->input_device_list.prev, &device->link); } void @@ -1047,10 +1065,18 @@ pick_config(struct egl_compositor *ec) static const char gem_device[] = "/dev/dri/card0"; -static const char *background_image = "background.jpg"; +static const char *macbook_air_default_input_device[] = { + "pci-0000:00:1d.0-usb-0:2:1*event*" +}; + +static const char *option_background = "background.jpg"; +static const char **option_input_devices = macbook_air_default_input_device; -static GOptionEntry option_entries[] = { - { "background", 'b', 0, G_OPTION_ARG_STRING, &background_image, "Background image" }, +static const GOptionEntry option_entries[] = { + { "background", 'b', 0, G_OPTION_ARG_STRING, + &option_background, "Background image" }, + { "input-device", 'i', 0, G_OPTION_ARG_STRING_ARRAY, + &option_input_devices, "Input device glob" }, { NULL } }; @@ -1061,7 +1087,7 @@ egl_compositor_create(struct wl_display *display) struct egl_compositor *ec; struct screenshooter *shooter; uint32_t fb_name; - int stride; + int i, stride; struct wl_event_loop *loop; const static EGLint attribs[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE }; @@ -1113,10 +1139,12 @@ egl_compositor_create(struct wl_display *display) glOrtho(0, ec->width, ec->height, 0, 0, 1000.0); glMatrixMode(GL_MODELVIEW); - create_input_devices(ec); + wl_list_init(&ec->input_device_list); + for (i = 0; option_input_devices[i]; i++) + create_input_device(ec, option_input_devices[i]); wl_list_init(&ec->surface_list); - ec->background = background_create(background_image, + ec->background = background_create(option_background, ec->width, ec->height); ec->overlay = overlay_create(0, ec->height, ec->width, 200); ec->overlay_y = ec->height; diff --git a/wayland.c b/wayland.c index e21d246f..647e8592 100644 --- a/wayland.c +++ b/wayland.c @@ -646,7 +646,7 @@ static const struct wl_method input_device_methods[] = { static const struct wl_event input_device_events[] = { { "motion", "iiii" }, - { "button", "uu" }, + { "button", "uuiiii" }, { "key", "uu" }, }; diff --git a/window.c b/window.c index c44d29bd..bf838545 100644 --- a/window.c +++ b/window.c @@ -46,8 +46,9 @@ struct window { int x, y, width, height; int minimum_width, minimum_height; int margin; - int drag_x, drag_y, last_x, last_y; + int drag_x, drag_y; int state; + uint32_t grab_device; uint32_t name; int fd; @@ -232,10 +233,10 @@ event_handler(struct wl_display *display, } else if (opcode == 0) { int x = p[0], y = p[1]; - window->last_x = x; - window->last_y = y; switch (window->state) { case WINDOW_MOVING: + if (window->grab_device != object) + break; window->x = window->drag_x + x; window->y = window->drag_y + y; wl_surface_map(window->surface, @@ -246,6 +247,8 @@ event_handler(struct wl_display *display, wl_display_commit(window->display, 1); break; case WINDOW_RESIZING_LOWER_RIGHT: + if (window->grab_device != object) + break; window->width = window->drag_x + x; window->height = window->drag_y + y; @@ -258,16 +261,15 @@ event_handler(struct wl_display *display, } } else if (opcode == 1) { int button = p[0], state = p[1]; + int32_t x = p[2], y = p[3]; - if (window->x + window->width - grip_size <= window->last_x && - window->last_x < window->x + window->width && - window->y + window->height - grip_size <= window->last_y && - window->last_y < window->y + window->height) { + if (window->x + window->width - grip_size <= x && + x < window->x + window->width && + window->y + window->height - grip_size <= y && + y < window->y + window->height) { location = LOCATION_LOWER_RIGHT; - } else if (window->x <= window->last_x && - window->last_x < window->x + window->width && - window->y <= window->last_y && - window->last_y < window->y + window->height) { + } else if (window->x <= x && x < window->x + window->width && + window->y <= y && y < window->y + window->height) { location = LOCATION_INTERIOR; } else { location = LOCATION_OUTSIDE; @@ -276,20 +278,23 @@ event_handler(struct wl_display *display, if (button == BTN_LEFT && state == 1) { switch (location) { case LOCATION_INTERIOR: - window->drag_x = window->x - window->last_x; - window->drag_y = window->y - window->last_y; + window->drag_x = window->x - x; + window->drag_y = window->y - y; window->state = WINDOW_MOVING; + window->grab_device = object; break; case LOCATION_LOWER_RIGHT: - window->drag_x = window->width - window->last_x; - window->drag_y = window->height - window->last_y; + window->drag_x = window->width - x; + window->drag_y = window->height - y; window->state = WINDOW_RESIZING_LOWER_RIGHT; + window->grab_device = object; break; default: window->state = WINDOW_STABLE; break; } - } else if (button == BTN_LEFT && state == 0) { + } else if (button == BTN_LEFT && + state == 0 && object == window->grab_device) { window->state = WINDOW_STABLE; } } else if (opcode == 2) {