From 6e229ca26381bc8191fd9af1e439c311da709aff Mon Sep 17 00:00:00 2001 From: Eric Toombs <3672-ewtoombs@users.noreply.gitlab.freedesktop.org> Date: Thu, 31 Jan 2019 21:53:25 -0500 Subject: [PATCH] weston: add more libinput config options This is so that, for instance, people using weston as their main Wayland compositor can invert the sense of two finger scrolling or change pointer acceleration using weston.ini, rather than having to edit C code. All of the options that libinput itself exposes through its API are now exposed in weston.ini. The new options are called `tap-and-drag`, `tap-and-drag-lock`, `disable-while-typing`, `middle-emulation`, `left-handed`, `rotation`, `accel-profile`, `accel-speed`, `scroll-method`, `natural-scroll`, and `scroll-button`. I have successfully tested everything except for `rotation`, out of a lack of hardware support. weston now depends directly on libevdev for turning button name strings into kernel input codes. This was needed for the `scroll-button` config option. (weston already depends indirectly on libevdev through libinput, so I figured people would be OK with this.) As a practical matter for debian-style packagers, weston now has a build dependency on libevdev-dev. Right now, the code applies the same options to all attached devices that a given option is relevant for. There are plans for multiple [libinput] sections, each with different device filters, for users who need more control here. Signed-off-by: Eric Toombs <3672-ewtoombs@users.noreply.gitlab.freedesktop.org> --- .gitlab-ci.yml | 2 +- Makefile.am | 3 +- compositor/main.c | 176 ++++++++++++++++++++++++++++++++++++++++- compositor/meson.build | 1 + configure.ac | 1 + man/weston.ini.man | 74 ++++++++++++++++- meson.build | 1 + weston.ini.in | 13 +++ 8 files changed, 265 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c6007d1d..f4b56d48 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,7 +11,7 @@ before_script: - chmod +x /usr/sbin/policy-rc.d - echo 'deb http://deb.debian.org/debian stretch-backports main' >> /etc/apt/sources.list - apt-get update - - apt-get -y --no-install-recommends install build-essential automake autoconf libtool pkg-config libexpat1-dev libffi-dev libxml2-dev libpixman-1-dev libpng-dev libjpeg-dev libcolord-dev mesa-common-dev libglu1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libwayland-dev libxcb1-dev libxcb-composite0-dev libxcb-xfixes0-dev libxcb-xkb-dev libx11-xcb-dev libx11-dev libudev-dev libgbm-dev libxkbcommon-dev libcairo2-dev libpango1.0-dev libgdk-pixbuf2.0-dev libxcursor-dev libmtdev-dev libpam0g-dev libvpx-dev libsystemd-dev libinput-dev libwebp-dev libjpeg-dev libva-dev liblcms2-dev git libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev freerdp2-dev curl python3-pip python3-setuptools ninja-build + - apt-get -y --no-install-recommends install build-essential automake autoconf libtool pkg-config libexpat1-dev libffi-dev libxml2-dev libpixman-1-dev libpng-dev libjpeg-dev libcolord-dev mesa-common-dev libglu1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libwayland-dev libxcb1-dev libxcb-composite0-dev libxcb-xfixes0-dev libxcb-xkb-dev libx11-xcb-dev libx11-dev libudev-dev libgbm-dev libxkbcommon-dev libcairo2-dev libpango1.0-dev libgdk-pixbuf2.0-dev libxcursor-dev libmtdev-dev libpam0g-dev libvpx-dev libsystemd-dev libevdev-dev libinput-dev libwebp-dev libjpeg-dev libva-dev liblcms2-dev git libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev freerdp2-dev curl python3-pip python3-setuptools ninja-build - pip3 install --user git+https://github.com/mesonbuild/meson.git@0.49 - mkdir -p /tmp/.X11-unix - chmod 777 /tmp/.X11-unix diff --git a/Makefile.am b/Makefile.am index 6036dbf5..24561a58 100644 --- a/Makefile.am +++ b/Makefile.am @@ -187,12 +187,13 @@ weston_LDFLAGS = -export-dynamic weston_CPPFLAGS = $(AM_CPPFLAGS) -DMODULEDIR='"$(moduledir)"' \ -DXSERVER_PATH='"@XSERVER_PATH@"' weston_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) $(LIBINPUT_BACKEND_CFLAGS) \ - $(PTHREAD_CFLAGS) + $(PTHREAD_CFLAGS) $(LIBEVDEV_CFLAGS) weston_LDADD = libshared.la libweston-@LIBWESTON_MAJOR@.la \ $(COMPOSITOR_LIBS) \ $(DL_LIBS) $(LIBINPUT_BACKEND_LIBS) \ $(CLOCK_GETRES_LIBS) \ $(PTHREAD_LIBS) \ + $(LIBEVDEV_LIBS) \ -lm weston_SOURCES = \ diff --git a/compositor/main.c b/compositor/main.c index 6fdb6bae..34d2e715 100644 --- a/compositor/main.c +++ b/compositor/main.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include @@ -1458,6 +1460,114 @@ wet_set_simple_head_configurator(struct weston_compositor *compositor, &wet->heads_changed_listener); } +static void +configure_input_device_accel(struct weston_config_section *s, + struct libinput_device *device) +{ + char *profile_string = NULL; + int is_a_profile = 1; + uint32_t profiles; + enum libinput_config_accel_profile profile; + double speed; + + if (weston_config_section_get_string(s, "accel-profile", + &profile_string, NULL) == 0) { + if (strcmp(profile_string, "flat") == 0) + profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; + else if (strcmp(profile_string, "adaptive") == 0) + profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; + else { + weston_log("warning: no such accel-profile: %s\n", + profile_string); + is_a_profile = 0; + } + + profiles = libinput_device_config_accel_get_profiles(device); + if (is_a_profile && (profile & profiles) != 0) { + weston_log(" accel-profile=%s\n", + profile_string); + libinput_device_config_accel_set_profile(device, + profile); + } + } + + if (weston_config_section_get_double(s, "accel-speed", + &speed, 0) == 0 && + speed >= -1. && speed <= 1.) { + weston_log(" accel-speed=%.3f\n", speed); + libinput_device_config_accel_set_speed(device, speed); + } + + free(profile_string); +} + +static void +configure_input_device_scroll(struct weston_config_section *s, + struct libinput_device *device) +{ + int natural; + char *method_string = NULL; + uint32_t methods; + enum libinput_config_scroll_method method; + char *button_string = NULL; + int button; + + if (libinput_device_config_scroll_has_natural_scroll(device) && + weston_config_section_get_bool(s, "natural-scroll", + &natural, 0) == 0) { + weston_log(" natural-scroll=%s\n", + natural ? "true" : "false"); + libinput_device_config_scroll_set_natural_scroll_enabled( + device, natural); + } + + if (weston_config_section_get_string(s, "scroll-method", + &method_string, NULL) != 0) + goto done; + if (strcmp(method_string, "two-finger") == 0) + method = LIBINPUT_CONFIG_SCROLL_2FG; + else if (strcmp(method_string, "edge") == 0) + method = LIBINPUT_CONFIG_SCROLL_EDGE; + else if (strcmp(method_string, "button") == 0) + method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; + else if (strcmp(method_string, "none") == 0) + method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + else { + weston_log("warning: no such scroll-method: %s\n", + method_string); + goto done; + } + + methods = libinput_device_config_scroll_get_methods(device); + if (method != LIBINPUT_CONFIG_SCROLL_NO_SCROLL && + (method & methods) == 0) + goto done; + + weston_log(" scroll-method=%s\n", method_string); + libinput_device_config_scroll_set_method(device, method); + + if (method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) { + if (weston_config_section_get_string(s, "scroll-button", + &button_string, + NULL) != 0) + goto done; + + button = libevdev_event_code_from_name(EV_KEY, button_string); + if (button == -1) { + weston_log(" Bad scroll-button: %s\n", + button_string); + goto done; + } + + weston_log(" scroll-button=%s\n", button_string); + libinput_device_config_scroll_set_button(device, button); + } + +done: + free(method_string); + free(button_string); +} + static void configure_input_device(struct weston_compositor *compositor, struct libinput_device *device) @@ -1466,6 +1576,15 @@ configure_input_device(struct weston_compositor *compositor, struct weston_config *config = wet_get_config(compositor); int has_enable_tap = 0; int enable_tap; + int disable_while_typing; + int middle_emulation; + int tap_and_drag; + int tap_and_drag_lock; + int left_handed; + unsigned int rotation; + + weston_log("libinput: configuring device \"%s\".\n", + libinput_device_get_name(device)); s = weston_config_get_section(config, "libinput", NULL, NULL); @@ -1482,10 +1601,65 @@ configure_input_device(struct weston_compositor *compositor, if (weston_config_section_get_bool(s, "enable-tap", &enable_tap, 0) == 0) has_enable_tap = 1; - if (has_enable_tap) + if (has_enable_tap) { + weston_log(" enable-tap=%s.\n", + enable_tap ? "true" : "false"); libinput_device_config_tap_set_enabled(device, enable_tap); + } + if (weston_config_section_get_bool(s, "tap-and-drag", + &tap_and_drag, 0) == 0) { + weston_log(" tap-and-drag=%s.\n", + tap_and_drag ? "true" : "false"); + libinput_device_config_tap_set_drag_enabled(device, + tap_and_drag); + } + if (weston_config_section_get_bool(s, "tap-and-drag-lock", + &tap_and_drag_lock, 0) == 0) { + weston_log(" tap-and-drag-lock=%s.\n", + tap_and_drag_lock ? "true" : "false"); + libinput_device_config_tap_set_drag_lock_enabled( + device, tap_and_drag_lock); + } + } + + if (libinput_device_config_dwt_is_available(device) && + weston_config_section_get_bool(s, "disable-while-typing", + &disable_while_typing, 0) == 0) { + weston_log(" disable-while-typing=%s.\n", + disable_while_typing ? "true" : "false"); + libinput_device_config_dwt_set_enabled(device, + disable_while_typing); } + + if (libinput_device_config_middle_emulation_is_available(device) && + weston_config_section_get_bool(s, "middle-button-emulation", + &middle_emulation, 0) == 0) { + weston_log(" middle-button-emulation=%s\n", + middle_emulation ? "true" : "false"); + libinput_device_config_middle_emulation_set_enabled( + device, middle_emulation); + } + + if (libinput_device_config_left_handed_is_available(device) && + weston_config_section_get_bool(s, "left-handed", + &left_handed, 0) == 0) { + weston_log(" left-handed=%s\n", + left_handed ? "true" : "false"); + libinput_device_config_left_handed_set(device, left_handed); + } + + if (libinput_device_config_rotation_is_available(device) && + weston_config_section_get_uint(s, "rotation", + &rotation, 0) == 0) { + weston_log(" rotation=%u\n", rotation); + libinput_device_config_rotation_set_angle(device, rotation); + } + + if (libinput_device_config_accel_is_available(device)) + configure_input_device_accel(s, device); + + configure_input_device_scroll(s, device); } static int diff --git a/compositor/meson.build b/compositor/meson.build index 88bea8d8..994b5877 100644 --- a/compositor/meson.build +++ b/compositor/meson.build @@ -14,6 +14,7 @@ deps_weston = [ dep_libshared, dep_libweston, dep_libinput, + dep_libevdev, dep_libdl, dep_threads, ] diff --git a/configure.ac b/configure.ac index 225d6692..00066eae 100644 --- a/configure.ac +++ b/configure.ac @@ -235,6 +235,7 @@ if test x$enable_remoting = xyes; then fi +PKG_CHECK_MODULES(LIBEVDEV, [libevdev]) PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.8.0]) PKG_CHECK_MODULES(COMPOSITOR, [$COMPOSITOR_MODULES]) diff --git a/man/weston.ini.man b/man/weston.ini.man index dea80ca0..5c0f1097 100644 --- a/man/weston.ini.man +++ b/man/weston.ini.man @@ -212,12 +212,80 @@ There is also a command line option to do the same. The .B libinput section is used to configure input devices when using the libinput input device -backend. +backend. The defaults are determined by libinput and vary according to what is +most sensible for any given device. .PP Available configuration are: .TP 7 -.BI "enable-tap=" true -enables tap to click on touchpad devices +.BI "enable-tap=" false +Enables tap to click on touchpad devices. +.TP 7 +.BI "tap-and-drag=" false +For touchpad devices with \fBenable-tap\fR enabled. If the user taps, then +taps a second time, this time holding, the virtual mouse button stays down for +as long as the user keeps their finger on the touchpad, allowing the user to +click and drag with taps alone. +.TP 7 +.BI "tap-and-drag-lock=" false +For touchpad devices with \fBenable-tap\fR and \fBtap-and-drag\fR enabled. +In the middle of a tap-and-drag, if the user releases the touchpad for less +than a certain number of milliseconds, then touches it again, the virtual mouse +button will remain pressed and the drag can continue. +.TP 7 +.BI "disable-while-typing=" true +For devices that may be accidentally triggered while typing on the keyboard, +causing a disruption of the typing. Disables them while the keyboard is in +use. +.TP 7 +.BI "middle-button-emulation=" false +For pointer devices with left and right buttons, but no middle button. When +enabled, a middle button event is emitted when the left and right buttons are +pressed simultaneously. +.TP 7 +.BI "left-handed=" false +Configures the device for use by left-handed people. Exactly what this option +does depends on the device. For pointers with left and right buttons, the +buttons are swapped. On tablets, the tablet is logically turned upside down, +because it will be physically turned upside down. +.TP 7 +.BI "rotation=" n +Changes the direction of the logical north, rotating it \fIn\fR degrees +clockwise away from the default orientation, where \fIn\fR is a whole +number between 0 and 359 inclusive. Needed for trackballs, mainly. Allows the +user to orient the trackball sideways, for example. +.TP 7 +.BI "accel-profile=" "{flat,adaptive}" +Set the pointer acceleration profile. The pointer's screen speed is +proportional to the physical speed with a certain constant of proportionality. +Call that constant alpha. \fIflat\fR keeps alpha fixed. See \fBaccel-speed\fR. +\fIadaptive\fR causes alpha to increase with physical speed, giving the user +more control when the speed is slow, and more reach when the speed is high. +\fIadaptive\fR is the default. +.TP 7 +.BI "accel-speed=" v +If \fBaccel-profile\fR is set to \fIflat\fR, it simply sets the value of alpha. +If \fBaccel-profile\fR is set to \fIadaptive\fR, the effect is more +complicated, but generally speaking, it will change the pointer's speed. +\fIv\fR is normalised and must lie in the range [-1, 1]. The exact mapping +between \fIv\fR and alpha is hardware-dependent, but higher values cause higher +cursor speeds. +.TP 7 +.BI "natural-scroll=" false +Enables natural scrolling, mimicking the behaviour of touchscreen scrolling. +That is, if the wheel, finger, or fingers are moved down, the surface is +scrolled up instead of down, as if the finger, or fingers were in contact with +the surface being scrolled. +.TP 7 +.BI "scroll-method=" {two-finger,edge,button,none} +Sets the scroll method. \fItwo-finger\fR scrolls with two fingers on a +touchpad. \fIedge\fR scrolls with one finger on the right edge of a touchpad. +\fIbutton\fR scrolls when the pointer is moved while a certain button is +pressed. See \fBscroll-button\fR. \fInone\fR disables scrolling altogether. +.TP 7 +.BI "scroll-button=" {BTN_LEFT,BTN_RIGHT,BTN_MIDDLE,...} +For devices with \fBscroll-method\fR set to \fIbutton\fR. Specifies the +button that will trigger scrolling. See /usr/include/linux/input-event-codes.h +for the complete list of possible values. .TP 7 .BI "touchscreen_calibrator=" true Advertise the touchscreen calibrator interface to all clients. This is a diff --git a/meson.build b/meson.build index 7826dbb0..12fa7433 100644 --- a/meson.build +++ b/meson.build @@ -143,6 +143,7 @@ dep_wayland_server = dependency('wayland-server', version: '>= 1.12.0') dep_wayland_client = dependency('wayland-client', version: '>= 1.12.0') dep_pixman = dependency('pixman-1', version: '>= 0.25.2') dep_libinput = dependency('libinput', version: '>= 0.8.0') +dep_libevdev = dependency('libevdev') dep_libm = cc.find_library('m') dep_libdl = cc.find_library('dl') dep_libdrm = dependency('libdrm', version: '>= 2.4.68') diff --git a/weston.ini.in b/weston.ini.in index 1a9acee4..846ef746 100644 --- a/weston.ini.in +++ b/weston.ini.in @@ -61,6 +61,19 @@ path=@libexecdir@/weston-keyboard #[libinput] #enable-tap=true +#tap-and-drag=true +#tap-and-drag-lock=true +#disable-while-typing=false +#middle-button-emulation=true +#left-handed=true +#rotation=90 +#accel-profile=flat +#accel-speed=.9 +#natural-scroll=true +#scroll-method=edge +# For button-triggered scrolling: +#scroll-method=button +#scroll-button=BTN_RIGHT #[touchpad] #constant_accel_factor = 50