[PATCH] weston-launch: only drop privileges when uid/gid != euid/egid
initgroups requires CAP_SETGID and may fail. If we're not actually changing anything anyway we can just skip this and (most likely) fail later when we don't have the required permissions to open something. --- Should arguably be part of the previous patch but since it changes behaviour from before 636156d, here it is separately. running weston-launch as user (w/o suid bit set) now passes this bit (and fails later, but still :) src/weston-launch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/weston-launch.c b/src/weston-launch.c index 5b03094..06194a9 100644 --- a/src/weston-launch.c +++ b/src/weston-launch.c @@ -554,7 +554,8 @@ launch_compositor(struct weston_launch *wl, int argc, char *argv[]) if (wl->new_user) setup_session(wl); - drop_privileges(wl); + if (getuid() != geteuid() || getgid() != getegid()) + drop_privileges(wl); if (wl->tty != STDIN_FILENO) setenv_fd("WESTON_TTY_FD", wl->tty); -- 1.8.2.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] weston-launch: always drop privileges before execve
The current code works if pw->pw_shell is bash because: "If the shell is started with the effective user (group) id not equal to the real user (group) id, and the -p option is not supplied, these actions are taken and the effective user id is set to the real user id." Thus, for bash, weston's EUID == UID. For zsh, the -p option "is enabled automatically on startup if the effective user (group) ID is not equal to the real user (group) ID." Thus, weston's EUID = 0, and if pw_shell is zsh, /run/user/$UID/wayland-0 is created with euid root and not writeable by the user, causing all clients to fail. Fix this by always dropping privileges to the user. Regression introduced in 636156d. --- src/weston-launch.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/weston-launch.c b/src/weston-launch.c index a111812..5b03094 100644 --- a/src/weston-launch.c +++ b/src/weston-launch.c @@ -513,13 +513,6 @@ setup_session(struct weston_launch *wl) error(1, errno, "TIOCSCTTY failed - tty is in use"); } - if (setgid(wl->pw->pw_gid) < 0 || -#ifdef HAVE_INITGROUPS - initgroups(wl->pw->pw_name, wl->pw->pw_gid) < 0 || -#endif - setuid(wl->pw->pw_uid) < 0) - error(1, errno, "dropping privileges failed"); - term = getenv("TERM"); clearenv(); setenv("TERM", term, 1); @@ -539,6 +532,17 @@ setup_session(struct weston_launch *wl) } static void +drop_privileges(struct weston_launch *wl) +{ + if (setgid(wl->pw->pw_gid) < 0 || +#ifdef HAVE_INITGROUPS + initgroups(wl->pw->pw_name, wl->pw->pw_gid) < 0 || +#endif + setuid(wl->pw->pw_uid) < 0) + error(1, errno, "dropping privileges failed"); +} + +static void launch_compositor(struct weston_launch *wl, int argc, char *argv[]) { char *child_argv[MAX_ARGV_SIZE]; @@ -550,6 +554,8 @@ launch_compositor(struct weston_launch *wl, int argc, char *argv[]) if (wl->new_user) setup_session(wl); + drop_privileges(wl); + if (wl->tty != STDIN_FILENO) setenv_fd("WESTON_TTY_FD", wl->tty); -- 1.8.2.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] Drop extraneous duplicate header includes
From: Bryce Harrington Signed-off-by: Bryce Harrington --- clients/flower.c |1 - clients/smoke.c|1 - src/compositor-drm.c |1 - src/compositor-fbdev.c |2 -- 4 files changed, 5 deletions(-) diff --git a/clients/flower.c b/clients/flower.c index 87a1a00..b31d513 100644 --- a/clients/flower.c +++ b/clients/flower.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/clients/smoke.c b/clients/smoke.c index 5d7333d..0177424 100644 --- a/clients/smoke.c +++ b/clients/smoke.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/src/compositor-drm.c b/src/compositor-drm.c index c7d6c04..a47fe36 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c index 10ba7db..73ce37b 100644 --- a/src/compositor-fbdev.c +++ b/src/compositor-fbdev.c @@ -39,8 +39,6 @@ #include -#include "config.h" - #include "compositor.h" #include "launcher-util.h" #include "pixman-renderer.h" -- 1.7.9.5 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH 3/4 v2] xwayland: Draw decoration on window manager side
Draw everything in a cairo image surface before copying it to the XCB surface. That removes the flickering visible on rpi whenever the decoration were redrawn. --- src/xwayland/window-manager.c | 26 -- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c index 15cb2ed..594c64f 100644 --- a/src/xwayland/window-manager.c +++ b/src/xwayland/window-manager.c @@ -97,6 +97,7 @@ struct weston_wm_window { xcb_window_t id; xcb_window_t frame_id; cairo_surface_t *cairo_surface; + cairo_surface_t *cairo_xcb_surface; struct weston_surface *surface; struct shell_surface *shsurf; struct wl_listener surface_destroy_listener; @@ -900,12 +901,16 @@ weston_wm_handle_map_request(struct weston_wm *wm, xcb_generic_event_t *event) xcb_map_window(wm->conn, map_request->window); xcb_map_window(wm->conn, window->frame_id); - window->cairo_surface = + window->cairo_xcb_surface = cairo_xcb_surface_create_with_xrender_format(wm->conn, wm->screen, window->frame_id, &wm->format_rgba, width, height); + window->cairo_surface = + cairo_surface_create_similar_image(window->cairo_xcb_surface, + CAIRO_FORMAT_ARGB32, + width, height); hash_table_insert(wm->window_hash, window->frame_id, window); @@ -967,6 +972,8 @@ weston_wm_handle_unmap_notify(struct weston_wm *wm, xcb_generic_event_t *event) wl_event_source_remove(window->repaint_source); if (window->cairo_surface) cairo_surface_destroy(window->cairo_surface); + if (window->cairo_xcb_surface) + cairo_surface_destroy(window->cairo_xcb_surface); if (window->frame_id) { xcb_reparent_window(wm->conn, window->id, wm->wm_window, 0, 0); @@ -1009,7 +1016,16 @@ weston_wm_window_draw_decoration(void *data) weston_wm_window_get_frame_size(window, &width, &height); weston_wm_window_get_child_position(window, &x, &y); - cairo_xcb_surface_set_size(window->cairo_surface, width, height); + if (cairo_image_surface_get_width(window->cairo_surface) != width || + cairo_image_surface_get_height(window->cairo_surface) != height) { + cairo_surface_destroy(window->cairo_surface); + window->cairo_surface = + cairo_surface_create_similar_image(window->cairo_xcb_surface, + CAIRO_FORMAT_ARGB32, + width, height); + cairo_xcb_surface_set_size(window->cairo_xcb_surface, width, height); + } + cr = cairo_create(window->cairo_surface); if (window->fullscreen) { @@ -1036,6 +1052,12 @@ weston_wm_window_draw_decoration(void *data) cairo_destroy(cr); + cr = cairo_create(window->cairo_xcb_surface); + cairo_set_source_surface(cr, window->cairo_surface, 0, 0); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + cairo_destroy(cr); + if (window->surface) { pixman_region32_fini(&window->surface->pending.opaque); if(window->has_alpha) { -- 1.8.1.4 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH 3/4] xwayland: Draw decoration on window manager side
On Wednesday, July 31, 2013 10:41 EDT, Uli Schlachter wrote: > Hi, > > On 30.07.2013 18:13, Louis-Francis Ratté-Boulianne wrote: > > Draw everything in a cairo image surface before copying it to the XCB > > surface. That removes the flickering visible on rpi whenever the > > decoration were redrawn. > > --- > > src/xwayland/window-manager.c | 22 -- > > 1 file changed, 20 insertions(+), 2 deletions(-) > > > > diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c > > index b3c9251..57a5d99 100644 > > --- a/src/xwayland/window-manager.c > > +++ b/src/xwayland/window-manager.c > > @@ -97,6 +97,7 @@ struct weston_wm_window { > > xcb_window_t id; > > xcb_window_t frame_id; > > cairo_surface_t *cairo_surface; > > + cairo_surface_t *cairo_xcb_surface; > > struct weston_surface *surface; > > struct shell_surface *shsurf; > > struct wl_listener surface_destroy_listener; > > @@ -900,12 +901,14 @@ weston_wm_handle_map_request(struct weston_wm *wm, > > xcb_generic_event_t *event) > > xcb_map_window(wm->conn, map_request->window); > > xcb_map_window(wm->conn, window->frame_id); > > > > - window->cairo_surface = > > + window->cairo_xcb_surface = > > cairo_xcb_surface_create_with_xrender_format(wm->conn, > > wm->screen, > > window->frame_id, > > &wm->format_rgba, > > width, height); > > + window->cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, > > + width, height); > [...] > > Why do you use an image surface for this? I would suggest to use > cairo_surface_create_similar() instead. This might then give you an XCB > surface > drawing to a temporary pixmap (but it could also be an image surface or > something completely different). I tried this way, but it still flickers between a black surface and the drawn decoration when the decorations are updated or the window is resized. It's still better than having each element showing up one after the other, but still really ugly. Also, I was wondering..if the similar surface that has been created is a XCB one, is the rendering on the server side? The objective of my patch was to move the drawing on client side (wm) so we know when it's done and we can push it to the screen. > If there is some reason for forcing image surfaces and if depending on cairo > 1.12 is no problem, I would suggest to use > cairo_surface_create_similar_image() > at least. This would make it possible for cairo to use shared memory instead > of > sending all the pixels over the X11 socket. That's seem to be the only solution that avoids any flickering while drawing the decoration on slow hardware (Raspberry Pi in my case). Unfortunately, there is a bug in Cairo < 1.12.6. So if you feel confident that we can update the dependency, that's the patch you should push. If not, the old patch still seems to be the only working solution for me. Related cairo commit: "xcb: Clear the result of create_similar_image" > And a third idea would be to use cairo_push_group(); / > cairo_pop_group_to_source(); cairo_paint();. This would need to be done around > the drawing code. I don't know this code and I am too lazy to look it up, but > if > this works and could be done easily, this would avoid the memory usage for > keeping the double-buffering surface around always. That solution would have been really great to avoid the memory usage, but a similar problem occurs (flickering). I guess it's because the decorations are still rendered on server side. Thanks for the review. If you want to see the patches I came up with to test the other solutions, let me know. -- Louis-Francis > Cheers, > Uli > -- > - He made himself, me nothing, you nothing out of the dust > - Er machte sich mir nichts, dir nichts aus dem Staub ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] clients: Fix typo in simple-touch and simple-shm.
listenter -> listener. Better fix it now before it spreads further. Signed-off-by: Stefan Schmidt --- clients/simple-shm.c |4 ++-- clients/simple-touch.c |4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clients/simple-shm.c b/clients/simple-shm.c index f187b10..98102eb 100644 --- a/clients/simple-shm.c +++ b/clients/simple-shm.c @@ -294,7 +294,7 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) d->formats |= (1 << format); } -struct wl_shm_listener shm_listenter = { +struct wl_shm_listener shm_listener = { shm_format }; @@ -314,7 +314,7 @@ registry_handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, "wl_shm") == 0) { d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); - wl_shm_add_listener(d->shm, &shm_listenter, d); + wl_shm_add_listener(d->shm, &shm_listener, d); } } diff --git a/clients/simple-touch.c b/clients/simple-touch.c index 534c77c..9e4c60a 100644 --- a/clients/simple-touch.c +++ b/clients/simple-touch.c @@ -95,7 +95,7 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) touch->has_argb = 1; } -struct wl_shm_listener shm_listenter = { +struct wl_shm_listener shm_listener = { shm_format }; @@ -257,7 +257,7 @@ handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, "wl_shm") == 0) { touch->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); - wl_shm_add_listener(touch->shm, &shm_listenter, touch); + wl_shm_add_listener(touch->shm, &shm_listener, touch); } else if (strcmp(interface, "wl_seat") == 0) { touch->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); -- 1.7.9.5 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 8/8] evdev-touchpad: Autodetect known Sony-style touchpads
From: "Alexander E. Patrakov" --- src/evdev-touchpad.c | 24 1 file changed, 24 insertions(+) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 53de1e7..e36c2aa 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -193,7 +193,31 @@ configure_interaction_model(struct touchpad_dispatch *touchpad) case TOUCHPAD_MODEL_APPLETOUCH: touchpad->interaction_model = INTERACTION_MODEL_APPLE; break; + case TOUCHPAD_MODEL_SYNAPTICS: + case TOUCHPAD_MODEL_ELANTECH: + case TOUCHPAD_MODEL_ALPS: + /* +* FIXME: fallback to INTERACTION_MODEL_SIMPLE if out +* requirements such as multitouch support or pressure +* readings are not met. +*/ + touchpad->interaction_model = INTERACTION_MODEL_SONY; + break; default: + /* Note: Chromebook Pixel also gets here because of the following: +* I: Bus=0018 Vendor= Product= Version= +* N: Name="Atmel maXTouch Touchpad" +* P: Phys=i2c-1-004b/input0 +* S: Sysfs=/devices/pci:00/:00:02.0/i2c-1/1-004b/input/input9 +* U: Uniq= +* H: Handlers=mouse1 event9 +* B: PROP=5 +* B: EV=b +* B: KEY=e520 1 0 0 0 0 +* B: ABS=6618103 +* +* Actually, Apple-style interaction is appropriate for Chromebooks. +*/ weston_log("Found a buttonpad of unknown type, assuming Apple-style\n"); touchpad->interaction_model = INTERACTION_MODEL_APPLE; break; -- 1.8.3.2 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 7/8] evdev-touchpad: Use multitouch for Sony touchpads
From: "Alexander E. Patrakov" Track finger poritions and virtual buttons --- src/evdev-touchpad.c | 168 +-- 1 file changed, 149 insertions(+), 19 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 01c52aa..53de1e7 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -76,9 +76,10 @@ struct touchpad_motion { }; enum touchpad_fingers_state { - TOUCHPAD_FINGERS_ONE = (1 << 0), - TOUCHPAD_FINGERS_TWO = (1 << 1), - TOUCHPAD_FINGERS_THREE = (1 << 2) + TOUCHPAD_FINGERS_NONE_YET = 1, + TOUCHPAD_FINGERS_ONE = (1 << 1), + TOUCHPAD_FINGERS_TWO = (1 << 2), + TOUCHPAD_FINGERS_THREE = (1 << 3) }; enum fsm_event { @@ -106,6 +107,7 @@ struct touchpad_dispatch { int last_finger_state; int slot; int relevant_touch; + int virtual_buttons; double constant_accel_factor; double min_accel_factor; @@ -127,6 +129,7 @@ struct touchpad_dispatch { bool is_moving; bool is_pressed; + bool tracking_id_changed; } hw_abs[MAX_SLOTS + 1]; bool has_moved; @@ -145,6 +148,11 @@ struct touchpad_dispatch { int32_t center_y; } hysteresis; + struct { + int32_t center_x; + int32_t separator_y; + } boundaries; + struct touchpad_motion motion_history[TOUCHPAD_HISTORY_LENGTH]; int motion_index; unsigned int motion_count; @@ -441,7 +449,7 @@ fsm_timout_handler(void *data) } static bool -is_valid_touch(struct touchpad_dispatch *touchpad, int slot) +is_valid_touch(struct touchpad_dispatch *touchpad, int slot, bool for_buttons) { if (!touchpad->hw_abs[slot].x_valid) return false; @@ -449,6 +457,14 @@ is_valid_touch(struct touchpad_dispatch *touchpad, int slot) return false; if (!touchpad->hw_abs[slot].is_pressed) return false; + if (touchpad->interaction_model == INTERACTION_MODEL_SONY) { + if (for_buttons && + touchpad->hw_abs[slot].y < touchpad->boundaries.separator_y) + return false; + if (!for_buttons && + touchpad->hw_abs[slot].y >= touchpad->boundaries.separator_y) + return false; + } return true; } @@ -466,12 +482,24 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) int last_valid_touch = -1; int relevant_touch = touchpad->relevant_touch; bool reset_motion = false; + int mt_finger_state = TOUCHPAD_FINGERS_NONE_YET; - for (i = 0; i < MAX_SLOTS; i++) - if (is_valid_touch(touchpad, i)) { + for (i = 0; i < MAX_SLOTS; i++) { + if (touchpad->hw_abs[i].tracking_id_changed) + touchpad->hw_abs[i].tracking_id_changed = false; + else if (is_valid_touch(touchpad, i, false)) { touch_state |= 1 << i; last_valid_touch = i; + if (mt_finger_state < TOUCHPAD_FINGERS_THREE) + mt_finger_state = mt_finger_state << 1; } + } + + if (touchpad->interaction_model == INTERACTION_MODEL_SONY) { + touchpad->finger_state = 0; + if (mt_finger_state != TOUCHPAD_FINGERS_NONE_YET) + touchpad->finger_state = mt_finger_state; + } if (touch_state && !touchpad->touch_state) { push_fsm_event(touchpad, FSM_EVENT_TOUCH); @@ -634,13 +662,81 @@ process_absolute(struct touchpad_dispatch *touchpad, } static inline void +process_absolute_sony(struct touchpad_dispatch *touchpad, + struct evdev_device *device, + struct input_event *e) +{ + int slot = touchpad->slot; + switch (e->code) { + case ABS_MT_SLOT: + slot = e->value; + if (slot < 0 || slot >= MAX_SLOTS) + slot = MAX_SLOTS; + touchpad->slot = slot; + break; + case ABS_MT_TRACKING_ID: + touchpad->hw_abs[slot].tracking_id_changed = true; + touchpad->hw_abs[slot].x_valid = false; + touchpad->hw_abs[slot].y_valid = false; + touchpad->hw_abs[slot].is_pressed = false; + touchpad->hw_abs[slot].is_moving = false; + break; + case ABS_MT_PRESSURE: + if (e->value > touchpad->pressure.touch_high && + !touchpad->hw_abs[slot].is_pressed) + on_touch(touchpad, slot); + else if (e->value < touchpad->pressure.touch_low && +touchpad->hw_abs[slot].is_pressed) + on_release(touchpad, slot); + break; + case ABS_MT_POSIT
[PATCH 6/8] evdev-touchpad: Made hw_abs an array
From: "Alexander E. Patrakov" In the non-multitouch case, the 0th entry tracks motion just as the old scalar hw_abs. In the multitouch case, there will be one entry for each slot, and relevant_touch is used to select which one is motion-tracked. --- src/evdev-touchpad.c | 146 +++ 1 file changed, 102 insertions(+), 44 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 1ed2dbb..01c52aa 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -51,6 +51,7 @@ enum touchpad_model { enum interaction_model { INTERACTION_MODEL_SIMPLE = 0, INTERACTION_MODEL_APPLE, + INTERACTION_MODEL_SONY, }; struct touchpad_model_spec { @@ -103,6 +104,8 @@ struct touchpad_dispatch { enum interaction_model interaction_model; int finger_state; int last_finger_state; + int slot; + int relevant_touch; double constant_accel_factor; double min_accel_factor; @@ -114,6 +117,7 @@ struct touchpad_dispatch { struct wl_event_source *timer_source; } fsm; + /* the extra dummy slot is used for out-of-range slots reported by mtdev */ struct { int32_t x; int32_t y; @@ -123,7 +127,7 @@ struct touchpad_dispatch { bool is_moving; bool is_pressed; - } hw_abs; + } hw_abs[MAX_SLOTS + 1]; bool has_moved; uint16_t touch_state; @@ -436,29 +440,80 @@ fsm_timout_handler(void *data) return 1; } +static bool +is_valid_touch(struct touchpad_dispatch *touchpad, int slot) +{ + if (!touchpad->hw_abs[slot].x_valid) + return false; + if (!touchpad->hw_abs[slot].y_valid) + return false; + if (!touchpad->hw_abs[slot].is_pressed) + return false; + return true; +} + static void touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) { + int i; int motion_index; int center_x, center_y; double dx = 0.0, dy = 0.0; /* For multitouch case, this will be a bitmask */ - uint16_t touch_state = touchpad->hw_abs.is_pressed; - if (touch_state && !touchpad->touch_state) + uint16_t touch_state = 0; + int last_valid_touch = -1; + int relevant_touch = touchpad->relevant_touch; + bool reset_motion = false; + + for (i = 0; i < MAX_SLOTS; i++) + if (is_valid_touch(touchpad, i)) { + touch_state |= 1 << i; + last_valid_touch = i; + } + + if (touch_state && !touchpad->touch_state) { push_fsm_event(touchpad, FSM_EVENT_TOUCH); + reset_motion = true; + } + if (!touch_state && touchpad->touch_state) { push_fsm_event(touchpad, FSM_EVENT_RELEASE); touchpad->has_moved = false; + reset_motion = true; } + if (touch_state && touchpad->touch_state && + !(touch_state & touchpad->touch_state)) { + push_fsm_event(touchpad, FSM_EVENT_RELEASE); + push_fsm_event(touchpad, FSM_EVENT_TOUCH); + touchpad->has_moved = false; + reset_motion = true; + } + + + if (relevant_touch != -1 && !(touch_state & (1 << relevant_touch))) { + reset_motion = true; + relevant_touch = -1; + } + if (relevant_touch == -1) + relevant_touch = last_valid_touch; + + if (touchpad->last_finger_state != touchpad->finger_state) + reset_motion = true; + touchpad->touch_state = touch_state; + touchpad->last_finger_state = touchpad->finger_state; + touchpad->relevant_touch = relevant_touch; - if (touchpad->last_finger_state != touchpad->finger_state) { + if (reset_motion) { touchpad->motion_count = 0; - touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; - touchpad->hw_abs.is_moving = false; + if (touchpad->interaction_model != INTERACTION_MODEL_SONY) { + touchpad->hw_abs[0].x_valid = false; + touchpad->hw_abs[0].y_valid = false; + touchpad->hw_abs[0].is_moving = false; + } touchpad->last_finger_state = touchpad->finger_state; @@ -466,37 +521,36 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) return; } - touchpad->last_finger_state = touchpad->finger_state; - if (!touchpad->hw_abs.x_valid || !touchpad->hw_abs.y_valid) + if (relevant_touch == -1) return; - if (!touchpad->hw_abs.is_moving) + if (!touchpad->hw_abs[relevant_touch].is_moving) return; /* Avoid noice by moving center only when delta reaches a threshold
[PATCH 5/8] evdev-touchpad: Introduced the notion of interaction model
From: "Alexander E. Patrakov" Different hardware can be interacted with differently. So far, there is some code for simple trackpads and for buttonpads. For buttonpads, currently the FSM is disabled and the right click is emulated through two-finger click. This is OK for Apple hardware, but not for Sony. A Sony-specific interaction model will be introduced later. --- src/evdev-touchpad.c | 47 ++- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index a9b21b8..1ed2dbb 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -45,7 +45,12 @@ enum touchpad_model { TOUCHPAD_MODEL_SYNAPTICS, TOUCHPAD_MODEL_ALPS, TOUCHPAD_MODEL_APPLETOUCH, - TOUCHPAD_MODEL_ELANTECH + TOUCHPAD_MODEL_ELANTECH, +}; + +enum interaction_model { + INTERACTION_MODEL_SIMPLE = 0, + INTERACTION_MODEL_APPLE, }; struct touchpad_model_spec { @@ -95,6 +100,7 @@ struct touchpad_dispatch { struct evdev_device *device; enum touchpad_model model; + enum interaction_model interaction_model; int finger_state; int last_finger_state; @@ -103,8 +109,6 @@ struct touchpad_dispatch { double max_accel_factor; struct { - bool enable; - struct wl_array events; enum fsm_state state; struct wl_event_source *timer_source; @@ -163,6 +167,28 @@ get_touchpad_model(struct evdev_device *device) } static void +configure_interaction_model(struct touchpad_dispatch *touchpad) +{ + unsigned long prop_bits[INPUT_PROP_MAX]; + + touchpad->interaction_model = INTERACTION_MODEL_SIMPLE; + + ioctl(touchpad->device->fd, EVIOCGPROP(sizeof(prop_bits)), prop_bits); + if (!TEST_BIT(prop_bits, INPUT_PROP_BUTTONPAD)) + return; + + switch (touchpad->model) { + case TOUCHPAD_MODEL_APPLETOUCH: + touchpad->interaction_model = INTERACTION_MODEL_APPLE; + break; + default: + weston_log("Found a buttonpad of unknown type, assuming Apple-style\n"); + touchpad->interaction_model = INTERACTION_MODEL_APPLE; + break; + } +} + +static void configure_touchpad_pressure(struct touchpad_dispatch *touchpad, int32_t pressure_min, int32_t pressure_max) { @@ -293,7 +319,7 @@ process_fsm_events(struct touchpad_dispatch *touchpad, uint32_t time) enum fsm_event *pevent; enum fsm_event event; - if (!touchpad->fsm.enable) + if (touchpad->interaction_model == INTERACTION_MODEL_APPLE) return; if (touchpad->fsm.events.size == 0) @@ -387,7 +413,7 @@ push_fsm_event(struct touchpad_dispatch *touchpad, { enum fsm_event *pevent; - if (!touchpad->fsm.enable) + if (touchpad->interaction_model == INTERACTION_MODEL_APPLE) return; pevent = wl_array_add(&touchpad->fsm.events, sizeof event); @@ -578,7 +604,8 @@ process_key(struct touchpad_dispatch *touchpad, case BTN_FORWARD: case BTN_BACK: case BTN_TASK: - if (!touchpad->fsm.enable && e->code == BTN_LEFT && + if (touchpad->interaction_model == INTERACTION_MODEL_APPLE && + e->code == BTN_LEFT && touchpad->finger_state == TOUCHPAD_FINGERS_TWO) code = BTN_RIGHT; else @@ -667,12 +694,9 @@ touchpad_init(struct touchpad_dispatch *touchpad, struct weston_motion_filter *accel; struct wl_event_loop *loop; - unsigned long prop_bits[INPUT_PROP_MAX]; struct input_absinfo absinfo; unsigned long abs_bits[NBITS(ABS_MAX)]; - bool has_buttonpad; - double width; double height; double diagonal; @@ -682,9 +706,7 @@ touchpad_init(struct touchpad_dispatch *touchpad, /* Detect model */ touchpad->model = get_touchpad_model(device); - - ioctl(device->fd, EVIOCGPROP(sizeof(prop_bits)), prop_bits); - has_buttonpad = TEST_BIT(prop_bits, INPUT_PROP_BUTTONPAD); + configure_interaction_model(touchpad); /* Configure pressure */ ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits); @@ -746,7 +768,6 @@ touchpad_init(struct touchpad_dispatch *touchpad, } /* Configure */ - touchpad->fsm.enable = !has_buttonpad; return 0; } -- 1.8.3.2 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 4/8] evdev-touchpad: Don't push FSM events from process_absolute
From: "Alexander E. Patrakov" In the multitouch case on Sony trackpads, not all touches are valid. However, the information needed to filter out invalid touches is consistent only on the SYN_REPORT event. --- src/evdev-touchpad.c | 23 --- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index aafa705..a9b21b8 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -122,6 +122,7 @@ struct touchpad_dispatch { } hw_abs; bool has_moved; + uint16_t touch_state; int has_pressure; struct { @@ -416,6 +417,18 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) int center_x, center_y; double dx = 0.0, dy = 0.0; + /* For multitouch case, this will be a bitmask */ + uint16_t touch_state = touchpad->hw_abs.is_pressed; + + if (touch_state && !touchpad->touch_state) + push_fsm_event(touchpad, FSM_EVENT_TOUCH); + if (!touch_state && touchpad->touch_state) { + push_fsm_event(touchpad, FSM_EVENT_RELEASE); + touchpad->has_moved = false; + } + + touchpad->touch_state = touch_state; + if (touchpad->last_finger_state != touchpad->finger_state) { touchpad->motion_count = 0; touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; @@ -498,19 +511,14 @@ static void on_touch(struct touchpad_dispatch *touchpad) { touchpad->hw_abs.is_pressed = true; - - push_fsm_event(touchpad, FSM_EVENT_TOUCH); } static void on_release(struct touchpad_dispatch *touchpad) { - - touchpad->has_moved = touchpad->hw_abs.is_pressed = false; - touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; + touchpad->hw_abs.is_pressed = false; touchpad->hw_abs.is_moving = false; - - push_fsm_event(touchpad, FSM_EVENT_RELEASE); + touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; } static inline void @@ -721,6 +729,7 @@ touchpad_init(struct touchpad_dispatch *touchpad, touchpad->hw_abs.is_pressed = false; touchpad->hw_abs.is_moving = false; touchpad->has_moved = false; + touchpad->touch_state = 0; touchpad->last_finger_state = 0; touchpad->finger_state = 0; -- 1.8.3.2 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 3/8] evdev-touchpad: Moved has_moved out of hw_abs
From: "Alexander E. Patrakov" For FSM purposes, it is a global property of a touchpad, not a property of each touch point. --- src/evdev-touchpad.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 6646896..aafa705 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -117,11 +117,12 @@ struct touchpad_dispatch { bool x_valid; bool y_valid; - bool has_moved; bool is_moving; bool is_pressed; } hw_abs; + bool has_moved; + int has_pressure; struct { int32_t touch_low; @@ -484,9 +485,9 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) } } - if (!touchpad->hw_abs.has_moved && + if (!touchpad->has_moved && ((int)dx || (int)dy)) { - touchpad->hw_abs.has_moved = true; + touchpad->has_moved = true; push_fsm_event(touchpad, FSM_EVENT_MOTION); } @@ -505,7 +506,7 @@ static void on_release(struct touchpad_dispatch *touchpad) { - touchpad->hw_abs.has_moved = touchpad->hw_abs.is_pressed = false; + touchpad->has_moved = touchpad->hw_abs.is_pressed = false; touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; touchpad->hw_abs.is_moving = false; @@ -719,7 +720,7 @@ touchpad_init(struct touchpad_dispatch *touchpad, touchpad->hw_abs.y_valid = false; touchpad->hw_abs.is_pressed = false; touchpad->hw_abs.is_moving = false; - touchpad->hw_abs.has_moved = false; + touchpad->has_moved = false; touchpad->last_finger_state = 0; touchpad->finger_state = 0; -- 1.8.3.2 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 2/8] evdev-touchpad: Split the reset logic
From: "Alexander E. Patrakov" In old code, the reset both cleared the (global) motion history and invalidated some state associated with (the) touch point. In the multitouch case, there is still the global motion history that may need to be cleared, and there are potentially many touch points that are certainly not appropriate to invalidate at once. So copy-paste the logic in order to be able to separate these two kinds of actions as needed. --- src/evdev-touchpad.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 35be921..6646896 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -102,8 +102,6 @@ struct touchpad_dispatch { double min_accel_factor; double max_accel_factor; - int reset; - struct { bool enable; @@ -417,13 +415,10 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) int center_x, center_y; double dx = 0.0, dy = 0.0; - if (touchpad->reset || - touchpad->last_finger_state != touchpad->finger_state) { - touchpad->reset = 0; + if (touchpad->last_finger_state != touchpad->finger_state) { touchpad->motion_count = 0; touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; touchpad->hw_abs.is_moving = false; - /* XXX what about is_pressed? */ touchpad->last_finger_state = touchpad->finger_state; @@ -511,7 +506,8 @@ on_release(struct touchpad_dispatch *touchpad) { touchpad->hw_abs.has_moved = touchpad->hw_abs.is_pressed = false; - touchpad->reset = 1; + touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; + touchpad->hw_abs.is_moving = false; push_fsm_event(touchpad, FSM_EVENT_RELEASE); } @@ -589,7 +585,11 @@ process_key(struct touchpad_dispatch *touchpad, case BTN_TOOL_AIRBRUSH: case BTN_TOOL_MOUSE: case BTN_TOOL_LENS: - touchpad->reset = 1; + /* The reset-logic below was copied without understanding +* and may be inappropriate */ + touchpad->motion_count = 0; + touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; + touchpad->hw_abs.is_moving = false; break; case BTN_TOOL_FINGER: if (e->value) @@ -711,8 +711,6 @@ touchpad_init(struct touchpad_dispatch *touchpad, touchpad->filter = accel; /* Setup initial state */ - touchpad->reset = 1; - memset(touchpad->motion_history, 0, sizeof touchpad->motion_history); touchpad->motion_index = 0; touchpad->motion_count = 0; -- 1.8.3.2 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 1/8] evdev-touchpad: Replaced flags with boolean variabes
From: "Alexander E. Patrakov" ...and put them inside hw_abs, because they will need to be made per-touch-point later. --- src/evdev-touchpad.c | 78 +--- 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 53300ce..35be921 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -48,14 +48,6 @@ enum touchpad_model { TOUCHPAD_MODEL_ELANTECH }; -enum touchpad_event { - TOUCHPAD_EVENT_NONE = 0, - TOUCHPAD_EVENT_ABSOLUTE_ANY = (1 << 0), - TOUCHPAD_EVENT_ABSOLUTE_X = (1 << 1), - TOUCHPAD_EVENT_ABSOLUTE_Y = (1 << 2), - TOUCHPAD_EVENT_REPORT = (1 << 3) -}; - struct touchpad_model_spec { short vendor; short product; @@ -70,12 +62,6 @@ static struct touchpad_model_spec touchpad_spec_table[] = { {0x, 0x, TOUCHPAD_MODEL_UNKNOWN} }; -enum touchpad_state { - TOUCHPAD_STATE_NONE = 0, - TOUCHPAD_STATE_TOUCH = (1 << 0), - TOUCHPAD_STATE_MOVE = (1 << 1) -}; - #define TOUCHPAD_HISTORY_LENGTH 4 struct touchpad_motion { @@ -109,7 +95,6 @@ struct touchpad_dispatch { struct evdev_device *device; enum touchpad_model model; - unsigned int state; int finger_state; int last_finger_state; @@ -117,9 +102,6 @@ struct touchpad_dispatch { double min_accel_factor; double max_accel_factor; - unsigned int event_mask; - unsigned int event_mask_filter; - int reset; struct { @@ -133,6 +115,13 @@ struct touchpad_dispatch { struct { int32_t x; int32_t y; + + bool x_valid; + bool y_valid; + + bool has_moved; + bool is_moving; + bool is_pressed; } hw_abs; int has_pressure; @@ -432,9 +421,9 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) touchpad->last_finger_state != touchpad->finger_state) { touchpad->reset = 0; touchpad->motion_count = 0; - touchpad->event_mask = TOUCHPAD_EVENT_NONE; - touchpad->event_mask_filter = - TOUCHPAD_EVENT_ABSOLUTE_X | TOUCHPAD_EVENT_ABSOLUTE_Y; + touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false; + touchpad->hw_abs.is_moving = false; + /* XXX what about is_pressed? */ touchpad->last_finger_state = touchpad->finger_state; @@ -444,18 +433,12 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) } touchpad->last_finger_state = touchpad->finger_state; - if (!(touchpad->event_mask & TOUCHPAD_EVENT_REPORT)) + if (!touchpad->hw_abs.x_valid || !touchpad->hw_abs.y_valid) return; - else - touchpad->event_mask &= ~TOUCHPAD_EVENT_REPORT; - if ((touchpad->event_mask & touchpad->event_mask_filter) != - touchpad->event_mask_filter) + if (!touchpad->hw_abs.is_moving) return; - touchpad->event_mask_filter = TOUCHPAD_EVENT_ABSOLUTE_ANY; - touchpad->event_mask = 0; - /* Avoid noice by moving center only when delta reaches a threshold * distance from the old center. */ if (touchpad->motion_count > 0) { @@ -506,9 +489,9 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) } } - if (!(touchpad->state & TOUCHPAD_STATE_MOVE) && + if (!touchpad->hw_abs.has_moved && ((int)dx || (int)dy)) { - touchpad->state |= TOUCHPAD_STATE_MOVE; + touchpad->hw_abs.has_moved = true; push_fsm_event(touchpad, FSM_EVENT_MOTION); } @@ -518,7 +501,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) static void on_touch(struct touchpad_dispatch *touchpad) { - touchpad->state |= TOUCHPAD_STATE_TOUCH; + touchpad->hw_abs.is_pressed = true; push_fsm_event(touchpad, FSM_EVENT_TOUCH); } @@ -527,8 +510,8 @@ static void on_release(struct touchpad_dispatch *touchpad) { + touchpad->hw_abs.has_moved = touchpad->hw_abs.is_pressed = false; touchpad->reset = 1; - touchpad->state &= ~(TOUCHPAD_STATE_MOVE | TOUCHPAD_STATE_TOUCH); push_fsm_event(touchpad, FSM_EVENT_RELEASE); } @@ -541,25 +524,25 @@ process_absolute(struct touchpad_dispatch *touchpad, switch (e->code) { case ABS_PRESSURE: if (e->value > touchpad->pressure.touch_high && - !(touchpad->state & TOUCHPAD_STATE_TOUCH)) + !touchpad->hw_abs.is_pressed) on_touch(touchpad); else if (e->value < touchpad->pressure.touch_low && -touchpad->state & TOUCHPAD_STATE_TOUCH) +
[RFC] weston: Sony clickpad support
This patch series adds support to weston for a special type of touchpads found in some laptops. These touchpads contain one physical button that covers the whole surface of the touchpad. Unlike the well-known Apple touchpad, these touchpads have markings painted on them, that designate virtual button areas. So the user interaction is quite different from one gets from Apple touchpads. +---+ |\/\/\/\/\/\/\/\/\/\/\/\/\/\| |/\/\/\/\/\/\/\/\/\/\/\/\/\/| |\/\/\/\/\/\/\/\/\/\/\/\/\/\| |/\ Cursor-moving area /\/| |\/\/\/\/\/\/\/\/\/\/\/\/\/\| |/\/\/\/\/\/\/\/\/\/\/\/\/\/| |\/\/\/\/\/\/\/\/\/\/\/\/\/\| +---+ <-- painted line | Left | Right | | virtual| virtual| | button | button | +-+-+ ^ | painted line E.g., currently, in order to get a right-click on such "clickpad", one has to click anywhere with two fingers. This is, however, inappropriate for touchpads I am talking about. See: one needs to drag something, he places a finger on the upper part of the touchpad surface (on the part of surface designated for moving the cursor), then places another finger into the left half of the button area, clicks with the intention to move the first finger. However, what he currently gets is a right-click. Also, if one wants to make a right click, he places his finger into the right half of the button area, clicks, but currently gets a left click. In other words, the touchpad is unusable for users that are accustomed to the way the interaction with the touchpad is done in Windows. I have implemented the interaction model that looks more like what one gets in Windows. In order to do so, I had to refactor the existing code a bit and add support for multitouch protocol to evdev-touchpad.c. Tested all of this on my Sony VAIO VPC-Z23A4R laptop. Here is what works: * Moving the cursor by moving the finger in the cursor-moving area of the touchpad. * Not moving the cursor if one moves the finger in the virtual button area. * Tap-to-click. * Tap-and-drag gesture (unreliable). * Left and right virtual buttons. * Dragging, as explaining above. * Insensitivity to bad clicks (those outside the designated button area). * Two-finger scrolling. ...i.e. the touchpad is now quite usable. Zoom gestures are not implemented, though. I have also added autodetection of the interaction model based on the laptops with clickpads that GUADEC participants brought with themselves. Result: the current interaction model is valid only for Apple and Chromebook Pixel laptops, for everyone else the alternative model in this patch is needed because there are buttons painted on the clickpad. -- Alexander E. Patrakov ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel