如何从C代码配置libinput设备?

时间:2019-06-25 04:01:01

标签: c linux configuration touchpad wayland

在Wayland上没有libinput的配置文件。这通常不是问题,因为桌面环境(例如Gnome)通常提供一种配置设备的方法。但是,无法为点击板设备启用中间点击仿真。默认情况下(使用按钮区域,以便我可以在触摸板的右下角单击鼠标右键),还会创建一个中间按钮区域。当我尝试单击鼠标左键和单击鼠标中键时,这通常会导致单击鼠标中键(导致粘贴内容)。如果启用了中间仿真,则可以禁用此中间单击区域,但是由于Gnome没有提供配置方法,因此我决定尝试构建自己的程序来实现此目的。

我浏览了libinput的API文档和示例(不幸的是,我似乎找不到任何设备配置示例)。以下代码是我编写的(与注释中的命令一起编译)。

/**
 * Simple program to setup libinput touchpad to use middle click emulation in wayland.
 *
 * To build install libinput-devel and libudev-devel
 * gcc -o middleemulation main.c `pkg-config --cflags --libs libinput libudev`
 * 
 * Copyright 2019 Marcus Behel
 *
 *Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <libudev.h>
#include <libinput.h>

static int open_restricted(const char *path, int flags, void *user_data){
  int fd = open(path, flags);
  return fd < 0 ? -errno : fd;
}

static void close_restricted(int fd, void *user_data){
  close(fd);
}

const static struct libinput_interface interface = {
        .open_restricted = open_restricted,
        .close_restricted = close_restricted,
};

int main(void){

  struct libinput *li;
  struct libinput_event *ev;
  struct udev *udev = udev_new();
  int dev_count = 0, tp_count = 0;

  li = libinput_udev_create_context(&interface, NULL, udev);
  libinput_udev_assign_seat(li, "seat0");
  libinput_dispatch(li);

  while ((ev = libinput_get_event(li))) {
    if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED){
      dev_count++;

      double w = 0, h = 0;
      struct libinput_device *dev = libinput_event_get_device(ev);
      const char *name = libinput_device_get_name(dev);
      if(libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_POINTER) &&
     libinput_device_get_size(dev, &w, &h) == 0){
    // Pointer with a size is a touchpad
    tp_count++;

    // This is a touchpad. Enable middle click emulation
    printf("Found touchpad: '%s'.\n", name);

    printf("Is middle click enabled: %s.\n", libinput_device_config_middle_emulation_get_enabled(dev) ? "true" : "false");

    if(libinput_device_config_middle_emulation_is_available(dev)){
      printf("Enabling middle emulation for device...");
      enum libinput_config_status err = libinput_device_config_middle_emulation_set_enabled(dev, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);

      if(err == LIBINPUT_CONFIG_STATUS_SUCCESS){
        printf("Succeeded.\n");
      }else{
        printf("Failed.\n");
      }

      printf("Is middle click enabled: %s.\n\n", libinput_device_config_middle_emulation_get_enabled(dev) ? "true" : "false");

    }else{
      printf("Device does not support middle emulation.\n\n");
    }
      }
    }

    libinput_event_destroy(ev);
    libinput_dispatch(li);
  }

  libinput_unref(li);

  if(dev_count == 0){
    fprintf(stderr, "No libinput devices were found. Run this as root and make sure libinput driver is enabled.\n");
    return 1;
  }

  if(tp_count == 0){
    printf("No touchpads found on this system.");
  }

  return 0;
}

我已经在Ubuntu 18.04(Dell Inspiron 5000)和Fedora 30(HP Pavilion 15)上对此进行了测试。在这两种情况下,该程序均指示成功,但是在运行libinput list-devices时,它仍显示中间仿真已禁用,并且行为没有改变。

程序输出(HP Pavilion)

Found touchpad: 'SynPS/2 Synaptics TouchPad'.
Is middle click enabled: false.
Enabling middle emulation for device...Succeeded.
Is middle click enabled: true.

运行程序后,libinput list-devices的输出

Device:           SynPS/2 Synaptics TouchPad
Kernel:           /dev/input/event4
Group:            9
Seat:             seat0, default
Size:             106x61mm
Capabilities:     pointer gesture
Tap-to-click:     disabled
Tap-and-drag:     enabled
Tap drag lock:    disabled
Left-handed:      disabled
Nat.scrolling:    disabled
Middle emulation: disabled
Calibration:      n/a
Scroll methods:   *two-finger edge 
Click methods:    *button-areas clickfinger 
Disable-w-typing: enabled
Accel profiles:   none
Rotation:         n/a

1 个答案:

答案 0 :(得分:0)

看起来这将需要预加载库才能按预期工作。这里的解决方案:https://github.com/gaul/libinput-force-middle-click-emulation 为我工作。