libinput
This commit is contained in:
parent
fe241126bb
commit
28081b7689
66
CMake/FindLibInput.cmake
Normal file
66
CMake/FindLibInput.cmake
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#.rst:
|
||||||
|
# FindLibInput
|
||||||
|
# -------
|
||||||
|
#
|
||||||
|
# Find LibInput library
|
||||||
|
#
|
||||||
|
# Try to find LibInpu library. The following values are defined
|
||||||
|
#
|
||||||
|
# ::
|
||||||
|
#
|
||||||
|
# LIBINPUT_FOUND - True if libinput is available
|
||||||
|
# LIBINPUT_INCLUDE_DIRS - Include directories for libinput
|
||||||
|
# LIBINPUT_LIBRARIES - List of libraries for libinput
|
||||||
|
# LIBINPUT_DEFINITIONS - List of definitions for libinput
|
||||||
|
#
|
||||||
|
# and also the following more fine grained variables
|
||||||
|
#
|
||||||
|
# ::
|
||||||
|
#
|
||||||
|
# LIBINPUT_VERSION
|
||||||
|
# LIBINPUT_VERSION_MAJOR
|
||||||
|
# LIBINPUT_VERSION_MINOR
|
||||||
|
# LIBINPUT_VERSION_MICRO
|
||||||
|
#
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright (c) 2015 Jari Vetoniemi
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
include(FeatureSummary)
|
||||||
|
set_package_properties(LibInput PROPERTIES
|
||||||
|
URL "http://freedesktop.org/wiki/Software/libinput/"
|
||||||
|
DESCRIPTION "Library to handle input devices")
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_INPUT QUIET libinput)
|
||||||
|
find_library(LIBINPUT_LIBRARIES NAMES input HINTS ${PC_INPUT_LIBRARY_DIRS})
|
||||||
|
find_path(LIBINPUT_INCLUDE_DIRS libinput.h HINTS ${PC_INPUT_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
set(LIBINPUT_VERSION ${PC_INPUT_VERSION})
|
||||||
|
string(REPLACE "." ";" VERSION_LIST "${PC_INPUT_VERSION}")
|
||||||
|
|
||||||
|
LIST(LENGTH VERSION_LIST n)
|
||||||
|
if (n EQUAL 3)
|
||||||
|
list(GET VERSION_LIST 0 LIBINPUT_VERSION_MAJOR)
|
||||||
|
list(GET VERSION_LIST 1 LIBINPUT_VERSION_MINOR)
|
||||||
|
list(GET VERSION_LIST 2 LIBINPUT_VERSION_MICRO)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# This is compatible with libinput-version.h that exists in upstream
|
||||||
|
# but isn't in distribution (probably forgotten)
|
||||||
|
set(LIBINPUT_DEFINITIONS ${PC_INPUT_CFLAGS_OTHER}
|
||||||
|
-DLIBINPUT_VERSION=\"${LIBINPUT_VERSION}\"
|
||||||
|
-DLIBINPUT_VERSION_MAJOR=${LIBINPUT_VERSION_MAJOR}
|
||||||
|
-DLIBINPUT_VERSION_MINOR=${LIBINPUT_VERSION_MINOR}
|
||||||
|
-DLIBINPUT_VERSION_MICRO=${LIBINPUT_VERSION_MICRO})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(LIBINPUT DEFAULT_MSG LIBINPUT_INCLUDE_DIRS LIBINPUT_LIBRARIES)
|
||||||
|
mark_as_advanced(LIBINPUT_INCLUDE_DIRS LIBINPUT_LIBRARIES LIBINPUT_DEFINITIONS
|
||||||
|
LIBINPUT_VERSION LIBINPUT_VERSION_MAJOR LIBINPUT_VERSION_MICRO LIBINPUT_VERSION_MINOR)
|
|
@ -57,6 +57,9 @@ find_package(Pango)
|
||||||
find_package(GdkPixbuf)
|
find_package(GdkPixbuf)
|
||||||
find_package(PAM)
|
find_package(PAM)
|
||||||
|
|
||||||
|
find_package(LibInput REQUIRED)
|
||||||
|
include_directories(${LIBINPUT_INClUDE_DIRS})
|
||||||
|
|
||||||
find_package(Backtrace)
|
find_package(Backtrace)
|
||||||
if(Backtrace_FOUND)
|
if(Backtrace_FOUND)
|
||||||
include_directories("${Backtrace_INCLUDE_DIRS}")
|
include_directories("${Backtrace_INCLUDE_DIRS}")
|
||||||
|
|
|
@ -17,7 +17,8 @@ enum cmd_status {
|
||||||
CMD_BLOCK_END,
|
CMD_BLOCK_END,
|
||||||
CMD_BLOCK_MODE,
|
CMD_BLOCK_MODE,
|
||||||
CMD_BLOCK_BAR,
|
CMD_BLOCK_BAR,
|
||||||
CMD_BLOCK_BAR_COLORS
|
CMD_BLOCK_BAR_COLORS,
|
||||||
|
CMD_BLOCK_INPUT
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#ifndef _SWAY_CONFIG_H
|
#ifndef _SWAY_CONFIG_H
|
||||||
#define _SWAY_CONFIG_H
|
#define _SWAY_CONFIG_H
|
||||||
|
|
||||||
|
#include <libinput.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <wlc/geometry.h>
|
||||||
#include <wlc/wlc.h>
|
#include <wlc/wlc.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include "wayland-desktop-shell-server-protocol.h"
|
#include "wayland-desktop-shell-server-protocol.h"
|
||||||
|
@ -45,6 +47,25 @@ struct sway_mode {
|
||||||
list_t *bindings;
|
list_t *bindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libinput options for input devices
|
||||||
|
*/
|
||||||
|
struct input_config {
|
||||||
|
char *identifier;
|
||||||
|
int click_method;
|
||||||
|
int drag_lock;
|
||||||
|
int dwt;
|
||||||
|
int middle_emulation;
|
||||||
|
int natural_scroll;
|
||||||
|
float pointer_accel;
|
||||||
|
int scroll_method;
|
||||||
|
int send_events;
|
||||||
|
int tap;
|
||||||
|
|
||||||
|
bool capturable;
|
||||||
|
struct wlc_geometry region;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size and position configuration for a particular output.
|
* Size and position configuration for a particular output.
|
||||||
*
|
*
|
||||||
|
@ -136,6 +157,7 @@ struct sway_config {
|
||||||
list_t *cmd_queue;
|
list_t *cmd_queue;
|
||||||
list_t *workspace_outputs;
|
list_t *workspace_outputs;
|
||||||
list_t *output_configs;
|
list_t *output_configs;
|
||||||
|
list_t *input_configs;
|
||||||
list_t *criteria;
|
list_t *criteria;
|
||||||
list_t *active_bar_modifiers;
|
list_t *active_bar_modifiers;
|
||||||
struct sway_mode *current_mode;
|
struct sway_mode *current_mode;
|
||||||
|
@ -172,6 +194,12 @@ bool read_config(FILE *file, bool is_active);
|
||||||
* Does variable replacement for a string based on the config's currently loaded variables.
|
* Does variable replacement for a string based on the config's currently loaded variables.
|
||||||
*/
|
*/
|
||||||
char *do_var_replacement(char *str);
|
char *do_var_replacement(char *str);
|
||||||
|
|
||||||
|
int input_identifier_cmp(const void *item, const void *data);
|
||||||
|
void merge_input_config(struct input_config *dst, struct input_config *src);
|
||||||
|
void apply_input_config(struct input_config *ic, struct libinput_device *dev);
|
||||||
|
void free_input_config(struct input_config *ic);
|
||||||
|
|
||||||
int output_name_cmp(const void *item, const void *data);
|
int output_name_cmp(const void *item, const void *data);
|
||||||
void merge_output_config(struct output_config *dst, struct output_config *src);
|
void merge_output_config(struct output_config *dst, struct output_config *src);
|
||||||
/** Sets up a WLC output handle based on a given output_config.
|
/** Sets up a WLC output handle based on a given output_config.
|
||||||
|
|
23
include/input.h
Normal file
23
include/input.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef _SWAY_INPUT_H
|
||||||
|
#define _SWAY_INPUT_H
|
||||||
|
|
||||||
|
#include <libinput.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
struct input_config *new_input_config(const char* identifier);
|
||||||
|
|
||||||
|
char* libinput_dev_unique_id(struct libinput_device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global input device list.
|
||||||
|
*/
|
||||||
|
extern list_t *input_devices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer used when reading input blocked.
|
||||||
|
* Shared so that it can be cleared from commands.c when closing the block
|
||||||
|
*/
|
||||||
|
extern struct input_config *current_input_config;
|
||||||
|
|
||||||
|
#endif
|
|
@ -5,11 +5,12 @@ enum ipc_command_type {
|
||||||
IPC_COMMAND = 0,
|
IPC_COMMAND = 0,
|
||||||
IPC_GET_WORKSPACES = 1,
|
IPC_GET_WORKSPACES = 1,
|
||||||
IPC_SUBSCRIBE = 2,
|
IPC_SUBSCRIBE = 2,
|
||||||
IPC_GET_OUTPUTS = 3,
|
IPC_GET_OUTPUTS = 3,
|
||||||
IPC_GET_TREE = 4,
|
IPC_GET_TREE = 4,
|
||||||
IPC_GET_MARKS = 5,
|
IPC_GET_MARKS = 5,
|
||||||
IPC_GET_BAR_CONFIG = 6,
|
IPC_GET_BAR_CONFIG = 6,
|
||||||
IPC_GET_VERSION = 7,
|
IPC_GET_VERSION = 7,
|
||||||
|
IPC_GET_INPUTS = 8,
|
||||||
// Events send from sway to clients. Events have the higest bit set.
|
// Events send from sway to clients. Events have the higest bit set.
|
||||||
IPC_EVENT_WORKSPACE = (1 << 31 | 0),
|
IPC_EVENT_WORKSPACE = (1 << 31 | 0),
|
||||||
IPC_EVENT_OUTPUT = (1 << 31 | 1),
|
IPC_EVENT_OUTPUT = (1 << 31 | 1),
|
||||||
|
@ -18,6 +19,7 @@ enum ipc_command_type {
|
||||||
IPC_EVENT_BARCONFIG_UPDATE = (1 << 31 | 4),
|
IPC_EVENT_BARCONFIG_UPDATE = (1 << 31 | 4),
|
||||||
IPC_EVENT_BINDING = (1 << 31 | 5),
|
IPC_EVENT_BINDING = (1 << 31 | 5),
|
||||||
IPC_EVENT_MODIFIER = (1 << 31 | 6),
|
IPC_EVENT_MODIFIER = (1 << 31 | 6),
|
||||||
|
IPC_EVENT_INPUT = (1 << 31 | 7),
|
||||||
IPC_SWAY_GET_PIXELS = 0x81
|
IPC_SWAY_GET_PIXELS = 0x81
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ include_directories(
|
||||||
${PCRE_INCLUDE_DIRS}
|
${PCRE_INCLUDE_DIRS}
|
||||||
${JSONC_INCLUDE_DIRS}
|
${JSONC_INCLUDE_DIRS}
|
||||||
${XKBCOMMON_INCLUDE_DIRS}
|
${XKBCOMMON_INCLUDE_DIRS}
|
||||||
|
${LIBINPUT_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(sway
|
add_executable(sway
|
||||||
|
@ -15,6 +16,7 @@ add_executable(sway
|
||||||
extensions.c
|
extensions.c
|
||||||
focus.c
|
focus.c
|
||||||
handlers.c
|
handlers.c
|
||||||
|
input.c
|
||||||
input_state.c
|
input_state.c
|
||||||
ipc-server.c
|
ipc-server.c
|
||||||
layout.c
|
layout.c
|
||||||
|
@ -32,6 +34,7 @@ target_link_libraries(sway
|
||||||
${PCRE_LIBRARIES}
|
${PCRE_LIBRARIES}
|
||||||
${JSONC_LIBRARIES}
|
${JSONC_LIBRARIES}
|
||||||
${WAYLAND_SERVER_LIBRARIES}
|
${WAYLAND_SERVER_LIBRARIES}
|
||||||
|
${LIBINPUT_LIBRARIES}
|
||||||
m
|
m
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
312
sway/commands.c
312
sway/commands.c
|
@ -11,6 +11,9 @@
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <libinput.h>
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
#include "focus.h"
|
#include "focus.h"
|
||||||
|
@ -26,6 +29,8 @@
|
||||||
#include "input_state.h"
|
#include "input_state.h"
|
||||||
#include "criteria.h"
|
#include "criteria.h"
|
||||||
#include "ipc-server.h"
|
#include "ipc-server.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
typedef struct cmd_results *sway_cmd(int argc, char **argv);
|
typedef struct cmd_results *sway_cmd(int argc, char **argv);
|
||||||
|
|
||||||
|
@ -49,6 +54,7 @@ static sway_cmd cmd_focus_follows_mouse;
|
||||||
static sway_cmd cmd_for_window;
|
static sway_cmd cmd_for_window;
|
||||||
static sway_cmd cmd_fullscreen;
|
static sway_cmd cmd_fullscreen;
|
||||||
static sway_cmd cmd_gaps;
|
static sway_cmd cmd_gaps;
|
||||||
|
static sway_cmd cmd_input;
|
||||||
static sway_cmd cmd_kill;
|
static sway_cmd cmd_kill;
|
||||||
static sway_cmd cmd_layout;
|
static sway_cmd cmd_layout;
|
||||||
static sway_cmd cmd_log_colors;
|
static sway_cmd cmd_log_colors;
|
||||||
|
@ -866,6 +872,293 @@ static struct cmd_results *cmd_orientation(int argc, char **argv) {
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void input_cmd_apply(struct input_config *input) {
|
||||||
|
int i;
|
||||||
|
i = list_seq_find(config->input_configs, input_identifier_cmp, input->identifier);
|
||||||
|
if (i >= 0) {
|
||||||
|
// merge existing config
|
||||||
|
struct input_config *ic = config->input_configs->items[i];
|
||||||
|
merge_input_config(ic, input);
|
||||||
|
free_input_config(input);
|
||||||
|
input = ic;
|
||||||
|
} else {
|
||||||
|
list_add(config->input_configs, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_input_config = input;
|
||||||
|
|
||||||
|
if (input->identifier) {
|
||||||
|
// Try to find the input device and apply configuration now. If
|
||||||
|
// this is during startup then there will be no container and config
|
||||||
|
// will be applied during normal "new input" event from wlc.
|
||||||
|
struct libinput_device *device = NULL;
|
||||||
|
for (int i = 0; i < input_devices->length; ++i) {
|
||||||
|
device = input_devices->items[i];
|
||||||
|
char* dev_identifier = libinput_dev_unique_id(device);
|
||||||
|
int match = dev_identifier && strcmp(dev_identifier, input->identifier) == 0;
|
||||||
|
free(dev_identifier);
|
||||||
|
if (match) {
|
||||||
|
apply_input_config(input, device);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_click_method(int argc, char **argv) {
|
||||||
|
sway_log(L_DEBUG, "click_method for device: %d %s", current_input_config==NULL, current_input_config->identifier);
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "click_method", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "click_method", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "none") == 0) {
|
||||||
|
new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||||
|
} else if (strcasecmp(argv[0], "button_areas") == 0) {
|
||||||
|
new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||||
|
} else if (strcasecmp(argv[0], "clickfinger") == 0) {
|
||||||
|
new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "click_method", "Expected 'click_method <none|button_areas|clickfinger'");
|
||||||
|
}
|
||||||
|
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_drag_lock(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "drag_lock", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "drag_lock", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "enabled") == 0) {
|
||||||
|
new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
|
||||||
|
} else if (strcasecmp(argv[0], "disabled") == 0) {
|
||||||
|
new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "drag_lock", "Expected 'drag_lock <enabled|disabled>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_dwt(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "dwt", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "dwt", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "enabled") == 0) {
|
||||||
|
new_config->dwt = LIBINPUT_CONFIG_DWT_ENABLED;
|
||||||
|
} else if (strcasecmp(argv[0], "disabled") == 0) {
|
||||||
|
new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "dwt", "Expected 'dwt <enabled|disabled>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_events(int argc, char **argv) {
|
||||||
|
sway_log(L_DEBUG, "events for device: %s", current_input_config->identifier);
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "events", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "enabled") == 0) {
|
||||||
|
new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||||
|
} else if (strcasecmp(argv[0], "disabled") == 0) {
|
||||||
|
new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||||
|
} else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) {
|
||||||
|
new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "events", "Expected 'events <enabled|disabled|disabled_on_external_mouse>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "middle_emulation", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "middle_emulation", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "enabled") == 0) {
|
||||||
|
new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED;
|
||||||
|
} else if (strcasecmp(argv[0], "disabled") == 0) {
|
||||||
|
new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "middle_emulation", "Expected 'middle_emulation <enabled|disabled>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "natural_scroll", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "natural_scoll", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "enabled") == 0) {
|
||||||
|
new_config->natural_scroll = 1;
|
||||||
|
} else if (strcasecmp(argv[0], "disabled") == 0) {
|
||||||
|
new_config->natural_scroll = 0;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "natural_scroll", "Expected 'natural_scroll <enabled|disabled>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "pointer_accel", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "pointer_accel", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
float pointer_accel = atof(argv[0]);
|
||||||
|
if (pointer_accel < -1 || pointer_accel > 1) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "pointer_accel", "Input out of range [-1, 1]");
|
||||||
|
}
|
||||||
|
new_config->pointer_accel = pointer_accel;
|
||||||
|
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_scroll_method(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "scroll_method", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "scroll_method", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "none") == 0) {
|
||||||
|
new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||||
|
} else if (strcasecmp(argv[0], "two_finger") == 0) {
|
||||||
|
new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
|
||||||
|
} else if (strcasecmp(argv[0], "edge") == 0) {
|
||||||
|
new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
|
||||||
|
} else if (strcasecmp(argv[0], "on_button_down") == 0) {
|
||||||
|
new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "scroll_method", "Expected 'scroll_method <none|two_finger|edge|on_button_down>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *input_cmd_tap(int argc, char **argv) {
|
||||||
|
sway_log(L_DEBUG, "tap for device: %s", current_input_config->identifier);
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "tap", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (!current_input_config) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "tap", "No input device defined.");
|
||||||
|
}
|
||||||
|
struct input_config *new_config = new_input_config(current_input_config->identifier);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "enabled") == 0) {
|
||||||
|
new_config->tap = LIBINPUT_CONFIG_TAP_ENABLED;
|
||||||
|
} else if (strcasecmp(argv[0], "disabled") == 0) {
|
||||||
|
new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "tap", "Expected 'tap <enabled|disabled>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_log(L_DEBUG, "apply-tap for device: %s", current_input_config->identifier);
|
||||||
|
input_cmd_apply(new_config);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *cmd_input(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->reading && strcmp("{", argv[1]) == 0) {
|
||||||
|
current_input_config = new_input_config(argv[0]);
|
||||||
|
sway_log(L_DEBUG, "entering input block: %s", current_input_config->identifier);
|
||||||
|
return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
int argc_new = argc-2;
|
||||||
|
char **argv_new = argv+2;
|
||||||
|
|
||||||
|
struct cmd_results *res;
|
||||||
|
current_input_config = new_input_config(argv[0]);
|
||||||
|
if (strcasecmp("click_method", argv[1]) == 0) {
|
||||||
|
res = input_cmd_click_method(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("drag_lock", argv[1]) == 0) {
|
||||||
|
res = input_cmd_drag_lock(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("dwt", argv[1]) == 0) {
|
||||||
|
res = input_cmd_dwt(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("events", argv[1]) == 0) {
|
||||||
|
res = input_cmd_events(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("middle_emulation", argv[1]) == 0) {
|
||||||
|
res = input_cmd_middle_emulation(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("natural_scroll", argv[1]) == 0) {
|
||||||
|
res = input_cmd_natural_scroll(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("pointer_accel", argv[1]) == 0) {
|
||||||
|
res = input_cmd_pointer_accel(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("scroll_method", argv[1]) == 0) {
|
||||||
|
res = input_cmd_scroll_method(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("tap", argv[1]) == 0) {
|
||||||
|
res = input_cmd_tap(argc_new, argv_new);
|
||||||
|
} else {
|
||||||
|
res = cmd_results_new(CMD_INVALID, "input <device>", "Unknonwn command %s", argv[1]);
|
||||||
|
}
|
||||||
|
current_input_config = NULL;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static struct cmd_results *cmd_output(int argc, char **argv) {
|
static struct cmd_results *cmd_output(int argc, char **argv) {
|
||||||
struct cmd_results *error = NULL;
|
struct cmd_results *error = NULL;
|
||||||
if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) {
|
if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
@ -1683,6 +1976,7 @@ static struct cmd_handler handlers[] = {
|
||||||
{ "for_window", cmd_for_window },
|
{ "for_window", cmd_for_window },
|
||||||
{ "fullscreen", cmd_fullscreen },
|
{ "fullscreen", cmd_fullscreen },
|
||||||
{ "gaps", cmd_gaps },
|
{ "gaps", cmd_gaps },
|
||||||
|
{ "input", cmd_input },
|
||||||
{ "kill", cmd_kill },
|
{ "kill", cmd_kill },
|
||||||
{ "layout", cmd_layout },
|
{ "layout", cmd_layout },
|
||||||
{ "log_colors", cmd_log_colors },
|
{ "log_colors", cmd_log_colors },
|
||||||
|
@ -2422,6 +2716,18 @@ static struct cmd_results *bar_colors_cmd_urgent_workspace(int argc, char **argv
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct cmd_handler input_handlers[] = {
|
||||||
|
{ "click_method", input_cmd_click_method },
|
||||||
|
{ "drag_lock", input_cmd_drag_lock },
|
||||||
|
{ "dwt", input_cmd_dwt },
|
||||||
|
{ "events", input_cmd_events },
|
||||||
|
{ "middle_emulation", input_cmd_middle_emulation },
|
||||||
|
{ "natural_scroll", input_cmd_natural_scroll },
|
||||||
|
{ "pointer_accel", input_cmd_pointer_accel },
|
||||||
|
{ "scroll_method", input_cmd_scroll_method },
|
||||||
|
{ "tap", input_cmd_tap },
|
||||||
|
};
|
||||||
|
|
||||||
static struct cmd_handler bar_colors_handlers[] = {
|
static struct cmd_handler bar_colors_handlers[] = {
|
||||||
{ "active_workspace", bar_colors_cmd_active_workspace },
|
{ "active_workspace", bar_colors_cmd_active_workspace },
|
||||||
{ "background", bar_colors_cmd_background },
|
{ "background", bar_colors_cmd_background },
|
||||||
|
@ -2442,6 +2748,7 @@ static int handler_compare(const void *_a, const void *_b) {
|
||||||
static struct cmd_handler *find_handler(char *line, enum cmd_status block) {
|
static struct cmd_handler *find_handler(char *line, enum cmd_status block) {
|
||||||
struct cmd_handler d = { .command=line };
|
struct cmd_handler d = { .command=line };
|
||||||
struct cmd_handler *res = NULL;
|
struct cmd_handler *res = NULL;
|
||||||
|
sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_INPUT);
|
||||||
if (block == CMD_BLOCK_BAR) {
|
if (block == CMD_BLOCK_BAR) {
|
||||||
res = bsearch(&d, bar_handlers,
|
res = bsearch(&d, bar_handlers,
|
||||||
sizeof(bar_handlers) / sizeof(struct cmd_handler),
|
sizeof(bar_handlers) / sizeof(struct cmd_handler),
|
||||||
|
@ -2450,6 +2757,11 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) {
|
||||||
res = bsearch(&d, bar_colors_handlers,
|
res = bsearch(&d, bar_colors_handlers,
|
||||||
sizeof(bar_colors_handlers) / sizeof(struct cmd_handler),
|
sizeof(bar_colors_handlers) / sizeof(struct cmd_handler),
|
||||||
sizeof(struct cmd_handler), handler_compare);
|
sizeof(struct cmd_handler), handler_compare);
|
||||||
|
} else if (block == CMD_BLOCK_INPUT) {
|
||||||
|
sway_log(L_DEBUG, "lookng at input handlers");
|
||||||
|
res = bsearch(&d, input_handlers,
|
||||||
|
sizeof(input_handlers) / sizeof(struct cmd_handler),
|
||||||
|
sizeof(struct cmd_handler), handler_compare);
|
||||||
} else {
|
} else {
|
||||||
res = bsearch(&d, handlers,
|
res = bsearch(&d, handlers,
|
||||||
sizeof(handlers) / sizeof(struct cmd_handler),
|
sizeof(handlers) / sizeof(struct cmd_handler),
|
||||||
|
|
116
sway/config.c
116
sway/config.c
|
@ -6,6 +6,9 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <libinput.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <float.h>
|
||||||
#include "wayland-desktop-shell-server-protocol.h"
|
#include "wayland-desktop-shell-server-protocol.h"
|
||||||
#include "readline.h"
|
#include "readline.h"
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
|
@ -16,6 +19,7 @@
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
#include "input_state.h"
|
#include "input_state.h"
|
||||||
#include "criteria.h"
|
#include "criteria.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
struct sway_config *config = NULL;
|
struct sway_config *config = NULL;
|
||||||
|
|
||||||
|
@ -59,6 +63,11 @@ static void free_bar(struct bar_config *bar) {
|
||||||
free(bar);
|
free(bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free_input_config(struct input_config *ic) {
|
||||||
|
free(ic->identifier);
|
||||||
|
free(ic);
|
||||||
|
}
|
||||||
|
|
||||||
void free_output_config(struct output_config *oc) {
|
void free_output_config(struct output_config *oc) {
|
||||||
free(oc->name);
|
free(oc->name);
|
||||||
free(oc);
|
free(oc);
|
||||||
|
@ -99,6 +108,11 @@ static void free_config(struct sway_config *config) {
|
||||||
}
|
}
|
||||||
list_free(config->criteria);
|
list_free(config->criteria);
|
||||||
|
|
||||||
|
for (i = 0; i < config->input_configs->length; ++i) {
|
||||||
|
free_input_config(config->input_configs->items[i]);
|
||||||
|
}
|
||||||
|
list_free(config->input_configs);
|
||||||
|
|
||||||
for (i = 0; i < config->output_configs->length; ++i) {
|
for (i = 0; i < config->output_configs->length; ++i) {
|
||||||
free_output_config(config->output_configs->items[i]);
|
free_output_config(config->output_configs->items[i]);
|
||||||
}
|
}
|
||||||
|
@ -119,6 +133,7 @@ static void config_defaults(struct sway_config *config) {
|
||||||
config->bars = create_list();
|
config->bars = create_list();
|
||||||
config->workspace_outputs = create_list();
|
config->workspace_outputs = create_list();
|
||||||
config->criteria = create_list();
|
config->criteria = create_list();
|
||||||
|
config->input_configs = create_list();
|
||||||
config->output_configs = create_list();
|
config->output_configs = create_list();
|
||||||
|
|
||||||
config->cmd_queue = create_list();
|
config->cmd_queue = create_list();
|
||||||
|
@ -294,6 +309,14 @@ bool read_config(FILE *file, bool is_active) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CMD_BLOCK_INPUT:
|
||||||
|
if (block == CMD_BLOCK_END) {
|
||||||
|
block = CMD_BLOCK_INPUT;
|
||||||
|
} else {
|
||||||
|
sway_log(L_ERROR, "Invalid block '%s'", line);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case CMD_BLOCK_BAR:
|
case CMD_BLOCK_BAR:
|
||||||
if (block == CMD_BLOCK_END) {
|
if (block == CMD_BLOCK_END) {
|
||||||
block = CMD_BLOCK_BAR;
|
block = CMD_BLOCK_BAR;
|
||||||
|
@ -318,6 +341,12 @@ bool read_config(FILE *file, bool is_active) {
|
||||||
block = CMD_BLOCK_END;
|
block = CMD_BLOCK_END;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CMD_BLOCK_INPUT:
|
||||||
|
sway_log(L_DEBUG, "End of input block");
|
||||||
|
current_input_config = NULL;
|
||||||
|
block = CMD_BLOCK_END;
|
||||||
|
break;
|
||||||
|
|
||||||
case CMD_BLOCK_BAR:
|
case CMD_BLOCK_BAR:
|
||||||
sway_log(L_DEBUG, "End of bar block");
|
sway_log(L_DEBUG, "End of bar block");
|
||||||
config->current_bar = NULL;
|
config->current_bar = NULL;
|
||||||
|
@ -353,6 +382,12 @@ bool read_config(FILE *file, bool is_active) {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int input_identifier_cmp(const void *item, const void *data) {
|
||||||
|
const struct input_config *ic = item;
|
||||||
|
const char *identifier = data;
|
||||||
|
return strcmp(ic->identifier, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
int output_name_cmp(const void *item, const void *data) {
|
int output_name_cmp(const void *item, const void *data) {
|
||||||
const struct output_config *output = item;
|
const struct output_config *output = item;
|
||||||
const char *name = data;
|
const char *name = data;
|
||||||
|
@ -360,6 +395,42 @@ int output_name_cmp(const void *item, const void *data) {
|
||||||
return strcmp(output->name, name);
|
return strcmp(output->name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void merge_input_config(struct input_config *dst, struct input_config *src) {
|
||||||
|
if (src->identifier) {
|
||||||
|
if (dst->identifier) {
|
||||||
|
free(dst->identifier);
|
||||||
|
}
|
||||||
|
dst->identifier = strdup(src->identifier);
|
||||||
|
}
|
||||||
|
if (src->click_method != INT_MIN) {
|
||||||
|
dst->click_method = src->click_method;
|
||||||
|
}
|
||||||
|
if (src->drag_lock != INT_MIN) {
|
||||||
|
dst->drag_lock = src->drag_lock;
|
||||||
|
}
|
||||||
|
if (src->dwt != INT_MIN) {
|
||||||
|
dst->dwt = src->dwt;
|
||||||
|
}
|
||||||
|
if (src->middle_emulation != INT_MIN) {
|
||||||
|
dst->middle_emulation = src->middle_emulation;
|
||||||
|
}
|
||||||
|
if (src->natural_scroll != INT_MIN) {
|
||||||
|
dst->natural_scroll = src->natural_scroll;
|
||||||
|
}
|
||||||
|
if (src->pointer_accel != FLT_MIN) {
|
||||||
|
dst->pointer_accel = src->pointer_accel;
|
||||||
|
}
|
||||||
|
if (src->scroll_method != INT_MIN) {
|
||||||
|
dst->scroll_method = src->scroll_method;
|
||||||
|
}
|
||||||
|
if (src->send_events != INT_MIN) {
|
||||||
|
dst->send_events = src->send_events;
|
||||||
|
}
|
||||||
|
if (src->tap != INT_MIN) {
|
||||||
|
dst->tap = src->tap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void merge_output_config(struct output_config *dst, struct output_config *src) {
|
void merge_output_config(struct output_config *dst, struct output_config *src) {
|
||||||
if (src->name) {
|
if (src->name) {
|
||||||
if (dst->name) {
|
if (dst->name) {
|
||||||
|
@ -508,6 +579,51 @@ void load_swaybars(swayc_t *output, int output_idx) {
|
||||||
list_free(bars);
|
list_free(bars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void apply_input_config(struct input_config *ic, struct libinput_device *dev) {
|
||||||
|
if (ic) {
|
||||||
|
sway_log(L_DEBUG,
|
||||||
|
"apply_input_config(%s)",
|
||||||
|
ic->identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ic && ic->click_method != INT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) click_set_method(%d)", ic->identifier, ic->click_method);
|
||||||
|
libinput_device_config_click_set_method(dev, ic->click_method);
|
||||||
|
}
|
||||||
|
if (ic && ic->drag_lock != INT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) tap_set_drag_lock_enabled(%d)", ic->identifier, ic->click_method);
|
||||||
|
libinput_device_config_tap_set_drag_lock_enabled(dev, ic->drag_lock);
|
||||||
|
}
|
||||||
|
if (ic && ic->dwt != INT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) dwt_set_enabled(%d)", ic->identifier, ic->dwt);
|
||||||
|
libinput_device_config_dwt_set_enabled(dev, ic->dwt);
|
||||||
|
}
|
||||||
|
if (ic && ic->middle_emulation != INT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) middle_emulation_set_enabled(%d)", ic->identifier, ic->middle_emulation);
|
||||||
|
libinput_device_config_middle_emulation_set_enabled(dev, ic->middle_emulation);
|
||||||
|
}
|
||||||
|
if (ic && ic->natural_scroll != INT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) natural_scroll_set_enabled(%d)", ic->identifier, ic->natural_scroll);
|
||||||
|
libinput_device_config_scroll_set_natural_scroll_enabled(dev, ic->natural_scroll);
|
||||||
|
}
|
||||||
|
if (ic && ic->pointer_accel != FLT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) accel_set_speed(%f)", ic->identifier, ic->pointer_accel);
|
||||||
|
libinput_device_config_accel_set_speed(dev, ic->pointer_accel);
|
||||||
|
}
|
||||||
|
if (ic && ic->scroll_method != INT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) scroll_set_method(%d)", ic->identifier, ic->scroll_method);
|
||||||
|
libinput_device_config_scroll_set_method(dev, ic->scroll_method);
|
||||||
|
}
|
||||||
|
if (ic && ic->send_events != INT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) send_events_set_mode(%d)", ic->identifier, ic->send_events);
|
||||||
|
libinput_device_config_send_events_set_mode(dev, ic->send_events);
|
||||||
|
}
|
||||||
|
if (ic && ic->tap != INT_MIN) {
|
||||||
|
sway_log(L_DEBUG, "apply_input_config(%s) tap_set_enabled(%d)", ic->identifier, ic->tap);
|
||||||
|
libinput_device_config_tap_set_enabled(dev, ic->tap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void apply_output_config(struct output_config *oc, swayc_t *output) {
|
void apply_output_config(struct output_config *oc, swayc_t *output) {
|
||||||
if (oc && oc->width > 0 && oc->height > 0) {
|
if (oc && oc->width > 0 && oc->height > 0) {
|
||||||
output->width = oc->width;
|
output->width = oc->width;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <libinput.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <wlc/wlc.h>
|
#include <wlc/wlc.h>
|
||||||
#include <wlc/wlc-wayland.h>
|
#include <wlc/wlc-wayland.h>
|
||||||
|
@ -21,6 +22,8 @@
|
||||||
#include "extensions.h"
|
#include "extensions.h"
|
||||||
#include "criteria.h"
|
#include "criteria.h"
|
||||||
#include "ipc-server.h"
|
#include "ipc-server.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
// Event should be sent to client
|
// Event should be sent to client
|
||||||
#define EVENT_PASSTHROUGH false
|
#define EVENT_PASSTHROUGH false
|
||||||
|
@ -30,6 +33,37 @@
|
||||||
|
|
||||||
/* Handles */
|
/* Handles */
|
||||||
|
|
||||||
|
static bool handle_input_created(struct libinput_device *device) {
|
||||||
|
const char *identifier = libinput_dev_unique_id(device);
|
||||||
|
sway_log(L_INFO, "Found input device (%s)", identifier);
|
||||||
|
|
||||||
|
list_add(input_devices, device);
|
||||||
|
|
||||||
|
struct input_config *ic = NULL;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < config->input_configs->length; ++i) {
|
||||||
|
struct input_config *cur = config->input_configs->items[i];
|
||||||
|
if (strcasecmp(identifier, cur->identifier) == 0) {
|
||||||
|
ic = cur;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_input_config(ic, device);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_input_destroyed(struct libinput_device *device) {
|
||||||
|
int i;
|
||||||
|
list_t *list = input_devices;
|
||||||
|
for (i = 0; i < list->length; ++i) {
|
||||||
|
if(((struct libinput_device *)list->items[i]) == device) {
|
||||||
|
list_del(list, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool handle_output_created(wlc_handle output) {
|
static bool handle_output_created(wlc_handle output) {
|
||||||
swayc_t *op = new_output(output);
|
swayc_t *op = new_output(output);
|
||||||
|
|
||||||
|
@ -660,5 +694,9 @@ struct wlc_interface interface = {
|
||||||
},
|
},
|
||||||
.compositor = {
|
.compositor = {
|
||||||
.ready = handle_wlc_ready
|
.ready = handle_wlc_ready
|
||||||
|
},
|
||||||
|
.input = {
|
||||||
|
.created = handle_input_created,
|
||||||
|
.destroyed = handle_input_destroyed
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
54
sway/input.c
Normal file
54
sway/input.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libinput.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
struct input_config *new_input_config(const char* identifier) {
|
||||||
|
struct input_config *input = calloc(1, sizeof(struct input_config));
|
||||||
|
sway_log(L_DEBUG, "new_input_config(%s)", identifier);
|
||||||
|
input->identifier = strdup(identifier);
|
||||||
|
|
||||||
|
input->tap = INT_MIN;
|
||||||
|
input->drag_lock = INT_MIN;
|
||||||
|
input->dwt = INT_MIN;
|
||||||
|
input->send_events = INT_MIN;
|
||||||
|
input->click_method = INT_MIN;
|
||||||
|
input->middle_emulation = INT_MIN;
|
||||||
|
input->natural_scroll = INT_MIN;
|
||||||
|
input->pointer_accel = FLT_MIN;
|
||||||
|
input->scroll_method = INT_MIN;
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *libinput_dev_unique_id(struct libinput_device *device) {
|
||||||
|
int vendor = libinput_device_get_id_vendor(device);
|
||||||
|
int product = libinput_device_get_id_product(device);
|
||||||
|
char *name = strdup(libinput_device_get_name(device));
|
||||||
|
|
||||||
|
char *p = name;
|
||||||
|
for (; *p; ++p) {
|
||||||
|
if (*p == ' ') {
|
||||||
|
*p = '_';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_log(L_DEBUG, "rewritten name %s", name);
|
||||||
|
|
||||||
|
int len = strlen(name) + sizeof(char) * 6;
|
||||||
|
char *identifier = malloc(len);
|
||||||
|
|
||||||
|
const char *fmt = "%d:%d:%s";
|
||||||
|
snprintf(identifier, len, fmt, vendor, product, name);
|
||||||
|
free(name);
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_t *input_devices = NULL;
|
||||||
|
struct input_config *current_input_config = NULL;
|
|
@ -13,6 +13,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <json-c/json.h>
|
#include <json-c/json.h>
|
||||||
#include <list.h>
|
#include <list.h>
|
||||||
|
#include <libinput.h>
|
||||||
#include "ipc-server.h"
|
#include "ipc-server.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
static int ipc_socket = -1;
|
static int ipc_socket = -1;
|
||||||
static struct wlc_event_source *ipc_event_source = NULL;
|
static struct wlc_event_source *ipc_event_source = NULL;
|
||||||
|
@ -325,6 +327,24 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
||||||
json_object_put(workspaces); // free
|
json_object_put(workspaces); // free
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IPC_GET_INPUTS:
|
||||||
|
{
|
||||||
|
json_object *inputs = json_object_new_array();
|
||||||
|
if (input_devices) {
|
||||||
|
for(int i=0; i<input_devices->length; i++) {
|
||||||
|
struct libinput_device *device = input_devices->items[i];
|
||||||
|
char* identifier = libinput_dev_unique_id(device);
|
||||||
|
json_object *device_object = json_object_new_object();
|
||||||
|
json_object_object_add(device_object, "identifier", json_object_new_string(identifier));
|
||||||
|
json_object_array_add(inputs, device_object);
|
||||||
|
free(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const char *json_string = json_object_to_json_string(inputs);
|
||||||
|
ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
|
||||||
|
json_object_put(inputs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case IPC_GET_OUTPUTS:
|
case IPC_GET_OUTPUTS:
|
||||||
{
|
{
|
||||||
json_object *outputs = json_object_new_array();
|
json_object *outputs = json_object_new_array();
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "ipc-client.h"
|
#include "ipc-client.h"
|
||||||
#include "ipc-server.h"
|
#include "ipc-server.h"
|
||||||
|
#include "input.h"
|
||||||
#include "sway.h"
|
#include "sway.h"
|
||||||
|
|
||||||
static bool terminate_request = false;
|
static bool terminate_request = false;
|
||||||
|
@ -173,6 +174,8 @@ int main(int argc, char **argv) {
|
||||||
wlc_log_set_handler(wlc_log_handler);
|
wlc_log_set_handler(wlc_log_handler);
|
||||||
detect_proprietary();
|
detect_proprietary();
|
||||||
|
|
||||||
|
input_devices = create_list();
|
||||||
|
|
||||||
/* Changing code earlier than this point requires detailed review */
|
/* Changing code earlier than this point requires detailed review */
|
||||||
/* (That code runs as root on systems without logind, and wlc_init drops to
|
/* (That code runs as root on systems without logind, and wlc_init drops to
|
||||||
* another user.) */
|
* another user.) */
|
||||||
|
@ -208,6 +211,10 @@ int main(int argc, char **argv) {
|
||||||
wlc_run();
|
wlc_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input_devices) {
|
||||||
|
free(input_devices);
|
||||||
|
}
|
||||||
|
|
||||||
ipc_terminate();
|
ipc_terminate();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
46
sway/sway-input.5.txt
Normal file
46
sway/sway-input.5.txt
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/////
|
||||||
|
vim:set ts=4 sw=4 tw=82 noet:
|
||||||
|
/////
|
||||||
|
sway (5)
|
||||||
|
========
|
||||||
|
|
||||||
|
Name
|
||||||
|
----
|
||||||
|
sway - input configuration file and commands
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Sway allows for configuration of libinput dveices.
|
||||||
|
|
||||||
|
|
||||||
|
Commands
|
||||||
|
--------
|
||||||
|
|
||||||
|
**input** <identifier> click_method <none|button_areas|clickfinger>:
|
||||||
|
Changes the click method for the specified device.
|
||||||
|
|
||||||
|
**input** <identifier> drag_lock <enabled|disabled>:
|
||||||
|
Enables or disables drag lock for specified input device.
|
||||||
|
|
||||||
|
**input** <identifier> dwt <enabled|disabled>:
|
||||||
|
Enables or disables disable-while-typing for the specified input device.
|
||||||
|
|
||||||
|
**input** <identifier> events <enable|disabled>:
|
||||||
|
Enables or disables send_events for specified input device.
|
||||||
|
(Disabling send_events disables the input device)
|
||||||
|
|
||||||
|
**input** <identifier> middle_emulation <enabled|disabled>:
|
||||||
|
Enables or disables middle click emulation.
|
||||||
|
|
||||||
|
**input** <identifier> natural_scroll <enabled|disabled>:
|
||||||
|
Enables or disables natural scrolling for the specified input device.
|
||||||
|
|
||||||
|
**input** <identifier> pointer_accel <[-1,1]>:
|
||||||
|
Changes the pointer acceleration for the specified input device.
|
||||||
|
|
||||||
|
**input** <identifier> scroll_method <none|two_finger|edge|on_button_down>:
|
||||||
|
Changes the scroll method for the specified input device.
|
||||||
|
|
||||||
|
**input** <identifier> tap <enabled|disabled>:
|
||||||
|
Enables or disables tap for specified input device.
|
|
@ -87,6 +87,8 @@ int main(int argc, char **argv) {
|
||||||
type = IPC_COMMAND;
|
type = IPC_COMMAND;
|
||||||
} else if (strcasecmp(cmdtype, "get_workspaces") == 0) {
|
} else if (strcasecmp(cmdtype, "get_workspaces") == 0) {
|
||||||
type = IPC_GET_WORKSPACES;
|
type = IPC_GET_WORKSPACES;
|
||||||
|
} else if (strcasecmp(cmdtype, "get_inputs") == 0) {
|
||||||
|
type = IPC_GET_INPUTS;
|
||||||
} else if (strcasecmp(cmdtype, "get_outputs") == 0) {
|
} else if (strcasecmp(cmdtype, "get_outputs") == 0) {
|
||||||
type = IPC_GET_OUTPUTS;
|
type = IPC_GET_OUTPUTS;
|
||||||
} else if (strcasecmp(cmdtype, "get_tree") == 0) {
|
} else if (strcasecmp(cmdtype, "get_tree") == 0) {
|
||||||
|
|
|
@ -43,6 +43,9 @@ IPC Message Types
|
||||||
*get_workspaces*::
|
*get_workspaces*::
|
||||||
Gets a JSON-encoded list of workspaces and their status.
|
Gets a JSON-encoded list of workspaces and their status.
|
||||||
|
|
||||||
|
*get_inputs*::
|
||||||
|
Gets a JSON-encoded list of current inputs.
|
||||||
|
|
||||||
*get_outputs*::
|
*get_outputs*::
|
||||||
Gets a JSON-encoded list of current outputs.
|
Gets a JSON-encoded list of current outputs.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue