From 733993a651c71f7e2198d505960d6bbd31e0e107 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 18 Nov 2017 11:22:02 -0500 Subject: Move everything to sway/old/ --- include/sway/config.h | 406 -------------------------------------------------- 1 file changed, 406 deletions(-) delete mode 100644 include/sway/config.h (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h deleted file mode 100644 index a05d5ede..00000000 --- a/include/sway/config.h +++ /dev/null @@ -1,406 +0,0 @@ -#ifndef _SWAY_CONFIG_H -#define _SWAY_CONFIG_H - -#define PID_WORKSPACE_TIMEOUT 60 - -#include -#include -#include -#include -#include -#include -#include "wayland-desktop-shell-server-protocol.h" -#include "list.h" -#include "layout.h" -#include "container.h" - -/** - * Describes a variable created via the `set` command. - */ -struct sway_variable { - char *name; - char *value; -}; - -/** - * A key binding and an associated command. - */ -struct sway_binding { - int order; - bool release; - bool bindcode; - list_t *keys; - uint32_t modifiers; - char *command; -}; - -/** - * A mouse binding and an associated command. - */ -struct sway_mouse_binding { - uint32_t button; - char *command; -}; - -/** - * A "mode" of keybindings created via the `mode` command. - */ -struct sway_mode { - char *name; - list_t *bindings; -}; - -/** - * libinput options for input devices - */ -struct input_config { - char *identifier; - - int accel_profile; - int click_method; - int drag_lock; - int dwt; - int left_handed; - 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. - * - * This is set via the `output` command. - */ -struct output_config { - char *name; - int enabled; - int width, height; - int x, y; - int scale; - char *background; - char *background_option; -}; - -/** - * Maps a workspace name to an output name. - * - * Set via `workspace output ` - */ -struct workspace_output { - char *output; - char *workspace; -}; - -struct pid_workspace { - pid_t *pid; - char *workspace; - time_t *time_added; -}; - -struct bar_config { - /** - * One of "dock", "hide", "invisible" - * - * Always visible in dock mode. Visible only when modifier key is held in hide mode. - * Never visible in invisible mode. - */ - char *mode; - /** - * One of "show" or "hide". - * - * In "show" mode, it will always be shown on top of the active workspace. - */ - char *hidden_state; - /** - * Id name used to identify the bar through IPC. - * - * Defaults to bar-x, where x corresponds to the position of the - * embedding bar block in the config file (bar-0, bar-1, ...). - */ - char *id; - uint32_t modifier; - list_t *outputs; - enum desktop_shell_panel_position position; - list_t *bindings; - char *status_command; - bool pango_markup; - char *swaybar_command; - char *font; - int height; // -1 not defined - -#ifdef ENABLE_TRAY - // Tray - char *tray_output; - char *icon_theme; - uint32_t tray_padding; - uint32_t activate_button; - uint32_t context_button; - uint32_t secondary_button; -#endif - - bool workspace_buttons; - bool wrap_scroll; - char *separator_symbol; - bool strip_workspace_numbers; - bool binding_mode_indicator; - bool verbose; - pid_t pid; - struct { - char *background; - char *statusline; - char *separator; - char *focused_background; - char *focused_statusline; - char *focused_separator; - char *focused_workspace_border; - char *focused_workspace_bg; - char *focused_workspace_text; - char *active_workspace_border; - char *active_workspace_bg; - char *active_workspace_text; - char *inactive_workspace_border; - char *inactive_workspace_bg; - char *inactive_workspace_text; - char *urgent_workspace_border; - char *urgent_workspace_bg; - char *urgent_workspace_text; - char *binding_mode_border; - char *binding_mode_bg; - char *binding_mode_text; - } colors; -}; - -struct border_colors { - uint32_t border; - uint32_t background; - uint32_t text; - uint32_t indicator; - uint32_t child_border; -}; - -enum edge_border_types { - E_NONE, /**< Don't hide edge borders */ - E_VERTICAL, /**< hide vertical edge borders */ - E_HORIZONTAL, /**< hide horizontal edge borders */ - E_BOTH, /**< hide vertical and horizontal edge borders */ - E_SMART /**< hide both if precisely one window is present in workspace */ -}; - -enum command_context { - CONTEXT_CONFIG = 1, - CONTEXT_BINDING = 2, - CONTEXT_IPC = 4, - CONTEXT_CRITERIA = 8, - CONTEXT_ALL = 0xFFFFFFFF, -}; - -struct command_policy { - char *command; - uint32_t context; -}; - -enum secure_feature { - FEATURE_LOCK = 1, - FEATURE_PANEL = 2, - FEATURE_BACKGROUND = 4, - FEATURE_SCREENSHOT = 8, - FEATURE_FULLSCREEN = 16, - FEATURE_KEYBOARD = 32, - FEATURE_MOUSE = 64, -}; - -struct feature_policy { - char *program; - uint32_t features; -}; - -enum ipc_feature { - IPC_FEATURE_COMMAND = 1, - IPC_FEATURE_GET_WORKSPACES = 2, - IPC_FEATURE_GET_OUTPUTS = 4, - IPC_FEATURE_GET_TREE = 8, - IPC_FEATURE_GET_MARKS = 16, - IPC_FEATURE_GET_BAR_CONFIG = 32, - IPC_FEATURE_GET_VERSION = 64, - IPC_FEATURE_GET_INPUTS = 128, - IPC_FEATURE_EVENT_WORKSPACE = 256, - IPC_FEATURE_EVENT_OUTPUT = 512, - IPC_FEATURE_EVENT_MODE = 1024, - IPC_FEATURE_EVENT_WINDOW = 2048, - IPC_FEATURE_EVENT_BINDING = 4096, - IPC_FEATURE_EVENT_INPUT = 8192, - IPC_FEATURE_GET_CLIPBOARD = 16384, - - IPC_FEATURE_ALL_COMMANDS = 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 16384, - IPC_FEATURE_ALL_EVENTS = 256 | 512 | 1024 | 2048 | 4096 | 8192, - - IPC_FEATURE_ALL = IPC_FEATURE_ALL_COMMANDS | IPC_FEATURE_ALL_EVENTS, -}; - -struct ipc_policy { - char *program; - uint32_t features; -}; - -/** - * The configuration struct. The result of loading a config file. - */ -struct sway_config { - list_t *symbols; - list_t *modes; - list_t *bars; - list_t *cmd_queue; - list_t *workspace_outputs; - list_t *pid_workspaces; - list_t *output_configs; - list_t *input_configs; - list_t *criteria; - list_t *no_focus; - list_t *active_bar_modifiers; - struct sway_mode *current_mode; - struct bar_config *current_bar; - uint32_t floating_mod; - uint32_t dragging_key; - uint32_t resizing_key; - char *floating_scroll_up_cmd; - char *floating_scroll_down_cmd; - char *floating_scroll_left_cmd; - char *floating_scroll_right_cmd; - enum swayc_layouts default_orientation; - enum swayc_layouts default_layout; - char *font; - int font_height; - - // Flags - bool focus_follows_mouse; - bool mouse_warping; - bool force_focus_wrapping; - bool active; - bool failed; - bool reloading; - bool reading; - bool auto_back_and_forth; - bool seamless_mouse; - bool show_marks; - - bool edge_gaps; - bool smart_gaps; - int gaps_inner; - int gaps_outer; - - list_t *config_chain; - const char *current_config; - - enum swayc_border_types border; - enum swayc_border_types floating_border; - int border_thickness; - int floating_border_thickness; - enum edge_border_types hide_edge_borders; - - // border colors - struct { - struct border_colors focused; - struct border_colors focused_inactive; - struct border_colors unfocused; - struct border_colors urgent; - struct border_colors placeholder; - uint32_t background; - } border_colors; - - // floating view - int32_t floating_maximum_width; - int32_t floating_maximum_height; - int32_t floating_minimum_width; - int32_t floating_minimum_height; - - // Security - list_t *command_policies; - list_t *feature_policies; - list_t *ipc_policies; -}; - -void pid_workspace_add(struct pid_workspace *pw); -void free_pid_workspace(struct pid_workspace *pw); - -/** - * Loads the main config from the given path. is_active should be true when - * reloading the config. - */ -bool load_main_config(const char *path, bool is_active); - -/** - * Loads an included config. Can only be used after load_main_config. - */ -bool load_include_configs(const char *path, struct sway_config *config); - -/** - * Reads the config from the given FILE. - */ -bool read_config(FILE *file, struct sway_config *config); - -/** - * Free config struct - */ -void free_config(struct sway_config *config); -/** - * Does variable replacement for a string based on the config's currently loaded variables. - */ -char *do_var_replacement(char *str); - -struct cmd_results *check_security_config(); - -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); -void merge_output_config(struct output_config *dst, struct output_config *src); -/** Sets up a WLC output handle based on a given output_config. - */ -void apply_output_config(struct output_config *oc, swayc_t *output); -void free_output_config(struct output_config *oc); - -/** - * Updates the list of active bar modifiers - */ -void update_active_bar_modifiers(void); - -int workspace_output_cmp_workspace(const void *a, const void *b); - -int sway_binding_cmp(const void *a, const void *b); -int sway_binding_cmp_qsort(const void *a, const void *b); -int sway_binding_cmp_keys(const void *a, const void *b); -void free_sway_binding(struct sway_binding *sb); -struct sway_binding *sway_binding_dup(struct sway_binding *sb); - -int sway_mouse_binding_cmp(const void *a, const void *b); -int sway_mouse_binding_cmp_qsort(const void *a, const void *b); -int sway_mouse_binding_cmp_buttons(const void *a, const void *b); -void free_sway_mouse_binding(struct sway_mouse_binding *smb); - -void load_swaybars(); -void terminate_swaybg(pid_t pid); - -/** - * Allocate and initialize default bar configuration. - */ -struct bar_config *default_bar_config(void); - -/** - * Global config singleton. - */ -extern struct sway_config *config; - -/** - * Config file currently being read. - */ -extern const char *current_config_path; - -#endif -- cgit v1.2.3 From 90f7f1a0e61fa20ed1b74b9df057aa70abc791ed Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 5 Dec 2017 10:40:55 +0100 Subject: Add minimal config subsystem --- include/sway/commands.h | 10 + include/sway/config.h | 405 +++++++++++++++++++++++++++++++++++ meson.build | 2 + sway/commands.c | 132 ++++++++++++ sway/commands/exec.c | 6 +- sway/commands/exec_always.c | 6 +- sway/commands/exit.c | 4 +- sway/config.c | 504 ++++++++++++++++++++++++++++++++++++++++++++ sway/main.c | 21 +- sway/meson.build | 2 + sway/security.c | 18 ++ 11 files changed, 1091 insertions(+), 19 deletions(-) create mode 100644 include/sway/config.h create mode 100644 sway/config.c create mode 100644 sway/security.c (limited to 'include/sway/config.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index df5c6859..b1f0423d 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -46,6 +46,16 @@ struct cmd_results *checkarg(int argc, const char *name, * Parse and handles a command. */ struct cmd_results *handle_command(char *command); +/** + * Parse and handles a command during config file loading. + * + * Do not use this under normal conditions. + */ +struct cmd_results *config_command(char *command, enum cmd_status block); +/* + * Parses a command policy rule. + */ +struct cmd_results *config_commands_command(char *exec); /** * Allocates a cmd_results object. */ diff --git a/include/sway/config.h b/include/sway/config.h new file mode 100644 index 00000000..56b4e637 --- /dev/null +++ b/include/sway/config.h @@ -0,0 +1,405 @@ +#ifndef _SWAY_CONFIG_H +#define _SWAY_CONFIG_H + +#define PID_WORKSPACE_TIMEOUT 60 + +#include +#include +#include +#include +#include +#include +#include "list.h" +#include "layout.h" +#include "container.h" + +/** + * Describes a variable created via the `set` command. + */ +struct sway_variable { + char *name; + char *value; +}; + +/** + * A key binding and an associated command. + */ +struct sway_binding { + int order; + bool release; + bool bindcode; + list_t *keys; + uint32_t modifiers; + char *command; +}; + +/** + * A mouse binding and an associated command. + */ +struct sway_mouse_binding { + uint32_t button; + char *command; +}; + +/** + * A "mode" of keybindings created via the `mode` command. + */ +struct sway_mode { + char *name; + list_t *bindings; +}; + +/** + * libinput options for input devices + */ +struct input_config { + char *identifier; + + int accel_profile; + int click_method; + int drag_lock; + int dwt; + int left_handed; + 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. + * + * This is set via the `output` command. + */ +struct output_config { + char *name; + int enabled; + int width, height; + int x, y; + int scale; + char *background; + char *background_option; +}; + +/** + * Maps a workspace name to an output name. + * + * Set via `workspace output ` + */ +struct workspace_output { + char *output; + char *workspace; +}; + +struct pid_workspace { + pid_t *pid; + char *workspace; + time_t *time_added; +}; + +struct bar_config { + /** + * One of "dock", "hide", "invisible" + * + * Always visible in dock mode. Visible only when modifier key is held in hide mode. + * Never visible in invisible mode. + */ + char *mode; + /** + * One of "show" or "hide". + * + * In "show" mode, it will always be shown on top of the active workspace. + */ + char *hidden_state; + /** + * Id name used to identify the bar through IPC. + * + * Defaults to bar-x, where x corresponds to the position of the + * embedding bar block in the config file (bar-0, bar-1, ...). + */ + char *id; + uint32_t modifier; + list_t *outputs; + //enum desktop_shell_panel_position position; // TODO + list_t *bindings; + char *status_command; + bool pango_markup; + char *swaybar_command; + char *font; + int height; // -1 not defined + +#ifdef ENABLE_TRAY + // Tray + char *tray_output; + char *icon_theme; + uint32_t tray_padding; + uint32_t activate_button; + uint32_t context_button; + uint32_t secondary_button; +#endif + + bool workspace_buttons; + bool wrap_scroll; + char *separator_symbol; + bool strip_workspace_numbers; + bool binding_mode_indicator; + bool verbose; + pid_t pid; + struct { + char *background; + char *statusline; + char *separator; + char *focused_background; + char *focused_statusline; + char *focused_separator; + char *focused_workspace_border; + char *focused_workspace_bg; + char *focused_workspace_text; + char *active_workspace_border; + char *active_workspace_bg; + char *active_workspace_text; + char *inactive_workspace_border; + char *inactive_workspace_bg; + char *inactive_workspace_text; + char *urgent_workspace_border; + char *urgent_workspace_bg; + char *urgent_workspace_text; + char *binding_mode_border; + char *binding_mode_bg; + char *binding_mode_text; + } colors; +}; + +struct border_colors { + uint32_t border; + uint32_t background; + uint32_t text; + uint32_t indicator; + uint32_t child_border; +}; + +enum edge_border_types { + E_NONE, /**< Don't hide edge borders */ + E_VERTICAL, /**< hide vertical edge borders */ + E_HORIZONTAL, /**< hide horizontal edge borders */ + E_BOTH, /**< hide vertical and horizontal edge borders */ + E_SMART /**< hide both if precisely one window is present in workspace */ +}; + +enum command_context { + CONTEXT_CONFIG = 1, + CONTEXT_BINDING = 2, + CONTEXT_IPC = 4, + CONTEXT_CRITERIA = 8, + CONTEXT_ALL = 0xFFFFFFFF, +}; + +struct command_policy { + char *command; + uint32_t context; +}; + +enum secure_feature { + FEATURE_LOCK = 1, + FEATURE_PANEL = 2, + FEATURE_BACKGROUND = 4, + FEATURE_SCREENSHOT = 8, + FEATURE_FULLSCREEN = 16, + FEATURE_KEYBOARD = 32, + FEATURE_MOUSE = 64, +}; + +struct feature_policy { + char *program; + uint32_t features; +}; + +enum ipc_feature { + IPC_FEATURE_COMMAND = 1, + IPC_FEATURE_GET_WORKSPACES = 2, + IPC_FEATURE_GET_OUTPUTS = 4, + IPC_FEATURE_GET_TREE = 8, + IPC_FEATURE_GET_MARKS = 16, + IPC_FEATURE_GET_BAR_CONFIG = 32, + IPC_FEATURE_GET_VERSION = 64, + IPC_FEATURE_GET_INPUTS = 128, + IPC_FEATURE_EVENT_WORKSPACE = 256, + IPC_FEATURE_EVENT_OUTPUT = 512, + IPC_FEATURE_EVENT_MODE = 1024, + IPC_FEATURE_EVENT_WINDOW = 2048, + IPC_FEATURE_EVENT_BINDING = 4096, + IPC_FEATURE_EVENT_INPUT = 8192, + IPC_FEATURE_GET_CLIPBOARD = 16384, + + IPC_FEATURE_ALL_COMMANDS = 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 16384, + IPC_FEATURE_ALL_EVENTS = 256 | 512 | 1024 | 2048 | 4096 | 8192, + + IPC_FEATURE_ALL = IPC_FEATURE_ALL_COMMANDS | IPC_FEATURE_ALL_EVENTS, +}; + +struct ipc_policy { + char *program; + uint32_t features; +}; + +/** + * The configuration struct. The result of loading a config file. + */ +struct sway_config { + list_t *symbols; + list_t *modes; + list_t *bars; + list_t *cmd_queue; + list_t *workspace_outputs; + list_t *pid_workspaces; + list_t *output_configs; + list_t *input_configs; + list_t *criteria; + list_t *no_focus; + list_t *active_bar_modifiers; + struct sway_mode *current_mode; + struct bar_config *current_bar; + uint32_t floating_mod; + uint32_t dragging_key; + uint32_t resizing_key; + char *floating_scroll_up_cmd; + char *floating_scroll_down_cmd; + char *floating_scroll_left_cmd; + char *floating_scroll_right_cmd; + enum swayc_layouts default_orientation; + enum swayc_layouts default_layout; + char *font; + int font_height; + + // Flags + bool focus_follows_mouse; + bool mouse_warping; + bool force_focus_wrapping; + bool active; + bool failed; + bool reloading; + bool reading; + bool auto_back_and_forth; + bool seamless_mouse; + bool show_marks; + + bool edge_gaps; + bool smart_gaps; + int gaps_inner; + int gaps_outer; + + list_t *config_chain; + const char *current_config; + + enum swayc_border_types border; + enum swayc_border_types floating_border; + int border_thickness; + int floating_border_thickness; + enum edge_border_types hide_edge_borders; + + // border colors + struct { + struct border_colors focused; + struct border_colors focused_inactive; + struct border_colors unfocused; + struct border_colors urgent; + struct border_colors placeholder; + uint32_t background; + } border_colors; + + // floating view + int32_t floating_maximum_width; + int32_t floating_maximum_height; + int32_t floating_minimum_width; + int32_t floating_minimum_height; + + // Security + list_t *command_policies; + list_t *feature_policies; + list_t *ipc_policies; +}; + +void pid_workspace_add(struct pid_workspace *pw); +void free_pid_workspace(struct pid_workspace *pw); + +/** + * Loads the main config from the given path. is_active should be true when + * reloading the config. + */ +bool load_main_config(const char *path, bool is_active); + +/** + * Loads an included config. Can only be used after load_main_config. + */ +bool load_include_configs(const char *path, struct sway_config *config); + +/** + * Reads the config from the given FILE. + */ +bool read_config(FILE *file, struct sway_config *config); + +/** + * Free config struct + */ +void free_config(struct sway_config *config); +/** + * Does variable replacement for a string based on the config's currently loaded variables. + */ +char *do_var_replacement(char *str); + +struct cmd_results *check_security_config(); + +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); +void merge_output_config(struct output_config *dst, struct output_config *src); +/** Sets up a WLC output handle based on a given output_config. + */ +void apply_output_config(struct output_config *oc, swayc_t *output); +void free_output_config(struct output_config *oc); + +/** + * Updates the list of active bar modifiers + */ +void update_active_bar_modifiers(void); + +int workspace_output_cmp_workspace(const void *a, const void *b); + +int sway_binding_cmp(const void *a, const void *b); +int sway_binding_cmp_qsort(const void *a, const void *b); +int sway_binding_cmp_keys(const void *a, const void *b); +void free_sway_binding(struct sway_binding *sb); +struct sway_binding *sway_binding_dup(struct sway_binding *sb); + +int sway_mouse_binding_cmp(const void *a, const void *b); +int sway_mouse_binding_cmp_qsort(const void *a, const void *b); +int sway_mouse_binding_cmp_buttons(const void *a, const void *b); +void free_sway_mouse_binding(struct sway_mouse_binding *smb); + +void load_swaybars(); +void terminate_swaybg(pid_t pid); + +/** + * Allocate and initialize default bar configuration. + */ +struct bar_config *default_bar_config(void); + +/** + * Global config singleton. + */ +extern struct sway_config *config; + +/** + * Config file currently being read. + */ +extern const char *current_config_path; + +#endif diff --git a/meson.build b/meson.build index 695e237e..8e7b98ed 100644 --- a/meson.build +++ b/meson.build @@ -65,6 +65,8 @@ if a2x.found() endforeach endif +add_project_arguments('-DSYSCONFDIR="/@0@"'.format(sysconfdir), language : 'c') + version = get_option('sway_version') if version != '' version = '"@0@"'.format(version) diff --git a/sway/commands.c b/sway/commands.c index 5fdcdbb6..17638129 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -7,6 +7,8 @@ #include #include #include "sway/commands.h" +#include "sway/config.h" +#include "sway/security.h" #include "stringop.h" #include "log.h" @@ -200,6 +202,136 @@ cleanup: return results; } +// this is like handle_command above, except: +// 1) it ignores empty commands (empty lines) +// 2) it does variable substitution +// 3) it doesn't split commands (because the multiple commands are supposed to +// be chained together) +// 4) handle_command handles all state internally while config_command has some +// state handled outside (notably the block mode, in read_config) +struct cmd_results *config_command(char *exec, enum cmd_status block) { + struct cmd_results *results = NULL; + int argc; + char **argv = split_args(exec, &argc); + if (!argc) { + results = cmd_results_new(CMD_SUCCESS, NULL, NULL); + goto cleanup; + } + + sway_log(L_INFO, "handling config command '%s'", exec); + // Endblock + if (**argv == '}') { + results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); + goto cleanup; + } + struct cmd_handler *handler = find_handler(argv[0], block); + if (!handler) { + char *input = argv[0] ? argv[0] : "(empty)"; + results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); + goto cleanup; + } + int i; + // Var replacement, for all but first argument of set + // TODO commands + for (i = /*handler->handle == cmd_set ? 2 :*/ 1; i < argc; ++i) { + argv[i] = do_var_replacement(argv[i]); + unescape_string(argv[i]); + } + /* Strip quotes for first argument. + * TODO This part needs to be handled much better */ + if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) { + strip_quotes(argv[1]); + } + if (handler->handle) { + results = handler->handle(argc-1, argv+1); + } else { + results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented"); + } + +cleanup: + free_argv(argc, argv); + return results; +} + +struct cmd_results *config_commands_command(char *exec) { + struct cmd_results *results = NULL; + int argc; + char **argv = split_args(exec, &argc); + if (!argc) { + results = cmd_results_new(CMD_SUCCESS, NULL, NULL); + goto cleanup; + } + + // Find handler for the command this is setting a policy for + char *cmd = argv[0]; + + if (strcmp(cmd, "}") == 0) { + results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); + goto cleanup; + } + + struct cmd_handler *handler = find_handler(cmd, CMD_BLOCK_END); + if (!handler && strcmp(cmd, "*") != 0) { + char *input = cmd ? cmd : "(empty)"; + results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); + goto cleanup; + } + + enum command_context context = 0; + + struct { + char *name; + enum command_context context; + } context_names[] = { + { "config", CONTEXT_CONFIG }, + { "binding", CONTEXT_BINDING }, + { "ipc", CONTEXT_IPC }, + { "criteria", CONTEXT_CRITERIA }, + { "all", CONTEXT_ALL }, + }; + + for (int i = 1; i < argc; ++i) { + size_t j; + for (j = 0; j < sizeof(context_names) / sizeof(context_names[0]); ++j) { + if (strcmp(context_names[j].name, argv[i]) == 0) { + break; + } + } + if (j == sizeof(context_names) / sizeof(context_names[0])) { + results = cmd_results_new(CMD_INVALID, cmd, + "Invalid command context %s", argv[i]); + goto cleanup; + } + context |= context_names[j].context; + } + + struct command_policy *policy = NULL; + for (int i = 0; i < config->command_policies->length; ++i) { + struct command_policy *p = config->command_policies->items[i]; + if (strcmp(p->command, cmd) == 0) { + policy = p; + break; + } + } + if (!policy) { + policy = alloc_command_policy(cmd); + sway_assert(policy, "Unable to allocate security policy"); + if (policy) { + list_add(config->command_policies, policy); + } + } + policy->context = context; + + sway_log(L_INFO, "Set command policy for %s to %d", + policy->command, policy->context); + + results = cmd_results_new(CMD_SUCCESS, NULL, NULL); + +cleanup: + free_argv(argc, argv); + return results; +} + struct cmd_results *cmd_results_new(enum cmd_status status, const char *input, const char *format, ...) { struct cmd_results *results = malloc(sizeof(struct cmd_results)); diff --git a/sway/commands/exec.c b/sway/commands/exec.c index dd71500a..fbbc4941 100644 --- a/sway/commands/exec.c +++ b/sway/commands/exec.c @@ -1,16 +1,16 @@ #include #include "sway/commands.h" +#include "sway/config.h" #include "log.h" #include "stringop.h" struct cmd_results *cmd_exec(int argc, char **argv) { - // TODO: config - /*if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL); + if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL); if (config->reloading) { char *args = join_args(argv, argc); sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); free(args); return cmd_results_new(CMD_SUCCESS, NULL, NULL); - }*/ + } return cmd_exec_always(argc, argv); } diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 0a252e7b..9527a487 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -5,15 +5,15 @@ #include #include #include "sway/commands.h" -#include "sway/workspace.h" +#include "sway/config.h" #include "sway/container.h" +#include "sway/workspace.h" #include "log.h" #include "stringop.h" struct cmd_results *cmd_exec_always(int argc, char **argv) { struct cmd_results *error = NULL; - // TODO: config - //if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); + if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); if ((error = checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0))) { return error; } diff --git a/sway/commands/exit.c b/sway/commands/exit.c index d294e344..4bb6a97b 100644 --- a/sway/commands/exit.c +++ b/sway/commands/exit.c @@ -1,19 +1,17 @@ #include #include "sway/commands.h" +#include "sway/config.h" void sway_terminate(int exit_code); struct cmd_results *cmd_exit(int argc, char **argv) { struct cmd_results *error = NULL; - /* TODO if (config->reading) { return cmd_results_new(CMD_FAILURE, "exit", "Can't be used in config file."); } - */ if ((error = checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0))) { return error; } sway_terminate(0); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } - diff --git a/sway/config.c b/sway/config.c new file mode 100644 index 00000000..475e8b04 --- /dev/null +++ b/sway/config.c @@ -0,0 +1,504 @@ +#define _POSIX_C_SOURCE 200809L +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#elif __FreeBSD__ +#include +#endif +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/layout.h" +#include "readline.h" +#include "stringop.h" +#include "list.h" +#include "log.h" + +struct sway_config *config = NULL; + +void free_config(struct sway_config *config) { + // TODO +} + +static void config_defaults(struct sway_config *config) { + if (!(config->symbols = create_list())) goto cleanup; + if (!(config->modes = create_list())) goto cleanup; + if (!(config->bars = create_list())) goto cleanup; + if (!(config->workspace_outputs = create_list())) goto cleanup; + if (!(config->pid_workspaces = create_list())) goto cleanup; + if (!(config->criteria = create_list())) goto cleanup; + if (!(config->no_focus = create_list())) goto cleanup; + if (!(config->input_configs = create_list())) goto cleanup; + if (!(config->output_configs = create_list())) goto cleanup; + + if (!(config->cmd_queue = create_list())) goto cleanup; + + if (!(config->current_mode = malloc(sizeof(struct sway_mode)))) goto cleanup; + if (!(config->current_mode->name = malloc(sizeof("default")))) goto cleanup; + strcpy(config->current_mode->name, "default"); + if (!(config->current_mode->bindings = create_list())) goto cleanup; + list_add(config->modes, config->current_mode); + + config->floating_mod = 0; + config->dragging_key = BTN_LEFT; + config->resizing_key = BTN_RIGHT; + if (!(config->floating_scroll_up_cmd = strdup(""))) goto cleanup; + if (!(config->floating_scroll_down_cmd = strdup(""))) goto cleanup; + if (!(config->floating_scroll_left_cmd = strdup(""))) goto cleanup; + if (!(config->floating_scroll_right_cmd = strdup(""))) goto cleanup; + config->default_layout = L_NONE; + config->default_orientation = L_NONE; + if (!(config->font = strdup("monospace 10"))) goto cleanup; + // TODO: border + //config->font_height = get_font_text_height(config->font); + + // floating view + config->floating_maximum_width = 0; + config->floating_maximum_height = 0; + config->floating_minimum_width = 75; + config->floating_minimum_height = 50; + + // Flags + config->focus_follows_mouse = true; + config->mouse_warping = true; + config->reloading = false; + config->active = false; + config->failed = false; + config->auto_back_and_forth = false; + config->seamless_mouse = true; + config->reading = false; + config->show_marks = true; + + config->edge_gaps = true; + config->smart_gaps = false; + config->gaps_inner = 0; + config->gaps_outer = 0; + + if (!(config->active_bar_modifiers = create_list())) goto cleanup; + + if (!(config->config_chain = create_list())) goto cleanup; + config->current_config = NULL; + + // borders + config->border = B_NORMAL; + config->floating_border = B_NORMAL; + config->border_thickness = 2; + config->floating_border_thickness = 2; + config->hide_edge_borders = E_NONE; + + // border colors + config->border_colors.focused.border = 0x4C7899FF; + config->border_colors.focused.background = 0x285577FF; + config->border_colors.focused.text = 0xFFFFFFFF; + config->border_colors.focused.indicator = 0x2E9EF4FF; + config->border_colors.focused.child_border = 0x285577FF; + + config->border_colors.focused_inactive.border = 0x333333FF; + config->border_colors.focused_inactive.background = 0x5F676AFF; + config->border_colors.focused_inactive.text = 0xFFFFFFFF; + config->border_colors.focused_inactive.indicator = 0x484E50FF; + config->border_colors.focused_inactive.child_border = 0x5F676AFF; + + config->border_colors.unfocused.border = 0x333333FF; + config->border_colors.unfocused.background = 0x222222FF; + config->border_colors.unfocused.text = 0x888888FF; + config->border_colors.unfocused.indicator = 0x292D2EFF; + config->border_colors.unfocused.child_border = 0x222222FF; + + config->border_colors.urgent.border = 0x2F343AFF; + config->border_colors.urgent.background = 0x900000FF; + config->border_colors.urgent.text = 0xFFFFFFFF; + config->border_colors.urgent.indicator = 0x900000FF; + config->border_colors.urgent.child_border = 0x900000FF; + + config->border_colors.placeholder.border = 0x000000FF; + config->border_colors.placeholder.background = 0x0C0C0CFF; + config->border_colors.placeholder.text = 0xFFFFFFFF; + config->border_colors.placeholder.indicator = 0x000000FF; + config->border_colors.placeholder.child_border = 0x0C0C0CFF; + + config->border_colors.background = 0xFFFFFFFF; + + // Security + if (!(config->command_policies = create_list())) goto cleanup; + if (!(config->feature_policies = create_list())) goto cleanup; + if (!(config->ipc_policies = create_list())) goto cleanup; + + return; +cleanup: + sway_abort("Unable to allocate config structures"); +} + +static bool file_exists(const char *path) { + return path && access(path, R_OK) != -1; +} + +static char *get_config_path(void) { + static const char *config_paths[] = { + "$HOME/.sway/config", + "$XDG_CONFIG_HOME/sway/config", + "$HOME/.i3/config", + "$XDG_CONFIG_HOME/i3/config", + SYSCONFDIR "/sway/config", + SYSCONFDIR "/i3/config", + }; + + if (!getenv("XDG_CONFIG_HOME")) { + char *home = getenv("HOME"); + char *config_home = malloc(strlen(home) + strlen("/.config") + 1); + if (!config_home) { + sway_log(L_ERROR, "Unable to allocate $HOME/.config"); + } else { + strcpy(config_home, home); + strcat(config_home, "/.config"); + setenv("XDG_CONFIG_HOME", config_home, 1); + sway_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); + free(config_home); + } + } + + wordexp_t p; + char *path; + + int i; + for (i = 0; i < (int)(sizeof(config_paths) / sizeof(char *)); ++i) { + if (wordexp(config_paths[i], &p, 0) == 0) { + path = strdup(p.we_wordv[0]); + wordfree(&p); + if (file_exists(path)) { + return path; + } + } + } + + return NULL; // Not reached +} + +const char *current_config_path; + +static bool load_config(const char *path, struct sway_config *config) { + sway_log(L_INFO, "Loading config from %s", path); + current_config_path = path; + + struct stat sb; + if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { + return false; + } + + if (path == NULL) { + sway_log(L_ERROR, "Unable to find a config file!"); + return false; + } + + FILE *f = fopen(path, "r"); + if (!f) { + sway_log(L_ERROR, "Unable to open %s for reading", path); + return false; + } + + bool config_load_success = read_config(f, config); + fclose(f); + + if (!config_load_success) { + sway_log(L_ERROR, "Error(s) loading config!"); + } + + current_config_path = NULL; + return true; +} + +static int qstrcmp(const void* a, const void* b) { + return strcmp(*((char**) a), *((char**) b)); +} + +bool load_main_config(const char *file, bool is_active) { + char *path; + if (file != NULL) { + path = strdup(file); + } else { + path = get_config_path(); + } + + struct sway_config *old_config = config; + config = calloc(1, sizeof(struct sway_config)); + if (!config) { + sway_abort("Unable to allocate config"); + } + + config_defaults(config); + if (is_active) { + sway_log(L_DEBUG, "Performing configuration file reload"); + config->reloading = true; + config->active = true; + } + + config->current_config = path; + list_add(config->config_chain, path); + + config->reading = true; + + // Read security configs + bool success = true; + DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); + if (!dir) { + sway_log(L_ERROR, "%s does not exist, sway will have no security configuration" + " and will probably be broken", SYSCONFDIR "/sway/security.d"); + } else { + list_t *secconfigs = create_list(); + char *base = SYSCONFDIR "/sway/security.d/"; + struct dirent *ent = readdir(dir); + struct stat s; + while (ent != NULL) { + char *_path = malloc(strlen(ent->d_name) + strlen(base) + 1); + strcpy(_path, base); + strcat(_path, ent->d_name); + lstat(_path, &s); + if (S_ISREG(s.st_mode) && ent->d_name[0] != '.') { + list_add(secconfigs, _path); + } + else { + free(_path); + } + ent = readdir(dir); + } + closedir(dir); + + list_qsort(secconfigs, qstrcmp); + for (int i = 0; i < secconfigs->length; ++i) { + char *_path = secconfigs->items[i]; + if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && (s.st_mode & 0777) != 0444)) { + sway_log(L_ERROR, "Refusing to load %s - it must be owned by root and mode 644 or 444", _path); + success = false; + } else { + success = success && load_config(_path, config); + } + } + + free_flat_list(secconfigs); + } + + success = success && load_config(path, config); + + if (is_active) { + config->reloading = false; + } + + if (old_config) { + free_config(old_config); + } + config->reading = false; + + if (success) { + // TODO: bar + //update_active_bar_modifiers(); + } + + return success; +} + +bool read_config(FILE *file, struct sway_config *config) { + bool success = true; + enum cmd_status block = CMD_BLOCK_END; + + int line_number = 0; + char *line; + while (!feof(file)) { + line = read_line(file); + if (!line) { + continue; + } + line_number++; + line = strip_whitespace(line); + if (line[0] == '#') { + free(line); + continue; + } + struct cmd_results *res; + if (block == CMD_BLOCK_COMMANDS) { + // Special case + res = config_commands_command(line); + } else { + res = config_command(line, block); + } + switch(res->status) { + case CMD_FAILURE: + case CMD_INVALID: + sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, line, + res->error, config->current_config); + success = false; + break; + + case CMD_DEFER: + sway_log(L_DEBUG, "Defferring command `%s'", line); + list_add(config->cmd_queue, strdup(line)); + break; + + case CMD_BLOCK_MODE: + if (block == CMD_BLOCK_END) { + block = CMD_BLOCK_MODE; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + 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: + if (block == CMD_BLOCK_END) { + block = CMD_BLOCK_BAR; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + + case CMD_BLOCK_BAR_COLORS: + if (block == CMD_BLOCK_BAR) { + block = CMD_BLOCK_BAR_COLORS; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + + case CMD_BLOCK_COMMANDS: + if (block == CMD_BLOCK_END) { + block = CMD_BLOCK_COMMANDS; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + + case CMD_BLOCK_IPC: + if (block == CMD_BLOCK_END) { + block = CMD_BLOCK_IPC; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + + case CMD_BLOCK_IPC_EVENTS: + if (block == CMD_BLOCK_IPC) { + block = CMD_BLOCK_IPC_EVENTS; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + + case CMD_BLOCK_END: + switch(block) { + case CMD_BLOCK_MODE: + sway_log(L_DEBUG, "End of mode block"); + config->current_mode = config->modes->items[0]; + block = CMD_BLOCK_END; + break; + + case CMD_BLOCK_INPUT: + sway_log(L_DEBUG, "End of input block"); + // TODO: input + //current_input_config = NULL; + block = CMD_BLOCK_END; + break; + + case CMD_BLOCK_BAR: + sway_log(L_DEBUG, "End of bar block"); + config->current_bar = NULL; + block = CMD_BLOCK_END; + break; + + case CMD_BLOCK_BAR_COLORS: + sway_log(L_DEBUG, "End of bar colors block"); + block = CMD_BLOCK_BAR; + break; + + case CMD_BLOCK_COMMANDS: + sway_log(L_DEBUG, "End of commands block"); + block = CMD_BLOCK_END; + break; + + case CMD_BLOCK_IPC: + sway_log(L_DEBUG, "End of IPC block"); + block = CMD_BLOCK_END; + break; + + case CMD_BLOCK_IPC_EVENTS: + sway_log(L_DEBUG, "End of IPC events block"); + block = CMD_BLOCK_IPC; + break; + + case CMD_BLOCK_END: + sway_log(L_ERROR, "Unmatched }"); + break; + + default:; + } + default:; + } + free(line); + free_cmd_results(res); + } + + return success; +} + +char *do_var_replacement(char *str) { + int i; + char *find = str; + while ((find = strchr(find, '$'))) { + // Skip if escaped. + if (find > str && find[-1] == '\\') { + if (find == str + 1 || !(find > str + 1 && find[-2] == '\\')) { + ++find; + continue; + } + } + // Find matching variable + for (i = 0; i < config->symbols->length; ++i) { + struct sway_variable *var = config->symbols->items[i]; + int vnlen = strlen(var->name); + if (strncmp(find, var->name, vnlen) == 0) { + int vvlen = strlen(var->value); + char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); + if (!newstr) { + sway_log(L_ERROR, + "Unable to allocate replacement during variable expansion"); + break; + } + char *newptr = newstr; + int offset = find - str; + strncpy(newptr, str, offset); + newptr += offset; + strncpy(newptr, var->value, vvlen); + newptr += vvlen; + strcpy(newptr, find + vnlen); + free(str); + str = newstr; + find = str + offset + vvlen; + break; + } + } + if (i == config->symbols->length) { + ++find; + } + } + return str; +} diff --git a/sway/main.c b/sway/main.c index bc107309..bc843591 100644 --- a/sway/main.c +++ b/sway/main.c @@ -15,6 +15,7 @@ #include #include #endif +#include "sway/config.h" #include "sway/server.h" #include "sway/layout.h" #include "sway/ipc-server.h" @@ -388,14 +389,14 @@ int main(int argc, char **argv) { ipc_init(&server); log_env(); - //if (validate) { - // bool valid = load_main_config(config_path, false); - // return valid ? 0 : 1; - //} + if (validate) { + bool valid = load_main_config(config_path, false); + return valid ? 0 : 1; + } - //if (!load_main_config(config_path, false)) { - // sway_terminate(EXIT_FAILURE); - //} + if (!load_main_config(config_path, false)) { + sway_terminate(EXIT_FAILURE); + } if (config_path) { free(config_path); @@ -411,9 +412,9 @@ int main(int argc, char **argv) { ipc_terminate(); - //if (config) { - // free_config(config); - //} + if (config) { + free_config(config); + } return exit_value; } diff --git a/sway/meson.build b/sway/meson.build index b224f15f..84f48137 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -5,12 +5,14 @@ sway_sources = files( 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', + 'config.c', 'ipc-json.c', 'ipc-server.c', 'desktop/output.c', 'desktop/wl_shell.c', 'desktop/xdg_shell_v6.c', 'desktop/xwayland.c', + 'security.c', 'tree/container.c', 'tree/layout.c', 'tree/workspace.c', diff --git a/sway/security.c b/sway/security.c new file mode 100644 index 00000000..cc0d3f66 --- /dev/null +++ b/sway/security.c @@ -0,0 +1,18 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include "sway/security.h" + +struct command_policy *alloc_command_policy(const char *command) { + struct command_policy *policy = malloc(sizeof(struct command_policy)); + if (!policy) { + return NULL; + } + policy->command = strdup(command); + if (!policy->command) { + free(policy); + return NULL; + } + policy->context = 0; + return policy; +} -- cgit v1.2.3 From 7e81d304a3121e92f78527dcf1327e991b0089ac Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 5 Dec 2017 18:21:48 +0100 Subject: Remove wlc includes --- include/sway/config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 56b4e637..7de85ab7 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -5,8 +5,8 @@ #include #include -#include -#include +#include +#include #include #include #include "list.h" @@ -68,7 +68,7 @@ struct input_config { int tap; bool capturable; - struct wlc_geometry region; + struct wlr_box region; }; /** -- cgit v1.2.3 From aaae59026ff3751190b93277ac6d7566e373c892 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 6 Dec 2017 12:36:06 +0100 Subject: Add output config --- include/sway/config.h | 4 + include/sway/container.h | 1 + sway/commands.c | 1 + sway/commands/output.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++ sway/config/output.c | 166 +++++++++++++++++++++++++++++++ sway/main.c | 4 + sway/meson.build | 2 + sway/tree/container.c | 83 +++++++++++++++- 8 files changed, 512 insertions(+), 2 deletions(-) create mode 100644 sway/commands/output.c create mode 100644 sway/config/output.c (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 7de85ab7..1b49c5c9 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -80,8 +81,11 @@ struct output_config { char *name; int enabled; int width, height; + float refresh_rate; int x, y; int scale; + enum wl_output_transform transform; + char *background; char *background_option; }; diff --git a/include/sway/container.h b/include/sway/container.h index 08a98ed9..e3f84fc6 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -132,6 +132,7 @@ swayc_t *new_output(struct sway_output *sway_output); swayc_t *new_workspace(swayc_t *output, const char *name); swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view); +swayc_t *destroy_output(swayc_t *output); swayc_t *destroy_view(swayc_t *view); swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); diff --git a/sway/commands.c b/sway/commands.c index 17638129..961cb867 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -95,6 +95,7 @@ static struct cmd_handler handlers[] = { { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, { "exit", cmd_exit }, + { "output", cmd_output }, }; static int handler_compare(const void *_a, const void *_b) { diff --git a/sway/commands/output.c b/sway/commands/output.c new file mode 100644 index 00000000..c964bef7 --- /dev/null +++ b/sway/commands/output.c @@ -0,0 +1,253 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "list.h" +#include "log.h" +#include "stringop.h" + +static char *bg_options[] = { + "stretch", + "center", + "fill", + "fit", + "tile", +}; + +struct cmd_results *cmd_output(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) { + return error; + } + const char *name = argv[0]; + + struct output_config *output = calloc(1, sizeof(struct output_config)); + if (!output) { + return cmd_results_new(CMD_FAILURE, "output", "Unable to allocate output config"); + } + output->x = output->y = output->width = output->height = -1; + output->name = strdup(name); + output->enabled = -1; + output->scale = 1; + + // TODO: atoi doesn't handle invalid numbers + + int i; + for (i = 1; i < argc; ++i) { + const char *command = argv[i]; + + if (strcasecmp(command, "disable") == 0) { + output->enabled = 0; + } else if (strcasecmp(command, "resolution") == 0 || strcasecmp(command, "res") == 0) { + if (++i >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing resolution argument."); + goto fail; + } + char *res = argv[i]; + char *x = strchr(res, 'x'); + int width = -1, height = -1; + if (x != NULL) { + // Format is 1234x4321 + *x = '\0'; + width = atoi(res); + height = atoi(x + 1); + *x = 'x'; + } else { + // Format is 1234 4321 + width = atoi(res); + if (++i >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing resolution argument (height)."); + goto fail; + } + res = argv[i]; + height = atoi(res); + } + output->width = width; + output->height = height; + } else if (strcasecmp(command, "refresh_rate") == 0) { + if (++i >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing refresh_rate argument."); + goto fail; + } + output->refresh_rate = atof(argv[i]); + } else if (strcasecmp(command, "position") == 0 || strcasecmp(command, "pos") == 0) { + if (++i >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing position argument."); + goto fail; + } + char *res = argv[i]; + char *c = strchr(res, ','); + int x = -1, y = -1; + if (c != NULL) { + // Format is 1234,4321 + *c = '\0'; + x = atoi(res); + y = atoi(c + 1); + *c = ','; + } else { + // Format is 1234 4321 + x = atoi(res); + if (++i >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing position argument (y)."); + goto fail; + } + res = argv[i]; + y = atoi(res); + } + output->x = x; + output->y = y; + } else if (strcasecmp(command, "scale") == 0) { + if (++i >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing scale parameter."); + goto fail; + } + output->scale = atoi(argv[i]); + } else if (strcasecmp(command, "transform") == 0) { + if (++i >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing transform parameter."); + goto fail; + } + char *value = argv[i]; + if (strcmp(value, "normal") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + } else if (strcmp(value, "90") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_90; + } else if (strcmp(value, "180") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_180; + } else if (strcmp(value, "270") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_270; + } else if (strcmp(value, "flipped") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; + } else if (strcmp(value, "flipped-90") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; + } else if (strcmp(value, "flipped-180") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; + } else if (strcmp(value, "flipped-270") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; + } else { + error = cmd_results_new(CMD_INVALID, "output", "Invalid output transform."); + goto fail; + } + } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) { + wordexp_t p; + if (++i >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing background file or color specification."); + goto fail; + } + if (i + 1 >= argc) { + error = cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode or `solid_color`."); + goto fail; + } + if (strcasecmp(argv[i + 1], "solid_color") == 0) { + output->background = strdup(argv[argc - 2]); + output->background_option = strdup("solid_color"); + } else { + // argv[i+j]=bg_option + bool valid = false; + char *mode; + size_t j; + for (j = 0; j < (size_t) (argc - i); ++j) { + mode = argv[i + j]; + for (size_t k = 0; k < sizeof(bg_options) / sizeof(char *); ++k) { + if (strcasecmp(mode, bg_options[k]) == 0) { + valid = true; + break; + } + } + if (valid) { + break; + } + } + if (!valid) { + error = cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode."); + goto fail; + } + + char *src = join_args(argv + i, j); + if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { + error = cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src); + goto fail; + } + free(src); + src = p.we_wordv[0]; + if (config->reading && *src != '/') { + char *conf = strdup(config->current_config); + if (conf) { + char *conf_path = dirname(conf); + src = malloc(strlen(conf_path) + strlen(src) + 2); + if (src) { + sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); + } else { + sway_log(L_ERROR, "Unable to allocate background source"); + } + free(conf); + } else { + sway_log(L_ERROR, "Unable to allocate background source"); + } + } + if (!src || access(src, F_OK) == -1) { + error = cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src); + wordfree(&p); + goto fail; + } + + output->background = strdup(src); + output->background_option = strdup(mode); + if (src != p.we_wordv[0]) { + free(src); + } + wordfree(&p); + + i += j; + } + } + } + + i = list_seq_find(config->output_configs, output_name_cmp, name); + if (i >= 0) { + // merge existing config + struct output_config *oc = config->output_configs->items[i]; + merge_output_config(oc, output); + free_output_config(output); + output = oc; + } else { + list_add(config->output_configs, output); + } + + sway_log(L_DEBUG, "Config stored for output %s (enabled:%d) (%d x %d @ " + "%d, %d scale %d transform %d refresh_rate %f) (bg %s %s)", + output->name, output->enabled, output->width, + output->height, output->x, output->y, output->scale, + output->transform, output->refresh_rate, + output->background, output->background_option); + + if (output->name) { + // Try to find the output container and apply configuration now. If + // this is during startup then there will be no container and config + // will be applied during normal "new output" event from wlc. + swayc_t *cont = NULL; + for (int i = 0; i < root_container.children->length; ++i) { + cont = root_container.children->items[i]; + if (cont->name && ((strcmp(cont->name, output->name) == 0) || (strcmp(output->name, "*") == 0))) { + apply_output_config(output, cont); + + if (strcmp(output->name, "*") != 0) { + // stop looking if the output config isn't applicable to all outputs + break; + } + } + } + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + +fail: + free_output_config(output); + return error; +} diff --git a/sway/config/output.c b/sway/config/output.c new file mode 100644 index 00000000..02e18e59 --- /dev/null +++ b/sway/config/output.c @@ -0,0 +1,166 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include "sway/config.h" +#include "sway/output.h" +#include "log.h" + +int output_name_cmp(const void *item, const void *data) { + const struct output_config *output = item; + const char *name = data; + + return strcmp(output->name, name); +} + +void merge_output_config(struct output_config *dst, struct output_config *src) { + if (src->name) { + if (dst->name) { + free(dst->name); + } + dst->name = strdup(src->name); + } + if (src->enabled != -1) { + dst->enabled = src->enabled; + } + if (src->width != -1) { + dst->width = src->width; + } + if (src->height != -1) { + dst->height = src->height; + } + if (src->x != -1) { + dst->x = src->x; + } + if (src->y != -1) { + dst->y = src->y; + } + if (src->scale != -1) { + dst->scale = src->scale; + } + if (src->background) { + if (dst->background) { + free(dst->background); + } + dst->background = strdup(src->background); + } + if (src->background_option) { + if (dst->background_option) { + free(dst->background_option); + } + dst->background_option = strdup(src->background_option); + } +} + +static void set_mode(struct wlr_output *output, int width, int height, + float refresh_rate) { + struct wlr_output_mode *mode, *best = NULL; + int mhz = (int)(refresh_rate * 1000); + wl_list_for_each(mode, &output->modes, link) { + if (mode->width == width && mode->height == height) { + if (mode->refresh == mhz) { + best = mode; + break; + } + best = mode; + } + } + if (!best) { + sway_log(L_ERROR, "Configured mode for %s not available", output->name); + } else { + sway_log(L_DEBUG, "Assigning configured mode to %s", output->name); + wlr_output_set_mode(output, best); + } +} + +void apply_output_config(struct output_config *oc, swayc_t *output) { + assert(output->type == C_OUTPUT); + + if (oc && oc->enabled == 0) { + destroy_output(output); + return; + } + + struct wlr_output *wlr_output = output->sway_output->wlr_output; + if (oc && oc->width > 0 && oc->height > 0) { + set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); + } + if (oc && oc->scale > 0) { + wlr_output->scale = oc->scale; + } + if (oc && oc->transform != WL_OUTPUT_TRANSFORM_NORMAL) { + wlr_output_transform(wlr_output, oc->transform); + } + + // Find position for it + if (oc && oc->x != -1 && oc->y != -1) { + sway_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); + output->x = oc->x; + output->y = oc->y; + } else { + int x = 0; + for (int i = 0; i < root_container.children->length; ++i) { + swayc_t *c = root_container.children->items[i]; + if (c->type == C_OUTPUT) { + if (c->width + c->x > x) { + x = c->width + c->x; + } + } + } + output->x = x; + } + + if (!oc || !oc->background) { + // Look for a * config for background + int i = list_seq_find(config->output_configs, output_name_cmp, "*"); + if (i >= 0) { + oc = config->output_configs->items[i]; + } else { + oc = NULL; + } + } + + int output_i; + for (output_i = 0; output_i < root_container.children->length; ++output_i) { + if (root_container.children->items[output_i] == output) { + break; + } + } + + if (oc && oc->background) { + // TODO: swaybg + /*if (output->bg_pid != 0) { + terminate_swaybg(output->bg_pid); + } + + sway_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); + + size_t bufsize = 12; + char output_id[bufsize]; + snprintf(output_id, bufsize, "%d", output_i); + output_id[bufsize-1] = 0; + + char *const cmd[] = { + "swaybg", + output_id, + oc->background, + oc->background_option, + NULL, + }; + + output->bg_pid = fork(); + if (output->bg_pid == 0) { + execvp(cmd[0], cmd); + }*/ + } +} + +void free_output_config(struct output_config *oc) { + if (!oc) { + return; + } + free(oc->name); + free(oc->background); + free(oc->background_option); + free(oc); +} diff --git a/sway/main.c b/sway/main.c index bc843591..8952f997 100644 --- a/sway/main.c +++ b/sway/main.c @@ -404,6 +404,10 @@ int main(int argc, char **argv) { security_sanity_check(); + // TODO: wait for server to be ready + // TODO: consume config->cmd_queue + config->active = true; + if (!terminate_request) { server_run(&server); } diff --git a/sway/meson.build b/sway/meson.build index 84f48137..5ae7fbb3 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -5,7 +5,9 @@ sway_sources = files( 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', + 'commands/output.c', 'config.c', + 'config/output.c', 'ipc-json.c', 'ipc-server.c', 'desktop/output.c', diff --git a/sway/tree/container.c b/sway/tree/container.c index e205fbcf..7720718f 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -2,7 +2,9 @@ #include #include #include +#include #include +#include "sway/config.h" #include "sway/container.h" #include "sway/layout.h" #include "sway/output.h" @@ -23,6 +25,30 @@ void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, } } +static void update_root_geometry() { + int width = 0; + int height = 0; + swayc_t *child; + int child_width; + int child_height; + + for (int i = 0; i < root_container.children->length; ++i) { + child = root_container.children->items[i]; + child_width = child->width + child->x; + child_height = child->height + child->y; + if (child_width > width) { + width = child_width; + } + + if (child_height > height) { + height = child_height; + } + } + + root_container.width = width; + root_container.height = height; +} + static swayc_t *new_swayc(enum swayc_types type) { // next id starts at 1 because 0 is assigned to root_container in layout.c static size_t next_id = 1; @@ -44,10 +70,33 @@ static swayc_t *new_swayc(enum swayc_types type) { swayc_t *new_output(struct sway_output *sway_output) { struct wlr_box size; - wlr_output_effective_resolution( - sway_output->wlr_output, &size.width, &size.height); + wlr_output_effective_resolution(sway_output->wlr_output, &size.width, + &size.height); const char *name = sway_output->wlr_output->name; + struct output_config *oc = NULL, *all = NULL; + for (int i = 0; i < config->output_configs->length; ++i) { + struct output_config *cur = config->output_configs->items[i]; + if (strcasecmp(name, cur->name) == 0) { + sway_log(L_DEBUG, "Matched output config for %s", name); + oc = cur; + } + if (strcasecmp("*", cur->name) == 0) { + sway_log(L_DEBUG, "Matched wildcard output config for %s", name); + all = cur; + } + + if (oc && all) { + break; + } + } + if (!oc) { + oc = all; + } + if (oc && !oc->enabled) { + return NULL; + } + swayc_t *output = new_swayc(C_OUTPUT); output->sway_output = sway_output; output->name = name ? strdup(name) : NULL; @@ -58,6 +107,8 @@ swayc_t *new_output(struct sway_output *sway_output) { wlr_output_layout_add_auto(root_container.output_layout, sway_output->wlr_output); + apply_output_config(oc, output); + add_child(&root_container, output); // Create workspace @@ -139,6 +190,34 @@ static void free_swayc(swayc_t *cont) { free(cont); } +swayc_t *destroy_output(swayc_t *output) { + if (!sway_assert(output, "null output passed to destroy_output")) { + return NULL; + } + if (output->children->length > 0) { + // TODO save workspaces when there are no outputs. + // TODO also check if there will ever be no outputs except for exiting + // program + if (root_container.children->length > 1) { + int p = root_container.children->items[0] == output; + // Move workspace from this output to another output + while (output->children->length) { + swayc_t *child = output->children->items[0]; + remove_child(child); + add_child(root_container.children->items[p], child); + } + sort_workspaces(root_container.children->items[p]); + // TODO WLR: is this needed anymore? + //update_visibility(root_container.children->items[p]); + arrange_windows(root_container.children->items[p], -1, -1); + } + } + sway_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); + free_swayc(output); + update_root_geometry(); + return &root_container; +} + swayc_t *destroy_view(swayc_t *view) { if (!sway_assert(view, "null view passed to destroy_view")) { return NULL; -- cgit v1.2.3 From 68ae989ceef0a144988c0a55b13aaacf514b957d Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 6 Dec 2017 12:57:13 +0100 Subject: Init, merge output config params, use wlr_output_layout --- include/sway/config.h | 3 ++- sway/commands/output.c | 4 +--- sway/config/output.c | 45 ++++++++++++++++++++++++++++++--------------- sway/tree/container.c | 6 ------ 4 files changed, 33 insertions(+), 25 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 1b49c5c9..231356f2 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -84,7 +84,7 @@ struct output_config { float refresh_rate; int x, y; int scale; - enum wl_output_transform transform; + int32_t transform; char *background; char *background_option; @@ -364,6 +364,7 @@ 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); +void output_config_defaults(struct output_config *oc); void merge_output_config(struct output_config *dst, struct output_config *src); /** Sets up a WLC output handle based on a given output_config. */ diff --git a/sway/commands/output.c b/sway/commands/output.c index c964bef7..bbf8efc3 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -31,10 +31,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { if (!output) { return cmd_results_new(CMD_FAILURE, "output", "Unable to allocate output config"); } - output->x = output->y = output->width = output->height = -1; + output_config_defaults(output); output->name = strdup(name); - output->enabled = -1; - output->scale = 1; // TODO: atoi doesn't handle invalid numbers diff --git a/sway/config/output.c b/sway/config/output.c index 02e18e59..4ed2c531 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "sway/config.h" #include "sway/output.h" #include "log.h" @@ -13,6 +14,15 @@ int output_name_cmp(const void *item, const void *data) { return strcmp(output->name, name); } +void output_config_defaults(struct output_config *oc) { + oc->enabled = -1; + oc->width = oc->height -1; + oc->refresh_rate = -1; + oc->x = oc->y = -1; + oc->scale = -1; + oc->transform = -1; +} + void merge_output_config(struct output_config *dst, struct output_config *src) { if (src->name) { if (dst->name) { @@ -38,6 +48,12 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { if (src->scale != -1) { dst->scale = src->scale; } + if (src->refresh_rate != -1) { + dst->refresh_rate = src->refresh_rate; + } + if (src->transform != -1) { + dst->transform = src->transform; + } if (src->background) { if (dst->background) { free(dst->background); @@ -86,29 +102,28 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); } if (oc && oc->scale > 0) { + sway_log(L_DEBUG, "Set %s scale to %d", oc->name, oc->scale); wlr_output->scale = oc->scale; } - if (oc && oc->transform != WL_OUTPUT_TRANSFORM_NORMAL) { + if (oc && oc->transform >= 0) { + sway_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); wlr_output_transform(wlr_output, oc->transform); } // Find position for it - if (oc && oc->x != -1 && oc->y != -1) { + if (oc && (oc->x != -1 || oc->y != -1)) { sway_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); - output->x = oc->x; - output->y = oc->y; + wlr_output_layout_add(root_container.output_layout, wlr_output, oc->x, + oc->y); } else { - int x = 0; - for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c->type == C_OUTPUT) { - if (c->width + c->x > x) { - x = c->width + c->x; - } - } - } - output->x = x; + wlr_output_layout_add_auto(root_container.output_layout, wlr_output); } + struct wlr_box *output_layout_box = + wlr_output_layout_get_box(root_container.output_layout, wlr_output); + output->x = output_layout_box->x; + output->y = output_layout_box->y; + output->width = output_layout_box->width; + output->height = output_layout_box->height; if (!oc || !oc->background) { // Look for a * config for background @@ -128,7 +143,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { } if (oc && oc->background) { - // TODO: swaybg + // TODO swaybg /*if (output->bg_pid != 0) { terminate_swaybg(output->bg_pid); } diff --git a/sway/tree/container.c b/sway/tree/container.c index 7720718f..ba305efa 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -100,12 +100,6 @@ swayc_t *new_output(struct sway_output *sway_output) { swayc_t *output = new_swayc(C_OUTPUT); output->sway_output = sway_output; output->name = name ? strdup(name) : NULL; - output->width = size.width; - output->height = size.width; - - // TODO configure output layout position - wlr_output_layout_add_auto(root_container.output_layout, - sway_output->wlr_output); apply_output_config(oc, output); -- cgit v1.2.3 From 8764dc26c634379ca5b5c2c4fc26cf8be9adf027 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 6 Dec 2017 19:45:43 +0100 Subject: Add new_output_config, update root container size on output hotplug --- include/sway/config.h | 4 +--- sway/commands/output.c | 3 +-- sway/config/output.c | 7 ++++++- sway/tree/container.c | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 231356f2..4dd8e94c 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -364,10 +364,8 @@ 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); -void output_config_defaults(struct output_config *oc); +struct output_config *new_output_config(); void merge_output_config(struct output_config *dst, struct output_config *src); -/** Sets up a WLC output handle based on a given output_config. - */ void apply_output_config(struct output_config *oc, swayc_t *output); void free_output_config(struct output_config *oc); diff --git a/sway/commands/output.c b/sway/commands/output.c index bbf8efc3..11da0ff6 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -27,11 +27,10 @@ struct cmd_results *cmd_output(int argc, char **argv) { } const char *name = argv[0]; - struct output_config *output = calloc(1, sizeof(struct output_config)); + struct output_config *output = new_output_config(); if (!output) { return cmd_results_new(CMD_FAILURE, "output", "Unable to allocate output config"); } - output_config_defaults(output); output->name = strdup(name); // TODO: atoi doesn't handle invalid numbers diff --git a/sway/config/output.c b/sway/config/output.c index 4a0a5cc9..26798503 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -14,13 +14,18 @@ int output_name_cmp(const void *item, const void *data) { return strcmp(output->name, name); } -void output_config_defaults(struct output_config *oc) { +struct output_config *new_output_config() { + struct output_config *oc = calloc(1, sizeof(struct output_config)); + if (oc == NULL) { + return NULL; + } oc->enabled = -1; oc->width = oc->height -1; oc->refresh_rate = -1; oc->x = oc->y = -1; oc->scale = -1; oc->transform = -1; + return oc; } void merge_output_config(struct output_config *dst, struct output_config *src) { diff --git a/sway/tree/container.c b/sway/tree/container.c index ec3311a0..d9bed7d8 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -93,6 +93,7 @@ swayc_t *new_output(struct sway_output *sway_output) { sway_log(L_DEBUG, "Creating default workspace %s", ws_name); new_workspace(output, ws_name); free(ws_name); + update_root_geometry(); return output; } -- cgit v1.2.3 From 163edc5a900fda58e006ed30e14ae10cc4aa13b3 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 12 Dec 2017 08:29:37 -0500 Subject: sway input device --- include/sway/config.h | 1 + include/sway/input/input-manager.h | 31 +++++-- include/sway/input/keyboard.h | 4 +- include/sway/input/seat.h | 13 +-- sway/commands.c | 23 +---- sway/config.c | 29 ++++++ sway/desktop/output.c | 5 +- sway/desktop/wl_shell.c | 5 +- sway/desktop/xdg_shell_v6.c | 5 +- sway/desktop/xwayland.c | 6 +- sway/input/input-manager.c | 185 ++++++++++++++++++++++++------------- sway/input/keyboard.c | 18 ++-- sway/input/seat.c | 104 ++++++++------------- sway/server.c | 2 +- 14 files changed, 237 insertions(+), 194 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 7de85ab7..d80f5a39 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -355,6 +355,7 @@ char *do_var_replacement(char *str); struct cmd_results *check_security_config(); int input_identifier_cmp(const void *item, const void *data); +struct input_config *new_input_config(const char* identifier); 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); diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 78bc161f..7d7c463f 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -7,21 +7,40 @@ extern struct input_config *current_input_config; +/** + * The global singleton input manager + * TODO: make me not a global + */ +extern struct sway_input_manager *input_manager; + +struct sway_input_device { + char *identifier; + struct wlr_input_device *wlr_device; + struct input_config *config; + struct sway_keyboard *keyboard; // managed by the seat + struct wl_list link; +}; + struct sway_input_manager { struct wl_listener input_add; struct wl_listener input_remove; struct sway_server *server; - list_t *seats; + struct wl_list devices; + struct wl_list seats; }; -struct input_config *new_input_config(const char* identifier); - -char* libinput_dev_unique_id(struct libinput_device *dev); - struct sway_input_manager *sway_input_manager_create( struct sway_server *server); -bool sway_input_manager_swayc_has_focus(struct sway_input_manager *input, +bool sway_input_manager_has_focus(struct sway_input_manager *input, swayc_t *container); +void sway_input_manager_set_focus(struct sway_input_manager *input, + swayc_t *container); + +void sway_input_manager_configure_xcursor(struct sway_input_manager *input); + +void sway_input_manager_apply_config(struct sway_input_manager *input, + struct input_config *config); + #endif diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index 19d40bdc..881805b4 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h @@ -2,7 +2,7 @@ struct sway_keyboard { struct sway_seat *seat; - struct wlr_input_device *device; + struct sway_input_device *device; struct wl_list link; // sway_seat::keyboards struct wl_listener keyboard_key; @@ -10,6 +10,6 @@ struct sway_keyboard { }; struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, - struct wlr_input_device *device); + struct sway_input_device *device); void sway_keyboard_destroy(struct sway_keyboard *keyboard); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 5455601e..bd94a357 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -10,26 +10,21 @@ struct sway_seat { struct sway_input_manager *input; swayc_t *focus; - struct wl_list keyboards; // sway_keyboard::link - struct wl_list pointers; // sway_pointer::link + list_t *devices; struct wl_listener focus_destroy; -}; -struct sway_pointer { - struct sway_seat *seat; - struct wlr_input_device *device; - struct wl_list link; + struct wl_list link; // input_manager::seats }; struct sway_seat *sway_seat_create(struct sway_input_manager *input, const char *seat_name); void sway_seat_add_device(struct sway_seat *seat, - struct wlr_input_device *device); + struct sway_input_device *device); void sway_seat_remove_device(struct sway_seat *seat, - struct wlr_input_device *device); + struct sway_input_device *device); void sway_seat_configure_xcursor(struct sway_seat *seat); diff --git a/sway/commands.c b/sway/commands.c index 7710c6ab..57f76ea9 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -71,28 +71,7 @@ void input_cmd_apply(struct input_config *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. - /* TODO WLR - 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); - if (!dev_identifier) { - break; - } - int match = dev_identifier && strcmp(dev_identifier, input->identifier) == 0; - free(dev_identifier); - if (match) { - apply_input_config(input, device); - break; - } - } - */ - } + sway_input_manager_apply_config(input_manager, input); } /** diff --git a/sway/config.c b/sway/config.c index ec8e89b4..7ae3c2a4 100644 --- a/sway/config.c +++ b/sway/config.c @@ -226,6 +226,34 @@ static int qstrcmp(const void* a, const void* b) { return strcmp(*((char**) a), *((char**) b)); } +struct input_config *new_input_config(const char* identifier) { + struct input_config *input = calloc(1, sizeof(struct input_config)); + if (!input) { + sway_log(L_DEBUG, "Unable to allocate input config"); + return NULL; + } + sway_log(L_DEBUG, "new_input_config(%s)", identifier); + if (!(input->identifier = strdup(identifier))) { + free(input); + sway_log(L_DEBUG, "Unable to allocate input config"); + return NULL; + } + + 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->accel_profile = INT_MIN; + input->pointer_accel = FLT_MIN; + input->scroll_method = INT_MIN; + input->left_handed = INT_MIN; + + return input; +} + void merge_input_config(struct input_config *dst, struct input_config *src) { if (src->identifier) { if (dst->identifier) { @@ -453,6 +481,7 @@ bool load_include_configs(const char *path, struct sway_config *config) { return true; } + bool read_config(FILE *file, struct sway_config *config) { bool success = true; enum cmd_status block = CMD_BLOCK_END; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0e7f7060..af067326 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -136,10 +136,7 @@ void output_add_notify(struct wl_listener *listener, void *data) { output->resolution.notify = output_resolution_notify; wl_signal_add(&wlr_output->events.resolution, &output->resolution); - for (int i = 0; i < server->input->seats->length; ++i) { - struct sway_seat *seat = server->input->seats->items[i]; - sway_seat_configure_xcursor(seat); - } + sway_input_manager_configure_xcursor(input_manager); arrange_windows(output->swayc, -1, -1); } diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 3d3b1c44..df81d5be 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -129,8 +129,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { arrange_windows(cont->parent, -1, -1); - for (int i = 0; i < server->input->seats->length; ++i) { - struct sway_seat *seat = server->input->seats->items[i]; - sway_seat_set_focus(seat, cont); - } + sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 8ad6a5ec..82775e2f 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -135,8 +135,5 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { arrange_windows(cont->parent, -1, -1); - for (int i = 0; i < server->input->seats->length; ++i) { - struct sway_seat *seat = server->input->seats->items[i]; - sway_seat_set_focus(seat, cont); - } + sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 724c8a82..a7e84aa1 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -173,9 +173,5 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); - - for (int i = 0; i < server->input->seats->length; ++i) { - struct sway_seat *seat = server->input->seats->items[i]; - sway_seat_set_focus(seat, cont); - } + sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index ca80f267..b7f5615c 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -14,23 +14,70 @@ static const char *default_seat = "seat0"; +// TODO make me not global +struct sway_input_manager *input_manager; + struct input_config *current_input_config = NULL; static struct sway_seat *input_manager_get_seat( struct sway_input_manager *input, const char *seat_name) { struct sway_seat *seat = NULL; - - for (int i = 0; i < input->seats->length; ++i) { - seat = input->seats->items[i]; + wl_list_for_each(seat, &input->seats, link) { if (strcmp(seat->seat->name, seat_name) == 0) { return seat; } } - seat = sway_seat_create(input, seat_name); - list_add(input->seats, seat); + return sway_seat_create(input, seat_name); +} + +static char *get_device_identifier(struct wlr_input_device *device) { + int vendor = device->vendor; + int product = device->product; + char *name = strdup(device->name); + + 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); + if (!identifier) { + sway_log(L_ERROR, "Unable to allocate unique input device name"); + return NULL; + } + + const char *fmt = "%d:%d:%s"; + snprintf(identifier, len, fmt, vendor, product, name); + free(name); + return identifier; +} - return seat; +static struct sway_input_device *input_sway_device_from_wlr(struct sway_input_manager *input, + struct wlr_input_device *device) { + struct sway_input_device *sway_device = NULL; + wl_list_for_each(sway_device, &input->devices, link) { + if (sway_device->wlr_device == device) { + return sway_device; + } + } + return NULL; +} + +static struct sway_input_device *input_sway_device_from_config(struct sway_input_manager *input, + struct input_config *config) { + struct sway_input_device *sway_device = NULL; + wl_list_for_each(sway_device, &input->devices, link) { + if (strcmp(sway_device->identifier, config->identifier) == 0) { + return sway_device; + } + } + return NULL; } static void input_add_notify(struct wl_listener *listener, void *data) { @@ -38,9 +85,27 @@ static void input_add_notify(struct wl_listener *listener, void *data) { wl_container_of(listener, input, input_add); struct wlr_input_device *device = data; - // TODO device configuration + struct sway_input_device *sway_device = + calloc(1, sizeof(struct sway_input_device)); + if (!sway_assert(sway_device, "could not allocate input device")) { + return; + } + + sway_device->wlr_device = device; + sway_device->identifier = get_device_identifier(device); + wl_list_insert(&input->devices, &sway_device->link); + + // find config + for (int i = 0; i < config->input_configs->length; ++i) { + struct input_config *input_config = config->input_configs->items[i]; + if (strcmp(input_config->identifier, sway_device->identifier) == 0) { + sway_device->config = input_config; + break; + } + } + struct sway_seat *seat = input_manager_get_seat(input, default_seat); - sway_seat_add_device(seat, device); + sway_seat_add_device(seat, sway_device); } static void input_remove_notify(struct wl_listener *listener, void *data) { @@ -48,9 +113,21 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { wl_container_of(listener, input, input_remove); struct wlr_input_device *device = data; - // TODO device configuration - struct sway_seat *seat = input_manager_get_seat(input, default_seat); - sway_seat_remove_device(seat, device); + struct sway_input_device *sway_device = + input_sway_device_from_wlr(input, device); + + if (!sway_assert(sway_device, "could not find sway device")) { + return; + } + + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + sway_seat_remove_device(seat, sway_device); + } + + wl_list_remove(&sway_device->link); + free(sway_device->identifier); + free(sway_device); } struct sway_input_manager *sway_input_manager_create( @@ -63,7 +140,8 @@ struct sway_input_manager *sway_input_manager_create( // XXX probably don't need the full server input->server = server; - input->seats = create_list(); + wl_list_init(&input->devices); + wl_list_init(&input->seats); // create the default seat input_manager_get_seat(input, default_seat); @@ -77,69 +155,46 @@ struct sway_input_manager *sway_input_manager_create( return input; } -struct input_config *new_input_config(const char* identifier) { - struct input_config *input = calloc(1, sizeof(struct input_config)); - if (!input) { - sway_log(L_DEBUG, "Unable to allocate input config"); - return NULL; - } - sway_log(L_DEBUG, "new_input_config(%s)", identifier); - if (!(input->identifier = strdup(identifier))) { - free(input); - sway_log(L_DEBUG, "Unable to allocate input config"); - return NULL; +bool sway_input_manager_has_focus(struct sway_input_manager *input, + swayc_t *container) { + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + if (seat->focus == container) { + return true; + } } - 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->accel_profile = INT_MIN; - input->pointer_accel = FLT_MIN; - input->scroll_method = INT_MIN; - input->left_handed = INT_MIN; - - return input; + return false; } -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 = '_'; - } +void sway_input_manager_set_focus(struct sway_input_manager *input, + swayc_t *container) { + struct sway_seat *seat ; + wl_list_for_each(seat, &input->seats, link) { + sway_seat_set_focus(seat, container); } +} - sway_log(L_DEBUG, "rewritten name %s", name); +void sway_input_manager_apply_config(struct sway_input_manager *input, + struct input_config *config) { + struct sway_input_device *sway_device = + input_sway_device_from_config(input, config); + if (!sway_device) { + return; + } - int len = strlen(name) + sizeof(char) * 6; - char *identifier = malloc(len); - if (!identifier) { - sway_log(L_ERROR, "Unable to allocate unique input device name"); - return NULL; + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + sway_seat_remove_device(seat, sway_device); } - const char *fmt = "%d:%d:%s"; - snprintf(identifier, len, fmt, vendor, product, name); - free(name); - return identifier; + seat = input_manager_get_seat(input, default_seat); + sway_seat_add_device(seat, sway_device); } -bool sway_input_manager_swayc_has_focus(struct sway_input_manager *input, - swayc_t *container) { - for (int i = 0; i < input->seats->length; ++i) { - struct sway_seat *seat = input->seats->items[i]; - if (seat->focus == container) { - return true; - } +void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + sway_seat_configure_xcursor(seat); } - - return false; } diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 31d254df..6a792c65 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -6,7 +6,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { struct sway_keyboard *keyboard = wl_container_of(listener, keyboard, keyboard_key); struct wlr_event_keyboard_key *event = data; - wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device); + wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device->wlr_device); wlr_seat_keyboard_notify_key(keyboard->seat->seat, event->time_msec, event->keycode, event->state); } @@ -15,12 +15,12 @@ static void handle_keyboard_modifiers(struct wl_listener *listener, void *data) { struct sway_keyboard *keyboard = wl_container_of(listener, keyboard, keyboard_modifiers); - wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device); + wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device->wlr_device); wlr_seat_keyboard_notify_modifiers(keyboard->seat->seat); } struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, - struct wlr_input_device *device) { + struct sway_input_device *device) { struct sway_keyboard *keyboard = calloc(1, sizeof(struct sway_keyboard)); if (!sway_assert(keyboard, "could not allocate sway keyboard")) { @@ -43,18 +43,18 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, return NULL; } - wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context, - &rules, XKB_KEYMAP_COMPILE_NO_FLAGS)); + wlr_keyboard_set_keymap(device->wlr_device->keyboard, + xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS)); xkb_context_unref(context); - wl_signal_add(&device->keyboard->events.key, &keyboard->keyboard_key); + wl_signal_add(&device->wlr_device->keyboard->events.key, + &keyboard->keyboard_key); keyboard->keyboard_key.notify = handle_keyboard_key; - wl_signal_add(&device->keyboard->events.modifiers, &keyboard->keyboard_modifiers); + wl_signal_add(&device->wlr_device->keyboard->events.modifiers, + &keyboard->keyboard_modifiers); keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; - wl_list_insert(&seat->keyboards, &keyboard->link); - return keyboard; } diff --git a/sway/input/seat.c b/sway/input/seat.c index 9c17250d..80c6424f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -29,6 +29,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, } seat->input = input; + seat->devices = create_list(); wlr_seat_set_capabilities(seat->seat, WL_SEAT_CAPABILITY_KEYBOARD | @@ -37,67 +38,38 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, sway_seat_configure_xcursor(seat); - wl_list_init(&seat->keyboards); + wl_list_insert(&input->seats, &seat->link); return seat; } -static struct sway_pointer *seat_pointer_from_device(struct sway_seat *seat, - struct wlr_input_device *device) { - struct sway_pointer *pointer = NULL; - wl_list_for_each(pointer, &seat->pointers, link) { - if (pointer->device == device) { - return pointer; - } - } - - return pointer; -} - -static struct sway_keyboard *seat_keyboard_from_device(struct sway_seat *seat, - struct wlr_input_device *device) { - struct sway_keyboard *keyboard = NULL; - wl_list_for_each(keyboard, &seat->keyboards, link) { - if (keyboard->device == device) { - return keyboard; - } - } - - return keyboard; -} - static void seat_add_pointer(struct sway_seat *seat, - struct wlr_input_device *device) { + struct sway_input_device *sway_device) { // TODO pointer configuration - if (seat_pointer_from_device(seat, device)) { - // already added - return; - } - - struct sway_pointer *pointer = calloc(1, sizeof(struct sway_pointer)); - pointer->seat = seat; - pointer->device = device; - wl_list_insert(&seat->pointers, &pointer->link); - - wlr_cursor_attach_input_device(seat->cursor->cursor, device); + wlr_cursor_attach_input_device(seat->cursor->cursor, + sway_device->wlr_device); } static void seat_add_keyboard(struct sway_seat *seat, - struct wlr_input_device *device) { + struct sway_input_device *device) { // TODO keyboard configuration - if (seat_keyboard_from_device(seat, device)) { - // already added - return; - } - sway_keyboard_create(seat, device); - wlr_seat_set_keyboard(seat->seat, device); + wlr_seat_set_keyboard(seat->seat, device->wlr_device); +} + +bool sway_seat_has_device(struct sway_seat *seat, + struct sway_input_device *device) { + return false; } void sway_seat_add_device(struct sway_seat *seat, - struct wlr_input_device *device) { - sway_log(L_DEBUG, "input add: %s", device->name); - switch (device->type) { + struct sway_input_device *device) { + if (sway_seat_has_device(seat, device)) { + return; + } + + sway_log(L_DEBUG, "input add: %s", device->identifier); + switch (device->wlr_device->type) { case WLR_INPUT_DEVICE_POINTER: seat_add_pointer(seat, device); break; @@ -110,31 +82,30 @@ void sway_seat_add_device(struct sway_seat *seat, sway_log(L_DEBUG, "TODO: add other devices"); break; } + + list_add(seat->devices, device); } static void seat_remove_keyboard(struct sway_seat *seat, - struct wlr_input_device *device) { - struct sway_keyboard *keyboard = seat_keyboard_from_device(seat, device); - if (keyboard) { - sway_keyboard_destroy(keyboard); + struct sway_input_device *device) { + if (device && device->keyboard) { + sway_keyboard_destroy(device->keyboard); } } static void seat_remove_pointer(struct sway_seat *seat, - struct wlr_input_device *device) { - struct sway_pointer *pointer = seat_pointer_from_device(seat, device); - - if (pointer) { - wl_list_remove(&pointer->link); - free(pointer); - wlr_cursor_detach_input_device(seat->cursor->cursor, device); - } + struct sway_input_device *device) { + wlr_cursor_detach_input_device(seat->cursor->cursor, device->wlr_device); } void sway_seat_remove_device(struct sway_seat *seat, - struct wlr_input_device *device) { - sway_log(L_DEBUG, "input remove: %s", device->name); - switch (device->type) { + struct sway_input_device *device) { + sway_log(L_DEBUG, "input remove: %s", device->identifier); + if (!sway_seat_has_device(seat, device)) { + return; + } + + switch (device->wlr_device->type) { case WLR_INPUT_DEVICE_POINTER: seat_remove_pointer(seat, device); break; @@ -147,6 +118,13 @@ void sway_seat_remove_device(struct sway_seat *seat, sway_log(L_DEBUG, "TODO: remove other devices"); break; } + + for (int i = 0; i < seat->devices->length; ++i) { + if (seat->devices->items[i] == device) { + list_del(seat->devices, i); + break; + } + } } void sway_seat_configure_xcursor(struct sway_seat *seat) { @@ -211,7 +189,7 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { seat->focus = container; if (last_focus && - !sway_input_manager_swayc_has_focus(seat->input, last_focus)) { + !sway_input_manager_has_focus(seat->input, last_focus)) { struct sway_view *view = last_focus->sway_view; view->iface.set_activated(view, false); diff --git a/sway/server.c b/sway/server.c index 7b9a5e8e..32c8f03c 100644 --- a/sway/server.c +++ b/sway/server.c @@ -60,7 +60,7 @@ bool server_init(struct sway_server *server) { return false; } - server->input = sway_input_manager_create(server); + input_manager = sway_input_manager_create(server); return true; } -- cgit v1.2.3 From c173d30b9203520c274f34eb72fc787aa33ca211 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 12 Dec 2017 10:55:20 -0500 Subject: seat configuration --- include/sway/commands.h | 1 + include/sway/config.h | 1 + sway/commands.c | 2 ++ sway/commands/input/seat.c | 28 ++++++++++++++++++++++++++++ sway/config.c | 1 + sway/input/input-manager.c | 11 +++++++---- sway/meson.build | 1 + 7 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 sway/commands/input/seat.c (limited to 'include/sway/config.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index 138e3c29..75340e03 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -180,6 +180,7 @@ sway_cmd bar_colors_cmd_statusline; sway_cmd bar_colors_cmd_focused_statusline; sway_cmd bar_colors_cmd_urgent_workspace; +sway_cmd input_cmd_seat; sway_cmd input_cmd_accel_profile; sway_cmd input_cmd_click_method; sway_cmd input_cmd_drag_lock; diff --git a/include/sway/config.h b/include/sway/config.h index d80f5a39..9fcecfd6 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -69,6 +69,7 @@ struct input_config { bool capturable; struct wlr_box region; + char *seat; }; /** diff --git a/sway/commands.c b/sway/commands.c index 57f76ea9..6645436a 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -123,6 +123,7 @@ static int handler_compare(const void *_a, const void *_b) { return strcasecmp(a->command, b->command); } +// must be in order for the bsearch static struct cmd_handler input_handlers[] = { { "accel_profile", input_cmd_accel_profile }, { "click_method", input_cmd_click_method }, @@ -134,6 +135,7 @@ static struct cmd_handler input_handlers[] = { { "natural_scroll", input_cmd_natural_scroll }, { "pointer_accel", input_cmd_pointer_accel }, { "scroll_method", input_cmd_scroll_method }, + { "seat", input_cmd_seat }, { "tap", input_cmd_tap }, }; diff --git a/sway/commands/input/seat.c b/sway/commands/input/seat.c new file mode 100644 index 00000000..9d86ac0e --- /dev/null +++ b/sway/commands/input/seat.c @@ -0,0 +1,28 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_seat(int argc, char **argv) { + sway_log(L_DEBUG, "seat for device: %d %s", + current_input_config==NULL, current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "seat", + "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + // TODO validate seat name + free(new_config->seat); + new_config->seat = strdup(argv[0]); + + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 4bc74ee0..b77b8b4b 100644 --- a/sway/config.c +++ b/sway/config.c @@ -300,6 +300,7 @@ void free_input_config(struct input_config *ic) { return; } free(ic->identifier); + free(ic->seat); free(ic); } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index b7f5615c..b07a733e 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -104,7 +104,9 @@ static void input_add_notify(struct wl_listener *listener, void *data) { } } - struct sway_seat *seat = input_manager_get_seat(input, default_seat); + const char *seat_name = + (sway_device->config ? sway_device->config->seat : default_seat); + struct sway_seat *seat = input_manager_get_seat(input, seat_name); sway_seat_add_device(seat, sway_device); } @@ -176,9 +178,9 @@ void sway_input_manager_set_focus(struct sway_input_manager *input, } void sway_input_manager_apply_config(struct sway_input_manager *input, - struct input_config *config) { + struct input_config *input_config) { struct sway_input_device *sway_device = - input_sway_device_from_config(input, config); + input_sway_device_from_config(input, input_config); if (!sway_device) { return; } @@ -188,7 +190,8 @@ void sway_input_manager_apply_config(struct sway_input_manager *input, sway_seat_remove_device(seat, sway_device); } - seat = input_manager_get_seat(input, default_seat); + const char *seat_name = (input_config->seat ? input_config->seat : default_seat); + seat = input_manager_get_seat(input, seat_name); sway_seat_add_device(seat, sway_device); } diff --git a/sway/meson.build b/sway/meson.build index aa3dd2a7..fad1f88c 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -11,6 +11,7 @@ sway_sources = files( 'commands/exec_always.c', 'commands/include.c', 'commands/input.c', + 'commands/input/seat.c', 'commands/input/accel_profile.c', 'commands/input/click_method.c', 'commands/input/drag_lock.c', -- cgit v1.2.3 From d293c429424a9f96c3fc8143af457645326e7a0e Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 12 Dec 2017 21:09:51 +0100 Subject: Update output container box in event handler --- include/sway/config.h | 1 - sway/commands/output.c | 3 ++- sway/config/output.c | 6 ------ sway/desktop/output.c | 23 +++++++++++++++++------ 4 files changed, 19 insertions(+), 14 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 4dd8e94c..139d7800 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/sway/commands/output.c b/sway/commands/output.c index be78358a..23792855 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -29,7 +29,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { struct output_config *output = new_output_config(); if (!output) { - return cmd_results_new(CMD_FAILURE, "output", "Unable to allocate output config"); + sway_log(L_ERROR, "Failed to allocate output config"); + return NULL; } output->name = strdup(name); diff --git a/sway/config/output.c b/sway/config/output.c index ed47a617..6371763f 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -131,12 +131,6 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { wlr_output_layout_add_auto(root_container.sway_root->output_layout, wlr_output); } - struct wlr_box *output_layout_box = wlr_output_layout_get_box( - root_container.sway_root->output_layout, wlr_output); - output->x = output_layout_box->x; - output->y = output_layout_box->y; - output->width = output_layout_box->width; - output->height = output_layout_box->height; if (!oc || !oc->background) { // Look for a * config for background diff --git a/sway/desktop/output.c b/sway/desktop/output.c index bcdaa7d2..3fd49846 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -91,19 +91,30 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { soutput->last_frame = now; } +static void output_update_size(struct sway_output *output) { + struct wlr_box *output_layout_box = wlr_output_layout_get_box( + root_container.sway_root->output_layout, output->wlr_output); + output->swayc->x = output_layout_box->x; + output->swayc->y = output_layout_box->y; + output->swayc->width = output_layout_box->width; + output->swayc->height = output_layout_box->height; + + arrange_windows(output->swayc, -1, -1); +} + static void output_resolution_notify(struct wl_listener *listener, void *data) { - struct sway_output *soutput = wl_container_of(listener, soutput, resolution); - arrange_windows(soutput->swayc, -1, -1); + struct sway_output *output = wl_container_of(listener, output, resolution); + output_update_size(output); } static void output_scale_notify(struct wl_listener *listener, void *data) { - struct sway_output *soutput = wl_container_of(listener, soutput, scale); - arrange_windows(soutput->swayc, -1, -1); + struct sway_output *output = wl_container_of(listener, output, scale); + output_update_size(output); } static void output_transform_notify(struct wl_listener *listener, void *data) { - struct sway_output *soutput = wl_container_of(listener, soutput, transform); - arrange_windows(soutput->swayc, -1, -1); + struct sway_output *output = wl_container_of(listener, output, transform); + output_update_size(output); } void output_add_notify(struct wl_listener *listener, void *data) { -- cgit v1.2.3 From 92fef27eaa0b52c9d37bdabff14ae21cd6660f46 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 14 Dec 2017 11:11:56 -0500 Subject: basic configuration --- include/sway/commands.h | 5 ++ include/sway/config.h | 27 +++++- include/sway/input/input-manager.h | 9 +- include/sway/input/keyboard.h | 9 +- include/sway/input/seat.h | 20 ++++- sway/commands.c | 32 +++++++- sway/commands/input/seat.c | 28 ------- sway/commands/seat.c | 35 ++++++++ sway/commands/seat/attach.c | 26 ++++++ sway/config.c | 144 ++++++++++++++++++++++++++++++-- sway/input/cursor.c | 8 +- sway/input/input-manager.c | 139 ++++++++++++++++++++++--------- sway/input/keyboard.c | 51 ++++++++---- sway/input/seat.c | 163 +++++++++++++++++++++++-------------- sway/meson.build | 3 +- 15 files changed, 534 insertions(+), 165 deletions(-) delete mode 100644 sway/commands/input/seat.c create mode 100644 sway/commands/seat.c create mode 100644 sway/commands/seat/attach.c (limited to 'include/sway/config.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index 75340e03..ce74e1ed 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -17,6 +17,7 @@ enum cmd_status { CMD_BLOCK_BAR, CMD_BLOCK_BAR_COLORS, CMD_BLOCK_INPUT, + CMD_BLOCK_SEAT, CMD_BLOCK_COMMANDS, CMD_BLOCK_IPC, CMD_BLOCK_IPC_EVENTS, @@ -42,6 +43,7 @@ enum expected_args { }; void input_cmd_apply(struct input_config *input); +void seat_cmd_apply(struct seat_config *seat); struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val); @@ -111,6 +113,7 @@ sway_cmd cmd_gaps; sway_cmd cmd_hide_edge_borders; sway_cmd cmd_include; sway_cmd cmd_input; +sway_cmd cmd_seat; sway_cmd cmd_ipc; sway_cmd cmd_kill; sway_cmd cmd_layout; @@ -193,6 +196,8 @@ sway_cmd input_cmd_pointer_accel; sway_cmd input_cmd_scroll_method; sway_cmd input_cmd_tap; +sway_cmd seat_cmd_attach; + sway_cmd cmd_ipc_cmd; sway_cmd cmd_ipc_events; sway_cmd cmd_ipc_event_cmd; diff --git a/include/sway/config.h b/include/sway/config.h index 9fcecfd6..5df5d61e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -69,7 +69,22 @@ struct input_config { bool capturable; struct wlr_box region; - char *seat; +}; + +/** + * Options for misc device configurations that happen in the seat block + */ +struct seat_attachment_config { + char *identifier; + // TODO other things are configured here for some reason +}; + +/** + * Options for multiseat and other misc device configurations + */ +struct seat_config { + char *name; + list_t *attachments; // list of seat_attachment configs }; /** @@ -260,6 +275,7 @@ struct sway_config { list_t *pid_workspaces; list_t *output_configs; list_t *input_configs; + list_t *seat_configs; list_t *criteria; list_t *no_focus; list_t *active_bar_modifiers; @@ -358,9 +374,16 @@ struct cmd_results *check_security_config(); int input_identifier_cmp(const void *item, const void *data); struct input_config *new_input_config(const char* identifier); 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 seat_name_cmp(const void *item, const void *data); +struct seat_config *new_seat_config(const char* name); +void merge_seat_config(struct seat_config *dst, struct seat_config *src); +void free_seat_config(struct seat_config *ic); +struct seat_attachment_config *seat_attachment_config_new(); +struct seat_attachment_config *seat_config_get_attachment( + struct seat_config *seat_config, char *identifier); + int output_name_cmp(const void *item, const void *data); void merge_output_config(struct output_config *dst, struct output_config *src); /** Sets up a WLC output handle based on a given output_config. diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 7d7c463f..cdcffab6 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -6,6 +6,7 @@ #include "list.h" extern struct input_config *current_input_config; +extern struct seat_config *current_seat_config; /** * The global singleton input manager @@ -17,7 +18,6 @@ struct sway_input_device { char *identifier; struct wlr_input_device *wlr_device; struct input_config *config; - struct sway_keyboard *keyboard; // managed by the seat struct wl_list link; }; @@ -40,7 +40,10 @@ void sway_input_manager_set_focus(struct sway_input_manager *input, void sway_input_manager_configure_xcursor(struct sway_input_manager *input); -void sway_input_manager_apply_config(struct sway_input_manager *input, - struct input_config *config); +void sway_input_manager_apply_input_config(struct sway_input_manager *input, + struct input_config *input_config); + +void sway_input_manager_apply_seat_config(struct sway_input_manager *input, + struct seat_config *seat_config); #endif diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index 881805b4..89cde3fa 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h @@ -1,15 +1,18 @@ #include "sway/input/seat.h" struct sway_keyboard { - struct sway_seat *seat; - struct sway_input_device *device; + struct sway_seat_device *seat_device; struct wl_list link; // sway_seat::keyboards + struct xkb_keymap *keymap; + struct wl_listener keyboard_key; struct wl_listener keyboard_modifiers; }; struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, - struct sway_input_device *device); + struct sway_seat_device *device); + +void sway_keyboard_configure(struct sway_keyboard *keyboard); void sway_keyboard_destroy(struct sway_keyboard *keyboard); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index bd94a357..db69f83e 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -4,16 +4,25 @@ #include #include "sway/input/input-manager.h" +struct sway_seat_device { + struct sway_seat *sway_seat; + struct sway_input_device *input_device; + struct sway_keyboard *keyboard; + struct seat_attachment_config *attachment_config; + struct wl_list link; // sway_seat::devices +}; + struct sway_seat { - struct wlr_seat *seat; + struct wlr_seat *wlr_seat; + struct seat_config *config; struct sway_cursor *cursor; struct sway_input_manager *input; swayc_t *focus; - list_t *devices; - struct wl_listener focus_destroy; + struct wl_list devices; // sway_seat_device::link + struct wl_list link; // input_manager::seats }; @@ -23,6 +32,9 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, void sway_seat_add_device(struct sway_seat *seat, struct sway_input_device *device); +void sway_seat_configure_device(struct sway_seat *seat, + struct sway_input_device *device); + void sway_seat_remove_device(struct sway_seat *seat, struct sway_input_device *device); @@ -30,4 +42,6 @@ void sway_seat_configure_xcursor(struct sway_seat *seat); void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); +void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); + #endif diff --git a/sway/commands.c b/sway/commands.c index 6645436a..e003e06d 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -71,7 +71,24 @@ void input_cmd_apply(struct input_config *input) { } current_input_config = input; - sway_input_manager_apply_config(input_manager, input); + sway_input_manager_apply_input_config(input_manager, input); +} + +void seat_cmd_apply(struct seat_config *seat) { + int i; + i = list_seq_find(config->seat_configs, seat_name_cmp, seat->name); + if (i >= 0) { + // merge existing config + struct seat_config *sc = config->seat_configs->items[i]; + merge_seat_config(sc, seat); + free_seat_config(seat); + seat = sc; + } else { + list_add(config->seat_configs, seat); + } + + current_seat_config = seat; + sway_input_manager_apply_seat_config(input_manager, seat); } /** @@ -115,6 +132,7 @@ static struct cmd_handler handlers[] = { { "exit", cmd_exit }, { "include", cmd_include }, { "input", cmd_input }, + { "seat", cmd_seat }, }; static int handler_compare(const void *_a, const void *_b) { @@ -135,19 +153,27 @@ static struct cmd_handler input_handlers[] = { { "natural_scroll", input_cmd_natural_scroll }, { "pointer_accel", input_cmd_pointer_accel }, { "scroll_method", input_cmd_scroll_method }, - { "seat", input_cmd_seat }, { "tap", input_cmd_tap }, }; +// must be in order for the bsearch +static struct cmd_handler seat_handlers[] = { + { "attach", seat_cmd_attach }, +}; + static struct cmd_handler *find_handler(char *line, enum cmd_status block) { struct cmd_handler d = { .command=line }; struct cmd_handler *res = NULL; - sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_INPUT); + sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); if (block == CMD_BLOCK_INPUT) { res = bsearch(&d, input_handlers, sizeof(input_handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); + } else if (block == CMD_BLOCK_SEAT) { + res = bsearch(&d, seat_handlers, + sizeof(seat_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); } else { res = bsearch(&d, handlers, sizeof(handlers) / sizeof(struct cmd_handler), diff --git a/sway/commands/input/seat.c b/sway/commands/input/seat.c deleted file mode 100644 index 9d86ac0e..00000000 --- a/sway/commands/input/seat.c +++ /dev/null @@ -1,28 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include "sway/commands.h" -#include "sway/input/input-manager.h" -#include "log.h" - -struct cmd_results *input_cmd_seat(int argc, char **argv) { - sway_log(L_DEBUG, "seat for device: %d %s", - current_input_config==NULL, current_input_config->identifier); - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "seat", - "No input device defined."); - } - struct input_config *new_config = - new_input_config(current_input_config->identifier); - - // TODO validate seat name - free(new_config->seat); - new_config->seat = strdup(argv[0]); - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/commands/seat.c b/sway/commands/seat.c new file mode 100644 index 00000000..4f9e259b --- /dev/null +++ b/sway/commands/seat.c @@ -0,0 +1,35 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *cmd_seat(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 2))) { + return error; + } + + if (config->reading && strcmp("{", argv[1]) == 0) { + current_seat_config = new_seat_config(argv[0]); + sway_log(L_DEBUG, "entering seat block: %s", current_seat_config->name); + return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); + } + + if (argc > 2) { + int argc_new = argc-2; + char **argv_new = argv+2; + + struct cmd_results *res; + current_seat_config = new_seat_config(argv[0]); + if (strcasecmp("attach", argv[1]) == 0) { + res = seat_cmd_attach(argc_new, argv_new); + } else { + res = cmd_results_new(CMD_INVALID, "seat ", "Unknown command %s", argv[1]); + } + current_seat_config = NULL; + return res; + } + + return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); +} diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c new file mode 100644 index 00000000..996c1bda --- /dev/null +++ b/sway/commands/seat/attach.c @@ -0,0 +1,26 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include "sway/input/input-manager.h" +#include "sway/commands.h" +#include "sway/config.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *seat_cmd_attach(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "attach", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_seat_config) { + return cmd_results_new(CMD_FAILURE, "attach", "No seat defined"); + } + + struct seat_config *new_config = new_seat_config(current_seat_config->name); + struct seat_attachment_config *new_attachment = seat_attachment_config_new(); + new_attachment->identifier = strdup(argv[0]); + list_add(new_config->attachments, new_attachment); + + seat_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index b77b8b4b..52633ad8 100644 --- a/sway/config.c +++ b/sway/config.c @@ -45,6 +45,7 @@ static void config_defaults(struct sway_config *config) { if (!(config->criteria = create_list())) goto cleanup; if (!(config->no_focus = create_list())) goto cleanup; if (!(config->input_configs = create_list())) goto cleanup; + if (!(config->seat_configs = create_list())) goto cleanup; if (!(config->output_configs = create_list())) goto cleanup; if (!(config->cmd_queue = create_list())) goto cleanup; @@ -258,9 +259,7 @@ struct input_config *new_input_config(const char* identifier) { void merge_input_config(struct input_config *dst, struct input_config *src) { if (src->identifier) { - if (dst->identifier) { - free(dst->identifier); - } + free(dst->identifier); dst->identifier = strdup(src->identifier); } if (src->accel_profile != INT_MIN) { @@ -300,7 +299,6 @@ void free_input_config(struct input_config *ic) { return; } free(ic->identifier); - free(ic->seat); free(ic); } @@ -310,6 +308,128 @@ int input_identifier_cmp(const void *item, const void *data) { return strcmp(ic->identifier, identifier); } +struct seat_config *new_seat_config(const char* name) { + struct seat_config *seat = calloc(1, sizeof(struct seat_config)); + if (!seat) { + sway_log(L_DEBUG, "Unable to allocate seat config"); + return NULL; + } + + sway_log(L_DEBUG, "new_seat_config(%s)", name); + seat->name = strdup(name); + if (!sway_assert(seat->name, "could not allocate name for seat")) { + return NULL; + } + + seat->attachments = create_list(); + if (!sway_assert(seat->attachments, + "could not allocate seat attachments list")) { + return NULL; + } + + return seat; +} + +struct seat_attachment_config *seat_attachment_config_new() { + struct seat_attachment_config *attachment = + calloc(1, sizeof(struct seat_attachment_config)); + if (!attachment) { + sway_log(L_DEBUG, "cannot allocate attachment config"); + return NULL; + } + return attachment; +} + +static void seat_attachment_config_free( + struct seat_attachment_config *attachment) { + free(attachment->identifier); + free(attachment); + return; +} + +static struct seat_attachment_config *seat_attachment_config_copy( + struct seat_attachment_config *attachment) { + struct seat_attachment_config *copy = seat_attachment_config_new(); + if (!copy) { + return NULL; + } + + copy->identifier = strdup(attachment->identifier); + + return copy; +} + +static void merge_seat_attachment_config(struct seat_attachment_config *dest, + struct seat_attachment_config *source) { + // nothing to merge yet, but there will be some day +} + +void merge_seat_config(struct seat_config *dest, struct seat_config *source) { + if (source->name) { + free(dest->name); + dest->name = strdup(source->name); + } + + for (int i = 0; i < source->attachments->length; ++i) { + struct seat_attachment_config *source_attachment = + source->attachments->items[i]; + bool found = false; + for (int j = 0; j < dest->attachments->length; ++j) { + struct seat_attachment_config *dest_attachment = + dest->attachments->items[j]; + if (strcmp(source_attachment->identifier, + dest_attachment->identifier) == 0) { + merge_seat_attachment_config(dest_attachment, + source_attachment); + found = true; + } + } + + if (!found) { + struct seat_attachment_config *copy = + seat_attachment_config_copy(source_attachment); + if (copy) { + list_add(dest->attachments, copy); + } + } + } +} + +void free_seat_config(struct seat_config *seat) { + if (!seat) { + return; + } + + free(seat->name); + for (int i = 0; i < seat->attachments->length; ++i) { + struct seat_attachment_config *attachment = + seat->attachments->items[i]; + seat_attachment_config_free(attachment); + } + + list_free(seat->attachments); + free(seat); +} + +int seat_name_cmp(const void *item, const void *data) { + const struct seat_config *sc = item; + const char *name = data; + return strcmp(sc->name, name); +} + +struct seat_attachment_config *seat_config_get_attachment( + struct seat_config *seat_config, char *identifier) { + for (int i = 0; i < seat_config->attachments->length; ++i) { + struct seat_attachment_config *attachment = + seat_config->attachments->items[i]; + if (strcmp(attachment->identifier, identifier) == 0) { + return attachment; + } + } + + return NULL; +} + bool load_main_config(const char *file, bool is_active) { char *path; if (file != NULL) { @@ -368,7 +488,7 @@ bool load_main_config(const char *file, bool is_active) { char *_path = secconfigs->items[i]; if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && - (s.st_mode & 0777) != 0444)) { + (s.st_mode & 0777) != 0444)) { sway_log(L_ERROR, "Refusing to load %s - it must be owned by root " "and mode 644 or 444", _path); @@ -547,6 +667,14 @@ bool read_config(FILE *file, struct sway_config *config) { } break; + case CMD_BLOCK_SEAT: + if (block == CMD_BLOCK_END) { + block = CMD_BLOCK_SEAT; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + case CMD_BLOCK_BAR: if (block == CMD_BLOCK_END) { block = CMD_BLOCK_BAR; @@ -601,6 +729,12 @@ bool read_config(FILE *file, struct sway_config *config) { block = CMD_BLOCK_END; break; + case CMD_BLOCK_SEAT: + sway_log(L_DEBUG, "End of seat block"); + current_seat_config = NULL; + block = CMD_BLOCK_END; + break; + case CMD_BLOCK_BAR: sway_log(L_DEBUG, "End of bar block"); config->current_bar = NULL; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 217c2ddb..3aa2d1bc 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -24,7 +24,7 @@ static void cursor_update_position(struct sway_cursor *cursor) { static void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time) { - struct wlr_seat *seat = cursor->seat->seat; + struct wlr_seat *seat = cursor->seat->wlr_seat; struct wlr_surface *surface = NULL; double sx, sy; swayc_t *swayc = @@ -72,7 +72,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { sway_seat_set_focus(cursor->seat, swayc); } - wlr_seat_pointer_notify_button(cursor->seat->seat, event->time_msec, + wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, event->button, event->state); } @@ -80,7 +80,7 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); struct wlr_event_pointer_axis *event = data; - wlr_seat_pointer_notify_axis(cursor->seat->seat, event->time_msec, + wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, event->orientation, event->delta); } @@ -173,7 +173,7 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { wl_signal_add(&wlr_cursor->events.tablet_tool_tip, &cursor->tool_tip); cursor->tool_tip.notify = handle_tool_tip; - wl_signal_add(&seat->seat->events.request_set_cursor, + wl_signal_add(&seat->wlr_seat->events.request_set_cursor, &cursor->request_set_cursor); cursor->request_set_cursor.notify = handle_request_set_cursor; diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index b07a733e..1950b6d9 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -18,12 +18,13 @@ static const char *default_seat = "seat0"; struct sway_input_manager *input_manager; struct input_config *current_input_config = NULL; +struct seat_config *current_seat_config = NULL; static struct sway_seat *input_manager_get_seat( struct sway_input_manager *input, const char *seat_name) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { - if (strcmp(seat->seat->name, seat_name) == 0) { + if (strcmp(seat->wlr_seat->name, seat_name) == 0) { return seat; } } @@ -58,56 +59,88 @@ static char *get_device_identifier(struct wlr_input_device *device) { return identifier; } -static struct sway_input_device *input_sway_device_from_wlr(struct sway_input_manager *input, - struct wlr_input_device *device) { - struct sway_input_device *sway_device = NULL; - wl_list_for_each(sway_device, &input->devices, link) { - if (sway_device->wlr_device == device) { - return sway_device; +static struct sway_input_device *input_sway_device_from_wlr( + struct sway_input_manager *input, struct wlr_input_device *device) { + struct sway_input_device *input_device = NULL; + wl_list_for_each(input_device, &input->devices, link) { + if (input_device->wlr_device == device) { + return input_device; } } return NULL; } -static struct sway_input_device *input_sway_device_from_config(struct sway_input_manager *input, - struct input_config *config) { - struct sway_input_device *sway_device = NULL; - wl_list_for_each(sway_device, &input->devices, link) { - if (strcmp(sway_device->identifier, config->identifier) == 0) { - return sway_device; +static struct sway_input_device *input_sway_device_from_config( + struct sway_input_manager *input, struct input_config *config) { + struct sway_input_device *input_device = NULL; + wl_list_for_each(input_device, &input->devices, link) { + if (strcmp(input_device->identifier, config->identifier) == 0) { + return input_device; } } return NULL; } +static struct sway_input_device *input_sway_device_from_identifier( + struct sway_input_manager *input, char *identifier) { + struct sway_input_device *input_device = NULL; + wl_list_for_each(input_device, &input->devices, link) { + if (strcmp(input_device->identifier, identifier) == 0) { + return input_device; + } + } + return NULL; +} + +static bool input_has_seat_configuration(struct sway_input_manager *input) { + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + if (seat->config) { + return true; + } + } + + return false; +} + static void input_add_notify(struct wl_listener *listener, void *data) { struct sway_input_manager *input = wl_container_of(listener, input, input_add); struct wlr_input_device *device = data; - struct sway_input_device *sway_device = + struct sway_input_device *input_device = calloc(1, sizeof(struct sway_input_device)); - if (!sway_assert(sway_device, "could not allocate input device")) { + if (!sway_assert(input_device, "could not allocate input device")) { return; } - sway_device->wlr_device = device; - sway_device->identifier = get_device_identifier(device); - wl_list_insert(&input->devices, &sway_device->link); + input_device->wlr_device = device; + input_device->identifier = get_device_identifier(device); + wl_list_insert(&input->devices, &input_device->link); // find config for (int i = 0; i < config->input_configs->length; ++i) { struct input_config *input_config = config->input_configs->items[i]; - if (strcmp(input_config->identifier, sway_device->identifier) == 0) { - sway_device->config = input_config; + if (strcmp(input_config->identifier, input_device->identifier) == 0) { + input_device->config = input_config; break; } } - const char *seat_name = - (sway_device->config ? sway_device->config->seat : default_seat); - struct sway_seat *seat = input_manager_get_seat(input, seat_name); - sway_seat_add_device(seat, sway_device); + struct sway_seat *seat = NULL; + if (!input_has_seat_configuration(input)) { + seat = input_manager_get_seat(input, default_seat); + sway_seat_add_device(seat, input_device); + return; + } + + wl_list_for_each(seat, &input->seats, link) { + if (seat->config && + (seat_config_get_attachment(seat->config, input_device->identifier) || + seat_config_get_attachment(seat->config, "*"))) { + sway_seat_add_device(seat, input_device); + } + } } static void input_remove_notify(struct wl_listener *listener, void *data) { @@ -115,21 +148,21 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { wl_container_of(listener, input, input_remove); struct wlr_input_device *device = data; - struct sway_input_device *sway_device = + struct sway_input_device *input_device = input_sway_device_from_wlr(input, device); - if (!sway_assert(sway_device, "could not find sway device")) { + if (!sway_assert(input_device, "could not find sway device")) { return; } struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { - sway_seat_remove_device(seat, sway_device); + sway_seat_remove_device(seat, input_device); } - wl_list_remove(&sway_device->link); - free(sway_device->identifier); - free(sway_device); + wl_list_remove(&input_device->link); + free(input_device->identifier); + free(input_device); } struct sway_input_manager *sway_input_manager_create( @@ -139,7 +172,6 @@ struct sway_input_manager *sway_input_manager_create( if (!input) { return NULL; } - // XXX probably don't need the full server input->server = server; wl_list_init(&input->devices); @@ -177,22 +209,53 @@ void sway_input_manager_set_focus(struct sway_input_manager *input, } } -void sway_input_manager_apply_config(struct sway_input_manager *input, +void sway_input_manager_apply_input_config(struct sway_input_manager *input, struct input_config *input_config) { - struct sway_input_device *sway_device = + struct sway_input_device *input_device = input_sway_device_from_config(input, input_config); - if (!sway_device) { + if (!input_device) { return; } + input_device->config = input_config; struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { - sway_seat_remove_device(seat, sway_device); + sway_seat_configure_device(seat, input_device); + } +} + +void sway_input_manager_apply_seat_config(struct sway_input_manager *input, + struct seat_config *seat_config) { + struct sway_seat *seat = input_manager_get_seat(input, seat_config->name); + // the old config is invalid so clear it + sway_seat_set_config(seat, NULL); + + // clear devices + struct sway_input_device *input_device = NULL; + wl_list_for_each(input_device, &input->devices, link) { + sway_seat_remove_device(seat, input_device); + } + + if (seat_config_get_attachment(seat_config, "*")) { + wl_list_for_each(input_device, &input->devices, link) { + sway_seat_add_device(seat, input_device); + } + } else { + for (int i = 0; i < seat_config->attachments->length; ++i) { + struct seat_attachment_config *attachment = + seat_config->attachments->items[i]; + + struct sway_input_device *device = + input_sway_device_from_identifier(input, + attachment->identifier); + + if (device) { + sway_seat_add_device(seat, device); + } + } } - const char *seat_name = (input_config->seat ? input_config->seat : default_seat); - seat = input_manager_get_seat(input, seat_name); - sway_seat_add_device(seat, sway_device); + sway_seat_set_config(seat, seat_config); } void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 6a792c65..53db3270 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -5,32 +5,46 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { struct sway_keyboard *keyboard = wl_container_of(listener, keyboard, keyboard_key); + struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; + struct wlr_input_device *wlr_device = + keyboard->seat_device->input_device->wlr_device; struct wlr_event_keyboard_key *event = data; - wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device->wlr_device); - wlr_seat_keyboard_notify_key(keyboard->seat->seat, event->time_msec, - event->keycode, event->state); + wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); + wlr_seat_set_keyboard(wlr_seat, wlr_device); + wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,event->keycode, + event->state); } static void handle_keyboard_modifiers(struct wl_listener *listener, void *data) { struct sway_keyboard *keyboard = wl_container_of(listener, keyboard, keyboard_modifiers); - wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device->wlr_device); - wlr_seat_keyboard_notify_modifiers(keyboard->seat->seat); + struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; + struct wlr_input_device *wlr_device = + keyboard->seat_device->input_device->wlr_device; + wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); + wlr_seat_set_keyboard(wlr_seat, wlr_device); + wlr_seat_keyboard_notify_modifiers(wlr_seat); } struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, - struct sway_input_device *device) { + struct sway_seat_device *device) { struct sway_keyboard *keyboard = calloc(1, sizeof(struct sway_keyboard)); if (!sway_assert(keyboard, "could not allocate sway keyboard")) { return NULL; } - keyboard->device = device; - keyboard->seat = seat; + keyboard->seat_device = device; + device->keyboard = keyboard; - // TODO keyboard config + wl_list_init(&keyboard->keyboard_key.link); + wl_list_init(&keyboard->keyboard_modifiers.link); + + return keyboard; +} + +void sway_keyboard_configure(struct sway_keyboard *keyboard) { struct xkb_rule_names rules; memset(&rules, 0, sizeof(rules)); rules.rules = getenv("XKB_DEFAULT_RULES"); @@ -38,27 +52,32 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, rules.layout = getenv("XKB_DEFAULT_LAYOUT"); rules.variant = getenv("XKB_DEFAULT_VARIANT"); rules.options = getenv("XKB_DEFAULT_OPTIONS"); + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!sway_assert(context, "cannot create XKB context")) { - return NULL; + return; } - wlr_keyboard_set_keymap(device->wlr_device->keyboard, - xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS)); + keyboard->keymap = + xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + wlr_keyboard_set_keymap(keyboard->seat_device->input_device->wlr_device->keyboard, keyboard->keymap); xkb_context_unref(context); - wl_signal_add(&device->wlr_device->keyboard->events.key, + wl_list_remove(&keyboard->keyboard_key.link); + wl_signal_add( + &keyboard->seat_device->input_device->wlr_device->keyboard->events.key, &keyboard->keyboard_key); keyboard->keyboard_key.notify = handle_keyboard_key; - wl_signal_add(&device->wlr_device->keyboard->events.modifiers, + wl_list_remove(&keyboard->keyboard_modifiers.link); + wl_signal_add( + &keyboard->seat_device->input_device->wlr_device->keyboard->events.modifiers, &keyboard->keyboard_modifiers); keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; - - return keyboard; } void sway_keyboard_destroy(struct sway_keyboard *keyboard) { + xkb_keymap_unref(keyboard->keymap); wl_list_remove(&keyboard->keyboard_key.link); wl_list_remove(&keyboard->keyboard_modifiers.link); wl_list_remove(&keyboard->link); diff --git a/sway/input/seat.c b/sway/input/seat.c index 80c6424f..1b25419b 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -9,6 +9,18 @@ #include "sway/view.h" #include "log.h" +static void seat_device_destroy(struct sway_seat_device *seat_device) { + if (!seat_device) { + return; + } + + sway_keyboard_destroy(seat_device->keyboard); + wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, + seat_device->input_device->wlr_device); + wl_list_remove(&seat_device->link); + free(seat_device); +} + struct sway_seat *sway_seat_create(struct sway_input_manager *input, const char *seat_name) { struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); @@ -16,22 +28,22 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, return NULL; } - seat->seat = wlr_seat_create(input->server->wl_display, seat_name); - if (!sway_assert(seat->seat, "could not allocate seat")) { + seat->wlr_seat = wlr_seat_create(input->server->wl_display, seat_name); + if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { return NULL; } seat->cursor = sway_cursor_create(seat); if (!seat->cursor) { - wlr_seat_destroy(seat->seat); + wlr_seat_destroy(seat->wlr_seat); free(seat); return NULL; } seat->input = input; - seat->devices = create_list(); + wl_list_init(&seat->devices); - wlr_seat_set_capabilities(seat->seat, + wlr_seat_set_capabilities(seat->wlr_seat, WL_SEAT_CAPABILITY_KEYBOARD | WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH); @@ -43,88 +55,94 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, return seat; } -static void seat_add_pointer(struct sway_seat *seat, - struct sway_input_device *sway_device) { +static void seat_configure_pointer(struct sway_seat *seat, + struct sway_seat_device *sway_device) { // TODO pointer configuration wlr_cursor_attach_input_device(seat->cursor->cursor, - sway_device->wlr_device); + sway_device->input_device->wlr_device); } -static void seat_add_keyboard(struct sway_seat *seat, - struct sway_input_device *device) { - // TODO keyboard configuration - sway_keyboard_create(seat, device); - wlr_seat_set_keyboard(seat->seat, device->wlr_device); +static void seat_configure_keyboard(struct sway_seat *seat, + struct sway_seat_device *seat_device) { + if (!seat_device->keyboard) { + sway_keyboard_create(seat, seat_device); + } + sway_keyboard_configure(seat_device->keyboard); } -bool sway_seat_has_device(struct sway_seat *seat, - struct sway_input_device *device) { - return false; +static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, + struct sway_input_device *input_device) { + struct sway_seat_device *seat_device = NULL; + wl_list_for_each(seat_device, &seat->devices, link) { + if (seat_device->input_device == input_device) { + return seat_device; + } + } + + return NULL; } -void sway_seat_add_device(struct sway_seat *seat, - struct sway_input_device *device) { - if (sway_seat_has_device(seat, device)) { +void sway_seat_configure_device(struct sway_seat *seat, + struct sway_input_device *input_device) { + struct sway_seat_device *seat_device = + sway_seat_get_device(seat, input_device); + if (!seat_device) { return; } - sway_log(L_DEBUG, "input add: %s", device->identifier); - switch (device->wlr_device->type) { + if (seat->config) { + seat_device->attachment_config = + seat_config_get_attachment(seat->config, input_device->identifier); + } + + switch (input_device->wlr_device->type) { case WLR_INPUT_DEVICE_POINTER: - seat_add_pointer(seat, device); + seat_configure_pointer(seat, seat_device); break; case WLR_INPUT_DEVICE_KEYBOARD: - seat_add_keyboard(seat, device); + seat_configure_keyboard(seat, seat_device); + wlr_seat_set_keyboard(seat->wlr_seat, + seat_device->input_device->wlr_device); break; case WLR_INPUT_DEVICE_TOUCH: case WLR_INPUT_DEVICE_TABLET_PAD: case WLR_INPUT_DEVICE_TABLET_TOOL: - sway_log(L_DEBUG, "TODO: add other devices"); + sway_log(L_DEBUG, "TODO: configure other devices"); break; } - - list_add(seat->devices, device); } -static void seat_remove_keyboard(struct sway_seat *seat, - struct sway_input_device *device) { - if (device && device->keyboard) { - sway_keyboard_destroy(device->keyboard); +void sway_seat_add_device(struct sway_seat *seat, + struct sway_input_device *input_device) { + if (sway_seat_get_device(seat, input_device)) { + return; } -} -static void seat_remove_pointer(struct sway_seat *seat, - struct sway_input_device *device) { - wlr_cursor_detach_input_device(seat->cursor->cursor, device->wlr_device); + struct sway_seat_device *seat_device = + calloc(1, sizeof(struct sway_seat_device)); + if (!seat_device) { + sway_log(L_DEBUG, "could not allocate seat device"); + return; + } + + seat_device->sway_seat = seat; + seat_device->input_device = input_device; + wl_list_insert(&seat->devices, &seat_device->link); + + sway_seat_configure_device(seat, input_device); } void sway_seat_remove_device(struct sway_seat *seat, - struct sway_input_device *device) { - sway_log(L_DEBUG, "input remove: %s", device->identifier); - if (!sway_seat_has_device(seat, device)) { - return; - } + struct sway_input_device *input_device) { + sway_log(L_DEBUG, "input remove: %s", input_device->identifier); + struct sway_seat_device *seat_device = + sway_seat_get_device(seat, input_device); - switch (device->wlr_device->type) { - case WLR_INPUT_DEVICE_POINTER: - seat_remove_pointer(seat, device); - break; - case WLR_INPUT_DEVICE_KEYBOARD: - seat_remove_keyboard(seat, device); - break; - case WLR_INPUT_DEVICE_TOUCH: - case WLR_INPUT_DEVICE_TABLET_PAD: - case WLR_INPUT_DEVICE_TABLET_TOOL: - sway_log(L_DEBUG, "TODO: remove other devices"); - break; + if (!seat_device) { + return; } - for (int i = 0; i < seat->devices->length; ++i) { - if (seat->devices->items[i] == device) { - list_del(seat->devices, i); - break; - } - } + seat_device_destroy(seat_device); } void sway_seat_configure_xcursor(struct sway_seat *seat) { @@ -135,7 +153,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->xcursor_manager = wlr_xcursor_manager_create("default", 24); if (sway_assert(seat->cursor->xcursor_manager, - "Cannot create XCursor manager for theme %s", cursor_theme)) { + "Cannot create XCursor manager for theme %s", + cursor_theme)) { return; } } @@ -183,7 +202,7 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { view->iface.set_activated(view, true); wl_signal_add(&container->events.destroy, &seat->focus_destroy); seat->focus_destroy.notify = handle_focus_destroy; - wlr_seat_keyboard_notify_enter(seat->seat, view->surface); + wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface); } seat->focus = container; @@ -195,3 +214,29 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { } } + +void sway_seat_set_config(struct sway_seat *seat, + struct seat_config *seat_config) { + // clear configs + seat->config = NULL; + + struct sway_seat_device *seat_device = NULL; + wl_list_for_each(seat_device, &seat->devices, link) { + seat_device->attachment_config = NULL; + } + + if (!seat_config) { + return; + } + + // add configs + seat->config = seat_config; + + wl_list_for_each(seat_device, &seat->devices, link) { + seat_device->attachment_config = + seat_config_get_attachment(seat_config, + seat_device->input_device->identifier); + sway_seat_configure_device(seat, seat_device->input_device); + } + +} diff --git a/sway/meson.build b/sway/meson.build index fad1f88c..ad8160eb 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -11,7 +11,8 @@ sway_sources = files( 'commands/exec_always.c', 'commands/include.c', 'commands/input.c', - 'commands/input/seat.c', + 'commands/seat.c', + 'commands/seat/attach.c', 'commands/input/accel_profile.c', 'commands/input/click_method.c', 'commands/input/drag_lock.c', -- cgit v1.2.3 From 9eecbb5d8a988a0dded57ead1982dd0121071454 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 15 Dec 2017 05:22:51 -0500 Subject: xkb config --- include/sway/commands.h | 5 +++++ include/sway/config.h | 6 ++++++ sway/commands.c | 5 +++++ sway/commands/input/xkb_layout.c | 24 ++++++++++++++++++++++++ sway/commands/input/xkb_model.c | 24 ++++++++++++++++++++++++ sway/commands/input/xkb_options.c | 24 ++++++++++++++++++++++++ sway/commands/input/xkb_rules.c | 24 ++++++++++++++++++++++++ sway/commands/input/xkb_variant.c | 24 ++++++++++++++++++++++++ sway/config.c | 20 ++++++++++++++++++++ sway/input/keyboard.c | 38 +++++++++++++++++++++++++++++++++----- sway/main.c | 1 + sway/meson.build | 5 +++++ 12 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 sway/commands/input/xkb_layout.c create mode 100644 sway/commands/input/xkb_model.c create mode 100644 sway/commands/input/xkb_options.c create mode 100644 sway/commands/input/xkb_rules.c create mode 100644 sway/commands/input/xkb_variant.c (limited to 'include/sway/config.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index ce74e1ed..61950d0d 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -195,6 +195,11 @@ sway_cmd input_cmd_natural_scroll; sway_cmd input_cmd_pointer_accel; sway_cmd input_cmd_scroll_method; sway_cmd input_cmd_tap; +sway_cmd input_cmd_xkb_layout; +sway_cmd input_cmd_xkb_model; +sway_cmd input_cmd_xkb_options; +sway_cmd input_cmd_xkb_rules; +sway_cmd input_cmd_xkb_variant; sway_cmd seat_cmd_attach; diff --git a/include/sway/config.h b/include/sway/config.h index 5df5d61e..9bfda259 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -67,6 +67,12 @@ struct input_config { int send_events; int tap; + char *xkb_layout; + char *xkb_model; + char *xkb_options; + char *xkb_rules; + char *xkb_variant; + bool capturable; struct wlr_box region; }; diff --git a/sway/commands.c b/sway/commands.c index e003e06d..b8948fb7 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -154,6 +154,11 @@ static struct cmd_handler input_handlers[] = { { "pointer_accel", input_cmd_pointer_accel }, { "scroll_method", input_cmd_scroll_method }, { "tap", input_cmd_tap }, + { "xkb_layout", input_cmd_xkb_layout }, + { "xkb_model", input_cmd_xkb_model }, + { "xkb_options", input_cmd_xkb_options }, + { "xkb_rules", input_cmd_xkb_rules }, + { "xkb_variant", input_cmd_xkb_variant }, }; // must be in order for the bsearch diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c new file mode 100644 index 00000000..9a9ce044 --- /dev/null +++ b/sway/commands/input/xkb_layout.c @@ -0,0 +1,24 @@ +#define _XOPEN_SOURCE 700 +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { + sway_log(L_DEBUG, "xkb layout for device: %s", current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "xkb_layout", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "xkb_layout", "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + new_config->xkb_layout = strdup(argv[0]); + + sway_log(L_DEBUG, "apply-xkb_layout for device: %s", + current_input_config->identifier); + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c new file mode 100644 index 00000000..14a50ffb --- /dev/null +++ b/sway/commands/input/xkb_model.c @@ -0,0 +1,24 @@ +#define _XOPEN_SOURCE 700 +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { + sway_log(L_DEBUG, "xkb model for device: %s", current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "xkb_model", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "xkb_model", "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + new_config->xkb_model = strdup(argv[0]); + + sway_log(L_DEBUG, "apply-xkb_model for device: %s", + current_input_config->identifier); + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c new file mode 100644 index 00000000..67eb5342 --- /dev/null +++ b/sway/commands/input/xkb_options.c @@ -0,0 +1,24 @@ +#define _XOPEN_SOURCE 700 +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { + sway_log(L_DEBUG, "xkb options for device: %s", current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "xkb_options", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "xkb_options", "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + new_config->xkb_options = strdup(argv[0]); + + sway_log(L_DEBUG, "apply-xkb_options for device: %s", + current_input_config->identifier); + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c new file mode 100644 index 00000000..3eda0bdd --- /dev/null +++ b/sway/commands/input/xkb_rules.c @@ -0,0 +1,24 @@ +#define _XOPEN_SOURCE 700 +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { + sway_log(L_DEBUG, "xkb rules for device: %s", current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "xkb_rules", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "xkb_rules", "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + new_config->xkb_rules = strdup(argv[0]); + + sway_log(L_DEBUG, "apply-xkb_rules for device: %s", + current_input_config->identifier); + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c new file mode 100644 index 00000000..c7f93ad4 --- /dev/null +++ b/sway/commands/input/xkb_variant.c @@ -0,0 +1,24 @@ +#define _XOPEN_SOURCE 700 +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { + sway_log(L_DEBUG, "xkb variant for device: %s", current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "xkb_variant", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "xkb_variant", "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + new_config->xkb_variant = strdup(argv[0]); + + sway_log(L_DEBUG, "apply-xkb_variant for device: %s", + current_input_config->identifier); + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 52633ad8..4e34aa8c 100644 --- a/sway/config.c +++ b/sway/config.c @@ -292,6 +292,26 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { if (src->tap != INT_MIN) { dst->tap = src->tap; } + if (src->xkb_layout) { + free(dst->xkb_layout); + dst->xkb_layout = strdup(src->xkb_layout); + } + if (src->xkb_model) { + free(dst->xkb_model); + dst->xkb_model = strdup(src->xkb_model); + } + if (src->xkb_options) { + free(dst->xkb_options); + dst->xkb_options = strdup(src->xkb_options); + } + if (src->xkb_rules) { + free(dst->xkb_rules); + dst->xkb_rules = strdup(src->xkb_rules); + } + if (src->xkb_variant) { + free(dst->xkb_variant); + dst->xkb_variant = strdup(src->xkb_variant); + } } void free_input_config(struct input_config *ic) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 53db3270..2ab0206a 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -1,5 +1,6 @@ #include "sway/input/seat.h" #include "sway/input/keyboard.h" +#include "sway/input/input-manager.h" #include "log.h" static void handle_keyboard_key(struct wl_listener *listener, void *data) { @@ -47,17 +48,44 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, void sway_keyboard_configure(struct sway_keyboard *keyboard) { struct xkb_rule_names rules; memset(&rules, 0, sizeof(rules)); - rules.rules = getenv("XKB_DEFAULT_RULES"); - rules.model = getenv("XKB_DEFAULT_MODEL"); - rules.layout = getenv("XKB_DEFAULT_LAYOUT"); - rules.variant = getenv("XKB_DEFAULT_VARIANT"); - rules.options = getenv("XKB_DEFAULT_OPTIONS"); + struct input_config *input_config = + keyboard->seat_device->input_device->config; + + if (input_config && input_config->xkb_layout) { + rules.layout = input_config->xkb_layout; + } else { + rules.layout = getenv("XKB_DEFAULT_LAYOUT"); + } + if (input_config && input_config->xkb_model) { + rules.model = input_config->xkb_model; + } else { + rules.model = getenv("XKB_DEFAULT_MODEL"); + } + + if (input_config && input_config->xkb_options) { + rules.options = input_config->xkb_options; + } else { + rules.options = getenv("XKB_DEFAULT_OPTIONS"); + } + + if (input_config && input_config->xkb_rules) { + rules.rules = input_config->xkb_rules; + } else { + rules.rules = getenv("XKB_DEFAULT_RULES"); + } + + if (input_config && input_config->xkb_variant) { + rules.variant = input_config->xkb_variant; + } else { + rules.variant = getenv("XKB_DEFAULT_VARIANT"); + } struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!sway_assert(context, "cannot create XKB context")) { return; } + xkb_keymap_unref(keyboard->keymap); keyboard->keymap = xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); wlr_keyboard_set_keymap(keyboard->seat_device->input_device->wlr_device->keyboard, keyboard->keymap); diff --git a/sway/main.c b/sway/main.c index 363f4d96..25032aa0 100644 --- a/sway/main.c +++ b/sway/main.c @@ -158,6 +158,7 @@ static void log_distro() { } static void log_kernel() { + return; FILE *f = popen("uname -a", "r"); if (!f) { sway_log(L_INFO, "Unable to determine kernel version"); diff --git a/sway/meson.build b/sway/meson.build index ad8160eb..c81e1c2c 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -24,6 +24,11 @@ sway_sources = files( 'commands/input/pointer_accel.c', 'commands/input/scroll_method.c', 'commands/input/tap.c', + 'commands/input/xkb_layout.c', + 'commands/input/xkb_model.c', + 'commands/input/xkb_options.c', + 'commands/input/xkb_rules.c', + 'commands/input/xkb_variant.c', 'config.c', 'ipc-json.c', 'ipc-server.c', -- cgit v1.2.3 From f16aa3c0ad8328da0820e81c99a619835f36082f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 12:14:24 -0500 Subject: rename config apply cmds --- include/sway/commands.h | 3 --- include/sway/config.h | 2 ++ sway/commands.c | 4 ++-- sway/commands/input/accel_profile.c | 3 ++- sway/commands/input/click_method.c | 3 ++- sway/commands/input/drag_lock.c | 3 ++- sway/commands/input/dwt.c | 3 ++- sway/commands/input/events.c | 3 ++- sway/commands/input/left_handed.c | 3 ++- sway/commands/input/middle_emulation.c | 3 ++- sway/commands/input/natural_scroll.c | 3 ++- sway/commands/input/pointer_accel.c | 3 ++- sway/commands/input/scroll_method.c | 3 ++- sway/commands/input/tap.c | 3 ++- sway/commands/input/xkb_layout.c | 3 ++- sway/commands/input/xkb_model.c | 3 ++- sway/commands/input/xkb_options.c | 3 ++- sway/commands/input/xkb_rules.c | 3 ++- sway/commands/input/xkb_variant.c | 3 ++- sway/commands/seat/attach.c | 2 +- 20 files changed, 37 insertions(+), 22 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index 61950d0d..5008831d 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -42,9 +42,6 @@ enum expected_args { EXPECTED_EQUAL_TO }; -void input_cmd_apply(struct input_config *input); -void seat_cmd_apply(struct seat_config *seat); - struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val); diff --git a/include/sway/config.h b/include/sway/config.h index 777fb5a8..eb642dc2 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -384,6 +384,7 @@ int input_identifier_cmp(const void *item, const void *data); struct input_config *new_input_config(const char* identifier); void merge_input_config(struct input_config *dst, struct input_config *src); void free_input_config(struct input_config *ic); +void apply_input_config(struct input_config *input); int seat_name_cmp(const void *item, const void *data); struct seat_config *new_seat_config(const char* name); @@ -392,6 +393,7 @@ void free_seat_config(struct seat_config *ic); struct seat_attachment_config *seat_attachment_config_new(); struct seat_attachment_config *seat_config_get_attachment( struct seat_config *seat_config, char *identifier); +void apply_seat_config(struct seat_config *seat); int output_name_cmp(const void *item, const void *data); struct output_config *new_output_config(); diff --git a/sway/commands.c b/sway/commands.c index 7485f2f6..3fb1842d 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -57,7 +57,7 @@ struct cmd_results *checkarg(int argc, const char *name, enum expected_args type return error; } -void input_cmd_apply(struct input_config *input) { +void apply_input_config(struct input_config *input) { int i; i = list_seq_find(config->input_configs, input_identifier_cmp, input->identifier); if (i >= 0) { @@ -74,7 +74,7 @@ void input_cmd_apply(struct input_config *input) { sway_input_manager_apply_input_config(input_manager, input); } -void seat_cmd_apply(struct seat_config *seat) { +void apply_seat_config(struct seat_config *seat) { int i; i = list_seq_find(config->seat_configs, seat_name_cmp, seat->name); if (i >= 0) { diff --git a/sway/commands/input/accel_profile.c b/sway/commands/input/accel_profile.c index 9b5fb7a2..f72b7d48 100644 --- a/sway/commands/input/accel_profile.c +++ b/sway/commands/input/accel_profile.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" @@ -24,6 +25,6 @@ struct cmd_results *input_cmd_accel_profile(int argc, char **argv) { "Expected 'accel_profile '"); } - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/click_method.c b/sway/commands/input/click_method.c index a0e3bddf..dcf64c1a 100644 --- a/sway/commands/input/click_method.c +++ b/sway/commands/input/click_method.c @@ -1,6 +1,7 @@ #include #include #include "sway/commands.h" +#include "sway/config.h" #include "sway/input/input-manager.h" #include "log.h" @@ -29,6 +30,6 @@ struct cmd_results *input_cmd_click_method(int argc, char **argv) { "Expected 'click_method #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" @@ -24,6 +25,6 @@ struct cmd_results *input_cmd_drag_lock(int argc, char **argv) { "Expected 'drag_lock '"); } - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/dwt.c b/sway/commands/input/dwt.c index 0954575c..8108a110 100644 --- a/sway/commands/input/dwt.c +++ b/sway/commands/input/dwt.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" @@ -23,6 +24,6 @@ struct cmd_results *input_cmd_dwt(int argc, char **argv) { "Expected 'dwt '"); } - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c index f44c0ec7..8a74c11e 100644 --- a/sway/commands/input/events.c +++ b/sway/commands/input/events.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" #include "log.h" @@ -30,6 +31,6 @@ struct cmd_results *input_cmd_events(int argc, char **argv) { "Expected 'events '"); } - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/left_handed.c b/sway/commands/input/left_handed.c index dc8fcd56..35740df3 100644 --- a/sway/commands/input/left_handed.c +++ b/sway/commands/input/left_handed.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" @@ -24,6 +25,6 @@ struct cmd_results *input_cmd_left_handed(int argc, char **argv) { "Expected 'left_handed '"); } - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/middle_emulation.c b/sway/commands/input/middle_emulation.c index e19964d8..7bc08ae6 100644 --- a/sway/commands/input/middle_emulation.c +++ b/sway/commands/input/middle_emulation.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" @@ -25,6 +26,6 @@ struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) { "Expected 'middle_emulation '"); } - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/natural_scroll.c b/sway/commands/input/natural_scroll.c index 8272c5b3..a7dcdc2c 100644 --- a/sway/commands/input/natural_scroll.c +++ b/sway/commands/input/natural_scroll.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" @@ -24,6 +25,6 @@ struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) { "Expected 'natural_scroll '"); } - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/pointer_accel.c b/sway/commands/input/pointer_accel.c index 2c9db5bf..d2261a63 100644 --- a/sway/commands/input/pointer_accel.c +++ b/sway/commands/input/pointer_accel.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" @@ -22,6 +23,6 @@ struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { } new_config->pointer_accel = pointer_accel; - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/scroll_method.c b/sway/commands/input/scroll_method.c index 40277155..035262cf 100644 --- a/sway/commands/input/scroll_method.c +++ b/sway/commands/input/scroll_method.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" @@ -28,6 +29,6 @@ struct cmd_results *input_cmd_scroll_method(int argc, char **argv) { "Expected 'scroll_method '"); } - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c index 18a54087..8547c0cd 100644 --- a/sway/commands/input/tap.c +++ b/sway/commands/input/tap.c @@ -1,5 +1,6 @@ #include #include +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" #include "log.h" @@ -27,6 +28,6 @@ struct cmd_results *input_cmd_tap(int argc, char **argv) { sway_log(L_DEBUG, "apply-tap for device: %s", current_input_config->identifier); - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c index 9a9ce044..4470fb1d 100644 --- a/sway/commands/input/xkb_layout.c +++ b/sway/commands/input/xkb_layout.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" #include "log.h" @@ -19,6 +20,6 @@ struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { sway_log(L_DEBUG, "apply-xkb_layout for device: %s", current_input_config->identifier); - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c index 14a50ffb..167ce2e7 100644 --- a/sway/commands/input/xkb_model.c +++ b/sway/commands/input/xkb_model.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" #include "log.h" @@ -19,6 +20,6 @@ struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { sway_log(L_DEBUG, "apply-xkb_model for device: %s", current_input_config->identifier); - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c index 67eb5342..180f40d5 100644 --- a/sway/commands/input/xkb_options.c +++ b/sway/commands/input/xkb_options.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" #include "log.h" @@ -19,6 +20,6 @@ struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { sway_log(L_DEBUG, "apply-xkb_options for device: %s", current_input_config->identifier); - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c index 3eda0bdd..047e8c84 100644 --- a/sway/commands/input/xkb_rules.c +++ b/sway/commands/input/xkb_rules.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" #include "log.h" @@ -19,6 +20,6 @@ struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { sway_log(L_DEBUG, "apply-xkb_rules for device: %s", current_input_config->identifier); - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c index c7f93ad4..0e998457 100644 --- a/sway/commands/input/xkb_variant.c +++ b/sway/commands/input/xkb_variant.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" #include "log.h" @@ -19,6 +20,6 @@ struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { sway_log(L_DEBUG, "apply-xkb_variant for device: %s", current_input_config->identifier); - input_cmd_apply(new_config); + apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c index 996c1bda..80ec63ce 100644 --- a/sway/commands/seat/attach.c +++ b/sway/commands/seat/attach.c @@ -21,6 +21,6 @@ struct cmd_results *seat_cmd_attach(int argc, char **argv) { new_attachment->identifier = strdup(argv[0]); list_add(new_config->attachments, new_attachment); - seat_cmd_apply(new_config); + apply_seat_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -- cgit v1.2.3 From 88bcd43ebf59cfa03a9e9a158c6f7a258c1f7db2 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 17 Dec 2017 10:39:22 -0500 Subject: seat fallback config --- include/sway/commands.h | 1 + include/sway/config.h | 1 + sway/commands.c | 1 + sway/commands/seat.c | 2 ++ sway/commands/seat/fallback.c | 29 +++++++++++++++ sway/config/seat.c | 5 +++ sway/input/input-manager.c | 83 ++++++++++++++++++++++++++++++------------- sway/input/seat.c | 3 +- sway/meson.build | 1 + 9 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 sway/commands/seat/fallback.c (limited to 'include/sway/config.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index 5008831d..4ee7af2a 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -198,6 +198,7 @@ sway_cmd input_cmd_xkb_options; sway_cmd input_cmd_xkb_rules; sway_cmd input_cmd_xkb_variant; +sway_cmd seat_cmd_fallback; sway_cmd seat_cmd_attach; sway_cmd cmd_ipc_cmd; diff --git a/include/sway/config.h b/include/sway/config.h index eb642dc2..fdfbbedb 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -90,6 +90,7 @@ struct seat_attachment_config { */ struct seat_config { char *name; + int fallback; // -1 means not set list_t *attachments; // list of seat_attachment configs }; diff --git a/sway/commands.c b/sway/commands.c index 3fb1842d..34afb6a0 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -165,6 +165,7 @@ static struct cmd_handler input_handlers[] = { // must be in order for the bsearch static struct cmd_handler seat_handlers[] = { { "attach", seat_cmd_attach }, + { "fallback", seat_cmd_fallback }, }; static struct cmd_handler *find_handler(char *line, enum cmd_status block) { diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 4f9e259b..0149762a 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -24,6 +24,8 @@ struct cmd_results *cmd_seat(int argc, char **argv) { current_seat_config = new_seat_config(argv[0]); if (strcasecmp("attach", argv[1]) == 0) { res = seat_cmd_attach(argc_new, argv_new); + } else if (strcasecmp("fallback", argv[1]) == 0) { + res = seat_cmd_fallback(argc_new, argv_new); } else { res = cmd_results_new(CMD_INVALID, "seat ", "Unknown command %s", argv[1]); } diff --git a/sway/commands/seat/fallback.c b/sway/commands/seat/fallback.c new file mode 100644 index 00000000..7c129aae --- /dev/null +++ b/sway/commands/seat/fallback.c @@ -0,0 +1,29 @@ +#include +#include +#include "sway/config.h" +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *seat_cmd_fallback(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "fallback", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_seat_config) { + return cmd_results_new(CMD_FAILURE, "fallback", "No seat defined"); + } + struct seat_config *new_config = + new_seat_config(current_seat_config->name); + + if (strcasecmp(argv[0], "true") == 0) { + new_config->fallback = 1; + } else if (strcasecmp(argv[0], "false") == 0) { + new_config->fallback = 0; + } else { + return cmd_results_new(CMD_INVALID, "fallback", + "Expected 'fallback '"); + } + + apply_seat_config(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config/seat.c b/sway/config/seat.c index 3a2fdaa6..4c9e8d0d 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -17,6 +17,7 @@ struct seat_config *new_seat_config(const char* name) { return NULL; } + seat->fallback = -1; seat->attachments = create_list(); if (!sway_assert(seat->attachments, "could not allocate seat attachments list")) { @@ -66,6 +67,10 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) { dest->name = strdup(source->name); } + if (source->fallback != -1) { + dest->fallback = source->fallback; + } + for (int i = 0; i < source->attachments->length; ++i) { struct seat_attachment_config *source_attachment = source->attachments->items[i]; diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index fa8e4b49..16301489 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -56,9 +56,9 @@ static char *get_device_identifier(struct wlr_input_device *device) { int len = (strlen(name) + - strlen_num(device->vendor) + - strlen_num(device->product) + - 3) * sizeof(char); + strlen_num(device->vendor) + + strlen_num(device->product) + + 3) * sizeof(char); char *identifier = malloc(len); if (!identifier) { @@ -151,13 +151,30 @@ static void input_add_notify(struct wl_listener *listener, void *data) { return; } + bool added = false; wl_list_for_each(seat, &input->seats, link) { if (seat->config && (seat_config_get_attachment(seat->config, input_device->identifier) || seat_config_get_attachment(seat->config, "*"))) { sway_seat_add_device(seat, input_device); + added = true; } } + + if (!added) { + wl_list_for_each(seat, &input->seats, link) { + if (seat->config && seat->config->fallback == 1) { + sway_seat_add_device(seat, input_device); + added = true; + } + } + } + + if (!added) { + sway_log(L_DEBUG, + "device '%s' is not configured on any seats", + input_device->identifier); + } } static void input_remove_notify(struct wl_listener *listener, void *data) { @@ -248,35 +265,53 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, struct seat_config *seat_config) { sway_log(L_DEBUG, "applying new seat config for seat %s", seat_config->name); struct sway_seat *seat = input_manager_get_seat(input, seat_config->name); - // the old config is invalid so clear it - sway_seat_set_config(seat, NULL); + if (!seat) { + return; + } + + sway_seat_set_config(seat, seat_config); - // clear devices + // for every device, try to add it to a seat and if no seat has it + // attached, add it to the fallback seats. struct sway_input_device *input_device = NULL; wl_list_for_each(input_device, &input->devices, link) { - sway_seat_remove_device(seat, input_device); - } - - if (seat_config_get_attachment(seat_config, "*")) { - wl_list_for_each(input_device, &input->devices, link) { - sway_seat_add_device(seat, input_device); + list_t *seat_list = create_list(); + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + if (!seat->config) { + continue; + } + if (seat_config_get_attachment(seat->config, "*") || + seat_config_get_attachment(seat->config, input_device->identifier)) { + list_add(seat_list, seat); + } } - } else { - for (int i = 0; i < seat_config->attachments->length; ++i) { - struct seat_attachment_config *attachment = - seat_config->attachments->items[i]; - - struct sway_input_device *device = - input_sway_device_from_identifier(input, - attachment->identifier); - if (device) { - sway_seat_add_device(seat, device); + if (seat_list->length) { + wl_list_for_each(seat, &input->seats, link) { + bool attached = false; + for (int i = 0; i < seat_list->length; ++i) { + if (seat == seat_list->items[i]) { + attached = true; + break; + } + } + if (attached) { + sway_seat_add_device(seat, input_device); + } else { + sway_seat_remove_device(seat, input_device); + } + } + } else { + wl_list_for_each(seat, &input->seats, link) { + if (seat->config && seat->config->fallback == 1) { + sway_seat_add_device(seat, input_device); + } else { + sway_seat_remove_device(seat, input_device); + } } } } - - sway_seat_set_config(seat, seat_config); } void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { diff --git a/sway/input/seat.c b/sway/input/seat.c index 8fe82b46..94503687 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -120,6 +120,7 @@ void sway_seat_configure_device(struct sway_seat *seat, void sway_seat_add_device(struct sway_seat *seat, struct sway_input_device *input_device) { if (sway_seat_get_device(seat, input_device)) { + sway_seat_configure_device(seat, input_device); return; } @@ -246,7 +247,5 @@ void sway_seat_set_config(struct sway_seat *seat, seat_device->attachment_config = seat_config_get_attachment(seat_config, seat_device->input_device->identifier); - sway_seat_configure_device(seat, seat_device->input_device); } - } diff --git a/sway/meson.build b/sway/meson.build index 3d38c7c9..fee2ddd2 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -13,6 +13,7 @@ sway_sources = files( 'commands/input.c', 'commands/seat.c', 'commands/seat/attach.c', + 'commands/seat/fallback.c', 'commands/input/accel_profile.c', 'commands/input/click_method.c', 'commands/input/drag_lock.c', -- cgit v1.2.3 From c815d6d1a97fe940052f079bd8eb7f174f5ab004 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 18 Dec 2017 14:13:07 +0100 Subject: Add support for fractional output scale --- include/sway/config.h | 2 +- sway/commands/output.c | 4 ++-- sway/config/output.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 139d7800..afff2738 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -82,7 +82,7 @@ struct output_config { int width, height; float refresh_rate; int x, y; - int scale; + float scale; int32_t transform; char *background; diff --git a/sway/commands/output.c b/sway/commands/output.c index d71e4d8d..7988e3e4 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -144,7 +144,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { goto fail; } char *end; - output->scale = strtol(argv[i], &end, 10); + output->scale = strtof(argv[i], &end); if (*end) { error = cmd_results_new(CMD_INVALID, "output", "Invalid scale."); @@ -278,7 +278,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { } sway_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " - "position %d,%d scale %d transform %d) (bg %s %s)", + "position %d,%d scale %f transform %d) (bg %s %s)", output->name, output->enabled, output->width, output->height, output->refresh_rate, output->x, output->y, output->scale, output->transform, output->background, output->background_option); diff --git a/sway/config/output.c b/sway/config/output.c index dc9ee37c..ff3f73a3 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -111,7 +111,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); } if (oc && oc->scale > 0) { - sway_log(L_DEBUG, "Set %s scale to %d", oc->name, oc->scale); + sway_log(L_DEBUG, "Set %s scale to %f", oc->name, oc->scale); wlr_output_set_scale(wlr_output, oc->scale); } if (oc && oc->transform >= 0) { -- cgit v1.2.3 From ba69f06695c24f98a05d138a53ba130108ebce6f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 27 Dec 2017 10:08:18 -0500 Subject: binding config --- include/sway/config.h | 3 +- sway/commands.c | 2 + sway/commands/bind.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ sway/config.c | 3 +- sway/meson.build | 1 + 5 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 sway/commands/bind.c (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 83ded720..7146623e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -46,7 +46,8 @@ struct sway_mouse_binding { */ struct sway_mode { char *name; - list_t *bindings; + list_t *keysym_bindings; + list_t *keycode_bindings; }; /** diff --git a/sway/commands.c b/sway/commands.c index 34afb6a0..b0078a46 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -127,6 +127,8 @@ struct cmd_results *add_color(const char *name, char *buffer, const char *color) /* Keep alphabetized */ static struct cmd_handler handlers[] = { + { "bindcode", cmd_bindcode }, + { "bindsym", cmd_bindsym }, { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, { "exit", cmd_exit }, diff --git a/sway/commands/bind.c b/sway/commands/bind.c new file mode 100644 index 00000000..62aa535a --- /dev/null +++ b/sway/commands/bind.c @@ -0,0 +1,173 @@ +#ifdef __linux__ +#include +#elif __FreeBSD__ +#include +#endif +#include +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "list.h" +#include "log.h" +#include "stringop.h" +#include "util.h" + +int binding_order = 0; + +void free_sway_binding(struct sway_binding *binding) { + if (binding->keys) { + for (int i = 0; i < binding->keys->length; i++) { + free(binding->keys->items[i]); + } + list_free(binding->keys); + } + if (binding->command) { + free(binding->command); + } + free(binding); +} + +struct cmd_results *cmd_bindsym(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1))) { + return error; + } + + struct sway_binding *binding = malloc(sizeof(struct sway_binding)); + if (!binding) { + return cmd_results_new(CMD_FAILURE, "bindsym", + "Unable to allocate binding"); + } + binding->keys = create_list(); + binding->modifiers = 0; + binding->release = false; + binding->bindcode = false; + + // Handle --release + if (strcmp("--release", argv[0]) == 0) { + if (argc >= 3) { + binding->release = true; + argv++; + argc--; + } else { + free_sway_binding(binding); + return cmd_results_new(CMD_FAILURE, "bindsym", + "Invalid bindsym command " + "(expected more than 2 arguments, got %d)", argc); + } + } + + binding->command = join_args(argv + 1, argc - 1); + + list_t *split = split_string(argv[0], "+"); + for (int i = 0; i < split->length; ++i) { + // Check for a modifier key + uint32_t mod; + if ((mod = get_modifier_mask_by_name(split->items[i])) > 0) { + binding->modifiers |= mod; + continue; + } + // Check for xkb key + xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], + XKB_KEYSYM_CASE_INSENSITIVE); + + // Check for mouse binding + if (strncasecmp(split->items[i], "button", strlen("button")) == 0 && + strlen(split->items[i]) == strlen("button0")) { + sym = ((char *)split->items[i])[strlen("button")] - '1' + BTN_LEFT; + } + if (!sym) { + struct cmd_results *ret = cmd_results_new(CMD_INVALID, "bindsym", + "Unknown key '%s'", (char *)split->items[i]); + free_sway_binding(binding); + free_flat_list(split); + return ret; + } + xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); + if (!key) { + free_sway_binding(binding); + free_flat_list(split); + return cmd_results_new(CMD_FAILURE, "bindsym", + "Unable to allocate binding"); + } + *key = sym; + list_add(binding->keys, key); + } + free_flat_list(split); + + struct sway_mode *mode = config->current_mode; + // TODO overwrite the binding if it already exists + binding->order = binding_order++; + list_add(mode->keysym_bindings, binding); + + sway_log(L_DEBUG, "bindsym - Bound %s to command %s", + argv[0], binding->command); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *cmd_bindcode(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "bindcode", EXPECTED_MORE_THAN, 1))) { + return error; + } + + struct sway_binding *binding = malloc(sizeof(struct sway_binding)); + if (!binding) { + return cmd_results_new(CMD_FAILURE, "bindsym", + "Unable to allocate binding"); + } + binding->keys = create_list(); + binding->modifiers = 0; + binding->release = false; + binding->bindcode = true; + + // Handle --release + if (strcmp("--release", argv[0]) == 0) { + if (argc >= 3) { + binding->release = true; + argv++; + argc--; + } else { + free_sway_binding(binding); + return cmd_results_new(CMD_FAILURE, "bindcode", + "Invalid bindcode command " + "(expected more than 2 arguments, got %d)", argc); + } + } + + binding->command = join_args(argv + 1, argc - 1); + + list_t *split = split_string(argv[0], "+"); + for (int i = 0; i < split->length; ++i) { + // Check for a modifier key + uint32_t mod; + if ((mod = get_modifier_mask_by_name(split->items[i])) > 0) { + binding->modifiers |= mod; + continue; + } + // parse keycode + xkb_keycode_t keycode = (int)strtol(split->items[i], NULL, 10); + if (!xkb_keycode_is_legal_ext(keycode)) { + error = + cmd_results_new(CMD_INVALID, "bindcode", + "Invalid keycode '%s'", (char *)split->items[i]); + free_sway_binding(binding); + list_free(split); + return error; + } + xkb_keycode_t *key = malloc(sizeof(xkb_keycode_t)); + *key = keycode - 8; + list_add(binding->keys, key); + } + free_flat_list(split); + + struct sway_mode *mode = config->current_mode; + // TODO overwrite binding if it already exists + binding->order = binding_order++; + list_add(mode->keycode_bindings, binding); + + sway_log(L_DEBUG, "bindcode - Bound %s to command %s", + argv[0], binding->command); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index b591ae9e..312e0779 100644 --- a/sway/config.c +++ b/sway/config.c @@ -53,7 +53,8 @@ static void config_defaults(struct sway_config *config) { goto cleanup; if (!(config->current_mode->name = malloc(sizeof("default")))) goto cleanup; strcpy(config->current_mode->name, "default"); - if (!(config->current_mode->bindings = create_list())) goto cleanup; + if (!(config->current_mode->keysym_bindings = create_list())) goto cleanup; + if (!(config->current_mode->keycode_bindings = create_list())) goto cleanup; list_add(config->modes, config->current_mode); config->floating_mod = 0; diff --git a/sway/meson.build b/sway/meson.build index fee2ddd2..01d5ef36 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -6,6 +6,7 @@ sway_sources = files( 'input/seat.c', 'input/cursor.c', 'input/keyboard.c', + 'commands/bind.c', 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', -- cgit v1.2.3 From 21c61f1c0909b613471f18dd41e984c54540aca8 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 27 Dec 2017 21:23:30 +0100 Subject: Refactor output command, add output enable --- include/sway/config.h | 2 +- sway/commands/output.c | 441 +++++++++++++++++++++++++------------------------ sway/config/output.c | 7 +- 3 files changed, 231 insertions(+), 219 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 83ded720..045359ca 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -397,7 +397,7 @@ struct seat_attachment_config *seat_config_get_attachment( void apply_seat_config(struct seat_config *seat); int output_name_cmp(const void *item, const void *data); -struct output_config *new_output_config(); +struct output_config *new_output_config(const char *name); void merge_output_config(struct output_config *dst, struct output_config *src); void apply_output_config(struct output_config *oc, swayc_t *output); void free_output_config(struct output_config *oc); diff --git a/sway/commands/output.c b/sway/commands/output.c index 7988e3e4..8cc74bcc 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -20,253 +20,260 @@ static char *bg_options[] = { "tile", }; +static struct cmd_results *cmd_output_mode(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", "Missing mode argument."); + } + + char *end; + output->width = strtol(argv[*i], &end, 10); + if (*end) { + // Format is 1234x4321 + if (*end != 'x') { + return cmd_results_new(CMD_INVALID, "output", + "Invalid mode width."); + } + ++end; + output->height = strtol(end, &end, 10); + if (*end) { + if (*end != '@') { + return cmd_results_new(CMD_INVALID, "output", + "Invalid mode height."); + } + ++end; + output->refresh_rate = strtof(end, &end); + if (strcasecmp("Hz", end) != 0) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid mode refresh rate."); + } + } + } else { + // Format is 1234 4321 + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing mode argument (height)."); + } + output->height = strtol(argv[*i], &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid mode height."); + } + } + + return NULL; +} + +static struct cmd_results *cmd_output_position(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing position argument."); + } + + char *end; + output->x = strtol(argv[*i], &end, 10); + if (*end) { + // Format is 1234,4321 + if (*end != ',') { + return cmd_results_new(CMD_INVALID, "output", + "Invalid position x."); + } + ++end; + output->y = strtol(end, &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid position y."); + } + } else { + // Format is 1234 4321 (legacy) + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing position argument (y)."); + } + output->y = strtol(argv[*i], &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid position y."); + } + } + + return NULL; +} + +static struct cmd_results *cmd_output_scale(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing scale argument."); + } + + char *end; + output->scale = strtof(argv[*i], &end); + if (*end) { + return cmd_results_new(CMD_INVALID, "output", "Invalid scale."); + } + + return NULL; +} + +static struct cmd_results *cmd_output_transform(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing transform argument."); + } + + char *value = argv[*i]; + if (strcmp(value, "normal") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + } else if (strcmp(value, "90") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_90; + } else if (strcmp(value, "180") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_180; + } else if (strcmp(value, "270") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_270; + } else if (strcmp(value, "flipped") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; + } else if (strcmp(value, "flipped-90") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; + } else if (strcmp(value, "flipped-180") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; + } else if (strcmp(value, "flipped-270") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; + } else { + return cmd_results_new(CMD_INVALID, "output", + "Invalid output transform."); + } + + return NULL; +} + +static struct cmd_results *cmd_output_background(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing background file or color specification."); + } + const char *background = argv[*i]; + if (*i + 1 >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing background scaling mode or `solid_color`."); + } + const char *background_option = argv[*i]; + + if (strcasecmp(background_option, "solid_color") == 0) { + output->background = strdup(background); + output->background_option = strdup("solid_color"); + } else { + bool valid = false; + char *mode; + size_t j; + for (j = 0; j < (size_t)(argc - *i); ++j) { + mode = argv[*i + j]; + size_t n = sizeof(bg_options) / sizeof(char *); + for (size_t k = 0; k < n; ++k) { + if (strcasecmp(mode, bg_options[k]) == 0) { + valid = true; + break; + } + } + if (valid) { + break; + } + } + if (!valid) { + return cmd_results_new(CMD_INVALID, "output", + "Missing background scaling mode."); + } + + wordexp_t p; + char *src = join_args(argv + *i - 1, j); + if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid syntax (%s).", src); + } + free(src); + src = p.we_wordv[0]; + if (config->reading && *src != '/') { + char *conf = strdup(config->current_config); + if (conf) { + char *conf_path = dirname(conf); + src = malloc(strlen(conf_path) + strlen(src) + 2); + if (src) { + sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); + } else { + sway_log(L_ERROR, + "Unable to allocate background source"); + } + free(conf); + } else { + sway_log(L_ERROR, "Unable to allocate background source"); + } + } + if (!src || access(src, F_OK) == -1) { + wordfree(&p); + return cmd_results_new(CMD_INVALID, "output", + "Background file unreadable (%s).", src); + } + + output->background = strdup(src); + output->background_option = strdup(mode); + if (src != p.we_wordv[0]) { + free(src); + } + wordfree(&p); + + *i += j; + } + + return NULL; +} + struct cmd_results *cmd_output(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) { return error; } - const char *name = argv[0]; - struct output_config *output = new_output_config(); + struct output_config *output = new_output_config(argv[0]); if (!output) { sway_log(L_ERROR, "Failed to allocate output config"); return NULL; } - output->name = strdup(name); - int i; - for (i = 1; i < argc; ++i) { + for (int i = 1; i < argc; ++i) { const char *command = argv[i]; - if (strcasecmp(command, "disable") == 0) { + if (strcasecmp(command, "enable") == 0) { + output->enabled = 1; + } else if (strcasecmp(command, "disable") == 0) { output->enabled = 0; } else if (strcasecmp(command, "mode") == 0 || strcasecmp(command, "resolution") == 0 || strcasecmp(command, "res") == 0) { - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing mode argument."); - goto fail; - } - - int width = -1, height = -1; - float refresh_rate = -1; - - char *end; - width = strtol(argv[i], &end, 10); - if (*end) { - // Format is 1234x4321 - if (*end != 'x') { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid mode width."); - goto fail; - } - ++end; - height = strtol(end, &end, 10); - if (*end) { - if (*end != '@') { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid mode height."); - goto fail; - } - ++end; - refresh_rate = strtof(end, &end); - if (strcasecmp("Hz", end) != 0) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid mode refresh rate."); - goto fail; - } - } - } else { - // Format is 1234 4321 - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing mode argument (height)."); - goto fail; - } - height = strtol(argv[i], &end, 10); - if (*end) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid mode height."); - goto fail; - } - } - output->width = width; - output->height = height; - output->refresh_rate = refresh_rate; + error = cmd_output_mode(output, &i, argc, argv); } else if (strcasecmp(command, "position") == 0 || strcasecmp(command, "pos") == 0) { - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing position argument."); - goto fail; - } - - int x = -1, y = -1; - - char *end; - x = strtol(argv[i], &end, 10); - if (*end) { - // Format is 1234,4321 - if (*end != ',') { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid position x."); - goto fail; - } - ++end; - y = strtol(end, &end, 10); - if (*end) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid position y."); - goto fail; - } - } else { - // Format is 1234 4321 (legacy) - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing position argument (y)."); - goto fail; - } - y = strtol(argv[i], &end, 10); - if (*end) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid position y."); - goto fail; - } - } - - output->x = x; - output->y = y; + error = cmd_output_position(output, &i, argc, argv); } else if (strcasecmp(command, "scale") == 0) { - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing scale parameter."); - goto fail; - } - char *end; - output->scale = strtof(argv[i], &end); - if (*end) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid scale."); - goto fail; - } + error = cmd_output_scale(output, &i, argc, argv); } else if (strcasecmp(command, "transform") == 0) { - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing transform parameter."); - goto fail; - } - char *value = argv[i]; - if (strcmp(value, "normal") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_NORMAL; - } else if (strcmp(value, "90") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_90; - } else if (strcmp(value, "180") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_180; - } else if (strcmp(value, "270") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_270; - } else if (strcmp(value, "flipped") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; - } else if (strcmp(value, "flipped-90") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; - } else if (strcmp(value, "flipped-180") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; - } else if (strcmp(value, "flipped-270") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; - } else { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid output transform."); - goto fail; - } + error = cmd_output_transform(output, &i, argc, argv); } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) { - wordexp_t p; - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing background file or color specification."); - goto fail; - } - if (i + 1 >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing background scaling mode or `solid_color`."); - goto fail; - } - if (strcasecmp(argv[i + 1], "solid_color") == 0) { - output->background = strdup(argv[argc - 2]); - output->background_option = strdup("solid_color"); - } else { - // argv[i+j]=bg_option - bool valid = false; - char *mode; - size_t j; - for (j = 0; j < (size_t) (argc - i); ++j) { - mode = argv[i + j]; - size_t n = sizeof(bg_options) / sizeof(char *); - for (size_t k = 0; k < n; ++k) { - if (strcasecmp(mode, bg_options[k]) == 0) { - valid = true; - break; - } - } - if (valid) { - break; - } - } - if (!valid) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing background scaling mode."); - goto fail; - } - - char *src = join_args(argv + i, j); - if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid syntax (%s).", src); - goto fail; - } - free(src); - src = p.we_wordv[0]; - if (config->reading && *src != '/') { - char *conf = strdup(config->current_config); - if (conf) { - char *conf_path = dirname(conf); - src = malloc(strlen(conf_path) + strlen(src) + 2); - if (src) { - sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); - } else { - sway_log(L_ERROR, - "Unable to allocate background source"); - } - free(conf); - } else { - sway_log(L_ERROR, - "Unable to allocate background source"); - } - } - if (!src || access(src, F_OK) == -1) { - error = cmd_results_new(CMD_INVALID, "output", - "Background file unreadable (%s).", src); - wordfree(&p); - goto fail; - } - - output->background = strdup(src); - output->background_option = strdup(mode); - if (src != p.we_wordv[0]) { - free(src); - } - wordfree(&p); - - i += j; - } + error = cmd_output_background(output, &i, argc, argv); } else { error = cmd_results_new(CMD_INVALID, "output", "Invalid output subcommand: %s.", command); + } + + if (error != NULL) { goto fail; } } - i = list_seq_find(config->output_configs, output_name_cmp, name); + int i = list_seq_find(config->output_configs, output_name_cmp, output->name); if (i >= 0) { // merge existing config struct output_config *oc = config->output_configs->items[i]; diff --git a/sway/config/output.c b/sway/config/output.c index ff3f73a3..f336c949 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -14,11 +14,16 @@ int output_name_cmp(const void *item, const void *data) { return strcmp(output->name, name); } -struct output_config *new_output_config() { +struct output_config *new_output_config(const char *name) { struct output_config *oc = calloc(1, sizeof(struct output_config)); if (oc == NULL) { return NULL; } + oc->name = strdup(name); + if (oc->name == NULL) { + free(oc); + return NULL; + } oc->enabled = -1; oc->width = oc->height = -1; oc->refresh_rate = -1; -- cgit v1.2.3 From ead3f1e676923b0457cef77b0b482e76cac50307 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 29 Dec 2017 19:04:16 +0100 Subject: Allow to configure outputs by their identifier --- include/sway/config.h | 2 ++ sway/commands/output.c | 46 ++++++++++++++++++--------------- sway/config/output.c | 8 ++++++ sway/tree/container.c | 70 ++++++++++++++++++++++++++++---------------------- 4 files changed, 75 insertions(+), 51 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 045359ca..eecdde3a 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -397,6 +397,8 @@ struct seat_attachment_config *seat_config_get_attachment( void apply_seat_config(struct seat_config *seat); int output_name_cmp(const void *item, const void *data); +void output_get_identifier(char *identifier, size_t len, + struct sway_output *output); struct output_config *new_output_config(const char *name); void merge_output_config(struct output_config *dst, struct output_config *src); void apply_output_config(struct output_config *oc, swayc_t *output); diff --git a/sway/commands/output.c b/sway/commands/output.c index 8cc74bcc..8c0fa63c 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -231,8 +231,8 @@ static struct cmd_results *cmd_output_background(struct output_config *output, } struct cmd_results *cmd_output(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) { + struct cmd_results *error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1); + if (error != NULL) { return error; } @@ -275,11 +275,11 @@ struct cmd_results *cmd_output(int argc, char **argv) { int i = list_seq_find(config->output_configs, output_name_cmp, output->name); if (i >= 0) { - // merge existing config - struct output_config *oc = config->output_configs->items[i]; - merge_output_config(oc, output); + // Merge existing config + struct output_config *current = config->output_configs->items[i]; + merge_output_config(current, output); free_output_config(output); - output = oc; + output = current; } else { list_add(config->output_configs, output); } @@ -290,22 +290,26 @@ struct cmd_results *cmd_output(int argc, char **argv) { output->refresh_rate, output->x, output->y, output->scale, output->transform, output->background, output->background_option); - if (output->name) { - // Try to find the output container and apply configuration now. If - // this is during startup then there will be no container and config - // will be applied during normal "new output" event from wlroots. - swayc_t *cont = NULL; - for (int i = 0; i < root_container.children->length; ++i) { - cont = root_container.children->items[i]; - if (cont->name && ((strcmp(cont->name, output->name) == 0) || - (strcmp(output->name, "*") == 0))) { - apply_output_config(output, cont); + // Try to find the output container and apply configuration now. If + // this is during startup then there will be no container and config + // will be applied during normal "new output" event from wlroots. + char identifier[128]; + bool all = strcmp(output->name, "*") == 0; + for (int i = 0; i < root_container.children->length; ++i) { + swayc_t *cont = root_container.children->items[i]; + if (cont->type != C_OUTPUT) { + continue; + } - if (strcmp(output->name, "*") != 0) { - // Stop looking if the output config isn't applicable to all - // outputs - break; - } + output_get_identifier(identifier, sizeof(identifier), cont->sway_output); + if (all || strcmp(cont->name, output->name) == 0 || + strcmp(identifier, output->name) == 0) { + apply_output_config(output, cont); + + if (!all) { + // Stop looking if the output config isn't applicable to all + // outputs + break; } } } diff --git a/sway/config/output.c b/sway/config/output.c index f336c949..e798a20e 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include #include #include #include @@ -14,6 +15,13 @@ int output_name_cmp(const void *item, const void *data) { return strcmp(output->name, name); } +void output_get_identifier(char *identifier, size_t len, + struct sway_output *output) { + struct wlr_output *wlr_output = output->wlr_output; + snprintf(identifier, len, "%s %s %s", wlr_output->make, wlr_output->model, + wlr_output->serial); +} + struct output_config *new_output_config(const char *name) { struct output_config *oc = calloc(1, sizeof(struct output_config)); if (oc == NULL) { diff --git a/sway/tree/container.c b/sway/tree/container.c index 6f2a3abf..c5574275 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -49,16 +49,49 @@ static swayc_t *new_swayc(enum swayc_types type) { return c; } +static void free_swayc(swayc_t *cont) { + if (!sway_assert(cont, "free_swayc passed NULL")) { + return; + } + + wl_signal_emit(&cont->events.destroy, cont); + + if (cont->children) { + // remove children until there are no more, free_swayc calls + // remove_child, which removes child from this container + while (cont->children->length) { + free_swayc(cont->children->items[0]); + } + list_free(cont->children); + } + if (cont->marks) { + list_foreach(cont->marks, free); + list_free(cont->marks); + } + if (cont->parent) { + remove_child(cont); + } + if (cont->name) { + free(cont->name); + } + free(cont); +} + swayc_t *new_output(struct sway_output *sway_output) { struct wlr_box size; wlr_output_effective_resolution(sway_output->wlr_output, &size.width, &size.height); + const char *name = sway_output->wlr_output->name; + char identifier[128]; + output_get_identifier(identifier, sizeof(identifier), sway_output); struct output_config *oc = NULL, *all = NULL; for (int i = 0; i < config->output_configs->length; ++i) { struct output_config *cur = config->output_configs->items[i]; - if (strcasecmp(name, cur->name) == 0) { + + if (strcasecmp(name, cur->name) == 0 || + strcasecmp(identifier, cur->name) == 0) { sway_log(L_DEBUG, "Matched output config for %s", name); oc = cur; } @@ -74,13 +107,18 @@ swayc_t *new_output(struct sway_output *sway_output) { if (!oc) { oc = all; } + if (oc && !oc->enabled) { return NULL; } swayc_t *output = new_swayc(C_OUTPUT); output->sway_output = sway_output; - output->name = name ? strdup(name) : NULL; + output->name = strdup(name); + if (output->name == NULL) { + free_swayc(output); + return NULL; + } apply_output_config(oc, output); @@ -140,34 +178,6 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { return swayc; } -static void free_swayc(swayc_t *cont) { - if (!sway_assert(cont, "free_swayc passed NULL")) { - return; - } - - wl_signal_emit(&cont->events.destroy, cont); - - if (cont->children) { - // remove children until there are no more, free_swayc calls - // remove_child, which removes child from this container - while (cont->children->length) { - free_swayc(cont->children->items[0]); - } - list_free(cont->children); - } - if (cont->marks) { - list_foreach(cont->marks, free); - list_free(cont->marks); - } - if (cont->parent) { - remove_child(cont); - } - if (cont->name) { - free(cont->name); - } - free(cont); -} - swayc_t *destroy_output(swayc_t *output) { if (!sway_assert(output, "null output passed to destroy_output")) { return NULL; -- cgit v1.2.3 From c83900593daace2ef85174163edf2748179e28f2 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 29 Dec 2017 15:31:04 +0100 Subject: config: add 'set' command --- include/sway/config.h | 1 + sway/commands.c | 3 ++- sway/commands/set.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ sway/config.c | 7 ++++- sway/meson.build | 1 + 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 sway/commands/set.c (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 405092e3..0a9c4595 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -375,6 +375,7 @@ bool read_config(FILE *file, struct sway_config *config); * Free config struct */ void free_config(struct sway_config *config); +void free_sway_variable(struct sway_variable *var); /** * Does variable replacement for a string based on the config's currently loaded variables. */ diff --git a/sway/commands.c b/sway/commands.c index c1c6dc5d..f01329db 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -138,6 +138,7 @@ static struct cmd_handler handlers[] = { { "input", cmd_input }, { "output", cmd_output }, { "seat", cmd_seat }, + { "set", cmd_set }, }; static int handler_compare(const void *_a, const void *_b) { @@ -290,7 +291,7 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) { int i; // Var replacement, for all but first argument of set // TODO commands - for (i = /*handler->handle == cmd_set ? 2 :*/ 1; i < argc; ++i) { + for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { argv[i] = do_var_replacement(argv[i]); unescape_string(argv[i]); } diff --git a/sway/commands/set.c b/sway/commands/set.c new file mode 100644 index 00000000..dcd928ba --- /dev/null +++ b/sway/commands/set.c @@ -0,0 +1,71 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "list.h" +#include "log.h" +#include "stringop.h" + +// sort in order of longest->shortest +static int compare_set_qsort(const void *_l, const void *_r) { + struct sway_variable const *l = *(void **)_l; + struct sway_variable const *r = *(void **)_r; + return strlen(r->name) - strlen(l->name); +} + +void free_sway_variable(struct sway_variable *var) { + if (!var) { + return; + } + free(var->name); + free(var->value); + free(var); +} + +struct cmd_results *cmd_set(int argc, char **argv) { + char *tmp; + struct cmd_results *error = NULL; + if (!config->reading) return cmd_results_new(CMD_FAILURE, "set", "Can only be used in config file."); + if ((error = checkarg(argc, "set", EXPECTED_AT_LEAST, 2))) { + return error; + } + + if (argv[0][0] != '$') { + sway_log(L_INFO, "Warning: variable '%s' doesn't start with $", argv[0]); + + size_t size = snprintf(NULL, 0, "$%s", argv[0]); + tmp = malloc(size + 1); + if (!tmp) { + return cmd_results_new(CMD_FAILURE, "set", "Not possible to create variable $'%s'", argv[0]); + } + snprintf(tmp, size+1, "$%s", argv[0]); + + argv[0] = tmp; + } + + struct sway_variable *var = NULL; + // Find old variable if it exists + int i; + for (i = 0; i < config->symbols->length; ++i) { + var = config->symbols->items[i]; + if (strcmp(var->name, argv[0]) == 0) { + break; + } + var = NULL; + } + if (var) { + free(var->value); + } else { + var = malloc(sizeof(struct sway_variable)); + if (!var) { + return cmd_results_new(CMD_FAILURE, "set", "Unable to allocate variable"); + } + var->name = strdup(argv[0]); + list_add(config->symbols, var); + list_qsort(config->symbols, compare_set_qsort); + } + var->value = join_args(argv + 1, argc - 1); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 627ed94f..e0a93e19 100644 --- a/sway/config.c +++ b/sway/config.c @@ -61,7 +61,12 @@ void free_config(struct sway_config *config) { } // TODO: handle all currently unhandled lists as we add implementations - list_free(config->symbols); + if (config->symbols) { + for (i = 0; i < config->symbols->length; i++) { + free_sway_variable(config->symbols->items[i]); + } + list_free(config->symbols); + } if (config->modes) { for (i = 0; i < config->modes->length; i++) { free_mode(config->modes->items[i]); diff --git a/sway/meson.build b/sway/meson.build index 01d5ef36..30ec166b 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -15,6 +15,7 @@ sway_sources = files( 'commands/seat.c', 'commands/seat/attach.c', 'commands/seat/fallback.c', + 'commands/set.c', 'commands/input/accel_profile.c', 'commands/input/click_method.c', 'commands/input/drag_lock.c', -- cgit v1.2.3 From 9f54cd89359119897fed2747c373879c09ae8706 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 17 Jan 2018 09:49:02 -0500 Subject: copy config references for input and seat --- include/sway/config.h | 2 ++ sway/config.c | 7 ++++++- sway/config/input.c | 10 ++++++++++ sway/config/seat.c | 11 +++++++++++ sway/input/input-manager.c | 7 +++++-- sway/input/seat.c | 7 +++---- 6 files changed, 37 insertions(+), 7 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 0a9c4595..967d3756 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -386,12 +386,14 @@ struct cmd_results *check_security_config(); int input_identifier_cmp(const void *item, const void *data); struct input_config *new_input_config(const char* identifier); void merge_input_config(struct input_config *dst, struct input_config *src); +struct input_config *copy_input_config(struct input_config *ic); void free_input_config(struct input_config *ic); void apply_input_config(struct input_config *input); int seat_name_cmp(const void *item, const void *data); struct seat_config *new_seat_config(const char* name); void merge_seat_config(struct seat_config *dst, struct seat_config *src); +struct seat_config *copy_seat_config(struct seat_config *seat); void free_seat_config(struct seat_config *ic); struct seat_attachment_config *seat_attachment_config_new(); struct seat_attachment_config *seat_config_get_attachment( diff --git a/sway/config.c b/sway/config.c index 5ec45b17..cbd9a8b2 100644 --- a/sway/config.c +++ b/sway/config.c @@ -84,7 +84,12 @@ void free_config(struct sway_config *config) { } list_free(config->input_configs); } - list_free(config->seat_configs); + if (config->seat_configs) { + for (i = 0; i < config->seat_configs->length; i++) { + free_seat_config(config->seat_configs->items[i]); + } + list_free(config->seat_configs); + } list_free(config->criteria); list_free(config->no_focus); list_free(config->active_bar_modifiers); diff --git a/sway/config/input.c b/sway/config/input.c index 96181302..c4f6211d 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -90,6 +90,16 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { } } +struct input_config *copy_input_config(struct input_config *ic) { + struct input_config *copy = calloc(1, sizeof(struct input_config)); + if (copy == NULL) { + wlr_log(L_ERROR, "could not allocate input config"); + return NULL; + } + merge_input_config(copy, ic); + return copy; +} + void free_input_config(struct input_config *ic) { if (!ic) { return; diff --git a/sway/config/seat.c b/sway/config/seat.c index 03cc6d4e..bd8b45c8 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -99,6 +99,17 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) { } } +struct seat_config *copy_seat_config(struct seat_config *seat) { + struct seat_config *copy = new_seat_config(seat->name); + if (copy == NULL) { + return NULL; + } + + merge_seat_config(copy, seat); + + return copy; +} + void free_seat_config(struct seat_config *seat) { if (!seat) { return; diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 26cf5035..bfe9d9c4 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -174,7 +174,8 @@ static void input_add_notify(struct wl_listener *listener, void *data) { for (int i = 0; i < config->input_configs->length; ++i) { struct input_config *input_config = config->input_configs->items[i]; if (strcmp(input_config->identifier, input_device->identifier) == 0) { - input_device->config = input_config; + free_input_config(input_device->config); + input_device->config = copy_input_config(input_config); break; } } @@ -240,6 +241,7 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { } wl_list_remove(&input_device->link); + free_input_config(input_device->config); free(input_device->identifier); free(input_device); } @@ -293,7 +295,8 @@ void sway_input_manager_apply_input_config(struct sway_input_manager *input, struct sway_input_device *input_device = NULL; wl_list_for_each(input_device, &input->devices, link) { if (strcmp(input_device->identifier, input_config->identifier) == 0) { - input_device->config = input_config; + free_input_config(input_device->config); + input_device->config = copy_input_config(input_config); if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { sway_input_manager_libinput_config_pointer(input_device); diff --git a/sway/input/seat.c b/sway/input/seat.c index 268486ab..d134bc68 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -230,6 +230,7 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config) { // clear configs + free_seat_config(seat->config); seat->config = NULL; struct sway_seat_device *seat_device = NULL; @@ -242,11 +243,9 @@ void sway_seat_set_config(struct sway_seat *seat, } // add configs - seat->config = seat_config; + seat->config = copy_seat_config(seat_config); wl_list_for_each(seat_device, &seat->devices, link) { - seat_device->attachment_config = - seat_config_get_attachment(seat_config, - seat_device->input_device->identifier); + sway_seat_configure_device(seat, seat_device->input_device); } } -- cgit v1.2.3 From 9e0595f26bcca2a4d0aa735c4cd9fc4f792918bf Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 20 Jan 2018 11:32:07 -0500 Subject: input config handler context --- include/sway/config.h | 8 ++++++++ include/sway/input/input-manager.h | 1 - sway/commands.c | 3 --- sway/commands/input.c | 28 +++++++++++++++++++--------- sway/commands/input/accel_profile.c | 2 ++ sway/commands/input/click_method.c | 4 ++-- sway/commands/input/drag_lock.c | 2 ++ sway/commands/input/dwt.c | 2 ++ sway/commands/input/events.c | 6 ++++-- sway/commands/input/left_handed.c | 2 ++ sway/commands/input/middle_emulation.c | 2 ++ sway/commands/input/natural_scroll.c | 2 ++ sway/commands/input/pointer_accel.c | 2 ++ sway/commands/input/scroll_method.c | 2 ++ sway/commands/input/tap.c | 3 ++- sway/commands/input/xkb_layout.c | 3 ++- sway/commands/input/xkb_model.c | 3 ++- sway/commands/input/xkb_options.c | 3 ++- sway/commands/input/xkb_rules.c | 3 ++- sway/commands/input/xkb_variant.c | 3 ++- sway/config.c | 10 ++++++++-- 21 files changed, 69 insertions(+), 25 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 0a9c4595..1ab96b51 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -350,6 +350,11 @@ struct sway_config { list_t *command_policies; list_t *feature_policies; list_t *ipc_policies; + + // Context for command handlers + struct { + struct input_config *input_config; + } handler_context; }; void pid_workspace_add(struct pid_workspace *pw); @@ -375,6 +380,9 @@ bool read_config(FILE *file, struct sway_config *config); * Free config struct */ void free_config(struct sway_config *config); + +void config_clear_handler_context(struct sway_config *config); + void free_sway_variable(struct sway_variable *var); /** * Does variable replacement for a string based on the config's currently loaded variables. diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 53064eed..8388f930 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -5,7 +5,6 @@ #include "sway/config.h" #include "list.h" -extern struct input_config *current_input_config; extern struct seat_config *current_seat_config; /** diff --git a/sway/commands.c b/sway/commands.c index 1005cf68..fd2e1514 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -70,10 +70,7 @@ void apply_input_config(struct input_config *input) { list_add(config->input_configs, input); } - struct input_config *old_input_config = current_input_config; - current_input_config = input; sway_input_manager_apply_input_config(input_manager, input); - current_input_config = old_input_config; } void apply_seat_config(struct seat_config *seat) { diff --git a/sway/commands/input.c b/sway/commands/input.c index 5ea39f62..5de65621 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -11,8 +11,12 @@ struct cmd_results *cmd_input(int argc, char **argv) { } if (config->reading && strcmp("{", argv[1]) == 0) { - current_input_config = new_input_config(argv[0]); - wlr_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); + free_input_config(config->handler_context.input_config); + config->handler_context.input_config = new_input_config(argv[0]); + if (!config->handler_context.input_config) { + return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); + } + wlr_log(L_DEBUG, "entering input block: %s", argv[0]); return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); } @@ -20,15 +24,16 @@ struct cmd_results *cmd_input(int argc, char **argv) { return error; } + bool has_context = (config->handler_context.input_config != NULL); + if (!has_context) { + // caller did not give a context so create one just for this command + config->handler_context.input_config = new_input_config(argv[0]); + } + int argc_new = argc-2; char **argv_new = argv+2; struct cmd_results *res; - struct input_config *old_input_config = current_input_config; - current_input_config = new_input_config(argv[0]); - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); - } if (strcasecmp("accel_profile", argv[1]) == 0) { res = input_cmd_accel_profile(argc_new, argv_new); } else if (strcasecmp("click_method", argv[1]) == 0) { @@ -64,7 +69,12 @@ struct cmd_results *cmd_input(int argc, char **argv) { } else { res = cmd_results_new(CMD_INVALID, "input ", "Unknown command %s", argv[1]); } - free_input_config(current_input_config); - current_input_config = old_input_config; + + if (!has_context) { + // clean up the context we created earlier + free_input_config(config->handler_context.input_config); + config->handler_context.input_config = NULL; + } + return res; } diff --git a/sway/commands/input/accel_profile.c b/sway/commands/input/accel_profile.c index f72b7d48..37d6e133 100644 --- a/sway/commands/input/accel_profile.c +++ b/sway/commands/input/accel_profile.c @@ -9,6 +9,8 @@ struct cmd_results *input_cmd_accel_profile(int argc, char **argv) { if ((error = checkarg(argc, "accel_profile", EXPECTED_AT_LEAST, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "accel_profile", "No input device defined."); diff --git a/sway/commands/input/click_method.c b/sway/commands/input/click_method.c index 22eb15f7..8f1f0aa7 100644 --- a/sway/commands/input/click_method.c +++ b/sway/commands/input/click_method.c @@ -6,12 +6,12 @@ #include "log.h" struct cmd_results *input_cmd_click_method(int argc, char **argv) { - wlr_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; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "click_method", "No input device defined."); diff --git a/sway/commands/input/drag_lock.c b/sway/commands/input/drag_lock.c index 1783978a..8273a7d4 100644 --- a/sway/commands/input/drag_lock.c +++ b/sway/commands/input/drag_lock.c @@ -9,6 +9,8 @@ struct cmd_results *input_cmd_drag_lock(int argc, char **argv) { if ((error = checkarg(argc, "drag_lock", EXPECTED_AT_LEAST, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "drag_lock", "No input device defined."); diff --git a/sway/commands/input/dwt.c b/sway/commands/input/dwt.c index 8108a110..995a2f47 100644 --- a/sway/commands/input/dwt.c +++ b/sway/commands/input/dwt.c @@ -9,6 +9,8 @@ struct cmd_results *input_cmd_dwt(int argc, char **argv) { if ((error = checkarg(argc, "dwt", EXPECTED_AT_LEAST, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "dwt", "No input device defined."); } diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c index a1bfbacd..2217f5ce 100644 --- a/sway/commands/input/events.c +++ b/sway/commands/input/events.c @@ -6,16 +6,18 @@ #include "log.h" struct cmd_results *input_cmd_events(int argc, char **argv) { - wlr_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; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "events", "No input device defined."); } + wlr_log(L_DEBUG, "events for device: %s", + current_input_config->identifier); struct input_config *new_config = new_input_config(current_input_config->identifier); diff --git a/sway/commands/input/left_handed.c b/sway/commands/input/left_handed.c index 35740df3..94b8e03e 100644 --- a/sway/commands/input/left_handed.c +++ b/sway/commands/input/left_handed.c @@ -9,6 +9,8 @@ struct cmd_results *input_cmd_left_handed(int argc, char **argv) { if ((error = checkarg(argc, "left_handed", EXPECTED_AT_LEAST, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "left_handed", "No input device defined."); diff --git a/sway/commands/input/middle_emulation.c b/sway/commands/input/middle_emulation.c index 7bc08ae6..a551fd51 100644 --- a/sway/commands/input/middle_emulation.c +++ b/sway/commands/input/middle_emulation.c @@ -9,6 +9,8 @@ struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) { if ((error = checkarg(argc, "middle_emulation", EXPECTED_AT_LEAST, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "middle_emulation", "No input device defined."); diff --git a/sway/commands/input/natural_scroll.c b/sway/commands/input/natural_scroll.c index a7dcdc2c..c4e19b78 100644 --- a/sway/commands/input/natural_scroll.c +++ b/sway/commands/input/natural_scroll.c @@ -9,6 +9,8 @@ struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) { if ((error = checkarg(argc, "natural_scroll", EXPECTED_AT_LEAST, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "natural_scoll", "No input device defined."); diff --git a/sway/commands/input/pointer_accel.c b/sway/commands/input/pointer_accel.c index d2261a63..171063aa 100644 --- a/sway/commands/input/pointer_accel.c +++ b/sway/commands/input/pointer_accel.c @@ -9,6 +9,8 @@ struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { if ((error = checkarg(argc, "pointer_accel", EXPECTED_AT_LEAST, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "pointer_accel", "No input device defined."); diff --git a/sway/commands/input/scroll_method.c b/sway/commands/input/scroll_method.c index 035262cf..0a1c57ac 100644 --- a/sway/commands/input/scroll_method.c +++ b/sway/commands/input/scroll_method.c @@ -9,6 +9,8 @@ struct cmd_results *input_cmd_scroll_method(int argc, char **argv) { if ((error = checkarg(argc, "scroll_method", EXPECTED_AT_LEAST, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "scroll_method", "No input device defined."); diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c index ecab9a5b..e7f03058 100644 --- a/sway/commands/input/tap.c +++ b/sway/commands/input/tap.c @@ -6,11 +6,12 @@ #include "log.h" struct cmd_results *input_cmd_tap(int argc, char **argv) { - wlr_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; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "tap", "No input device defined."); } diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c index 25db1a33..867e65d3 100644 --- a/sway/commands/input/xkb_layout.c +++ b/sway/commands/input/xkb_layout.c @@ -5,11 +5,12 @@ #include "log.h" struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { - wlr_log(L_DEBUG, "xkb layout for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_layout", EXPECTED_EQUAL_TO, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "xkb_layout", "No input device defined."); } diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c index 819b796b..e8c8e04e 100644 --- a/sway/commands/input/xkb_model.c +++ b/sway/commands/input/xkb_model.c @@ -5,11 +5,12 @@ #include "log.h" struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { - wlr_log(L_DEBUG, "xkb model for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_model", EXPECTED_EQUAL_TO, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "xkb_model", "No input device defined."); } diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c index ff5f83ec..e9ddd6e3 100644 --- a/sway/commands/input/xkb_options.c +++ b/sway/commands/input/xkb_options.c @@ -5,11 +5,12 @@ #include "log.h" struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { - wlr_log(L_DEBUG, "xkb options for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_options", EXPECTED_EQUAL_TO, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "xkb_options", "No input device defined."); } diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c index aafe0003..926d0ac1 100644 --- a/sway/commands/input/xkb_rules.c +++ b/sway/commands/input/xkb_rules.c @@ -5,11 +5,12 @@ #include "log.h" struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { - wlr_log(L_DEBUG, "xkb rules for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_rules", EXPECTED_EQUAL_TO, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "xkb_rules", "No input device defined."); } diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c index 89a61fdc..0e3ffd41 100644 --- a/sway/commands/input/xkb_variant.c +++ b/sway/commands/input/xkb_variant.c @@ -5,11 +5,12 @@ #include "log.h" struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { - wlr_log(L_DEBUG, "xkb variant for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_variant", EXPECTED_EQUAL_TO, 1))) { return error; } + struct input_config *current_input_config = + config->handler_context.input_config; if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "xkb_variant", "No input device defined."); } diff --git a/sway/config.c b/sway/config.c index 5ec45b17..54357625 100644 --- a/sway/config.c +++ b/sway/config.c @@ -54,6 +54,8 @@ static void free_mode(struct sway_mode *mode) { } void free_config(struct sway_config *config) { + config_clear_handler_context(config); + int i; if (!config) { @@ -480,6 +482,11 @@ bool load_include_configs(const char *path, struct sway_config *config) { return true; } +void config_clear_handler_context(struct sway_config *config) { + free_input_config(config->handler_context.input_config); + + memset(&config->handler_context, 0, sizeof(config->handler_context)); +} bool read_config(FILE *file, struct sway_config *config) { bool success = true; @@ -592,8 +599,6 @@ bool read_config(FILE *file, struct sway_config *config) { case CMD_BLOCK_INPUT: wlr_log(L_DEBUG, "End of input block"); - free_input_config(current_input_config); - current_input_config = NULL; block = CMD_BLOCK_END; break; @@ -635,6 +640,7 @@ bool read_config(FILE *file, struct sway_config *config) { default:; } + config_clear_handler_context(config); default:; } free(line); -- cgit v1.2.3 From cc3c713889e529c74888d9cd89af7039bfbae20c Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 20 Jan 2018 11:44:34 -0500 Subject: seat config handler context --- include/sway/config.h | 1 + include/sway/input/input-manager.h | 2 -- sway/commands.c | 1 - sway/commands/input.c | 3 +++ sway/commands/seat.c | 25 +++++++++++++++++++++---- sway/commands/seat/attach.c | 2 ++ sway/commands/seat/fallback.c | 3 +++ sway/config.c | 2 +- 8 files changed, 31 insertions(+), 8 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 1ab96b51..27fae0c6 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -354,6 +354,7 @@ struct sway_config { // Context for command handlers struct { struct input_config *input_config; + struct seat_config *seat_config; } handler_context; }; diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 8388f930..58a93fe3 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -5,8 +5,6 @@ #include "sway/config.h" #include "list.h" -extern struct seat_config *current_seat_config; - /** * The global singleton input manager * TODO: make me not a global diff --git a/sway/commands.c b/sway/commands.c index fd2e1514..414ef809 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -86,7 +86,6 @@ void apply_seat_config(struct seat_config *seat) { list_add(config->seat_configs, seat); } - current_seat_config = seat; sway_input_manager_apply_seat_config(input_manager, seat); } diff --git a/sway/commands/input.c b/sway/commands/input.c index 5de65621..fa9cf05a 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -28,6 +28,9 @@ struct cmd_results *cmd_input(int argc, char **argv) { if (!has_context) { // caller did not give a context so create one just for this command config->handler_context.input_config = new_input_config(argv[0]); + if (!config->handler_context.input_config) { + return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); + } } int argc_new = argc-2; diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 6284002b..45079616 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -11,8 +11,12 @@ struct cmd_results *cmd_seat(int argc, char **argv) { } if (config->reading && strcmp("{", argv[1]) == 0) { - current_seat_config = new_seat_config(argv[0]); - wlr_log(L_DEBUG, "entering seat block: %s", current_seat_config->name); + free_seat_config(config->handler_context.seat_config); + config->handler_context.seat_config = new_seat_config(argv[0]); + if (!config->handler_context.seat_config) { + return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); + } + wlr_log(L_DEBUG, "entering seat block: %s", argv[0]); return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); } @@ -20,11 +24,18 @@ struct cmd_results *cmd_seat(int argc, char **argv) { return error; } + bool has_context = (config->handler_context.seat_config != NULL); + if (!has_context) { + config->handler_context.seat_config = new_seat_config(argv[0]); + if (!config->handler_context.seat_config) { + return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); + } + } + int argc_new = argc-2; char **argv_new = argv+2; struct cmd_results *res; - current_seat_config = new_seat_config(argv[0]); if (strcasecmp("attach", argv[1]) == 0) { res = seat_cmd_attach(argc_new, argv_new); } else if (strcasecmp("fallback", argv[1]) == 0) { @@ -32,6 +43,12 @@ struct cmd_results *cmd_seat(int argc, char **argv) { } else { res = cmd_results_new(CMD_INVALID, "seat ", "Unknown command %s", argv[1]); } - current_seat_config = NULL; + + if (!has_context) { + // clean up the context we created earlier + free_seat_config(config->handler_context.seat_config); + config->handler_context.seat_config = NULL; + } + return res; } diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c index 80ec63ce..3e771c00 100644 --- a/sway/commands/seat/attach.c +++ b/sway/commands/seat/attach.c @@ -12,6 +12,8 @@ struct cmd_results *seat_cmd_attach(int argc, char **argv) { if ((error = checkarg(argc, "attach", EXPECTED_AT_LEAST, 1))) { return error; } + struct seat_config *current_seat_config = + config->handler_context.seat_config; if (!current_seat_config) { return cmd_results_new(CMD_FAILURE, "attach", "No seat defined"); } diff --git a/sway/commands/seat/fallback.c b/sway/commands/seat/fallback.c index 7c129aae..56feaab5 100644 --- a/sway/commands/seat/fallback.c +++ b/sway/commands/seat/fallback.c @@ -9,6 +9,8 @@ struct cmd_results *seat_cmd_fallback(int argc, char **argv) { if ((error = checkarg(argc, "fallback", EXPECTED_AT_LEAST, 1))) { return error; } + struct seat_config *current_seat_config = + config->handler_context.seat_config; if (!current_seat_config) { return cmd_results_new(CMD_FAILURE, "fallback", "No seat defined"); } @@ -20,6 +22,7 @@ struct cmd_results *seat_cmd_fallback(int argc, char **argv) { } else if (strcasecmp(argv[0], "false") == 0) { new_config->fallback = 0; } else { + free_seat_config(new_config); return cmd_results_new(CMD_INVALID, "fallback", "Expected 'fallback '"); } diff --git a/sway/config.c b/sway/config.c index 54357625..2683d6bc 100644 --- a/sway/config.c +++ b/sway/config.c @@ -484,6 +484,7 @@ bool load_include_configs(const char *path, struct sway_config *config) { void config_clear_handler_context(struct sway_config *config) { free_input_config(config->handler_context.input_config); + free_seat_config(config->handler_context.seat_config); memset(&config->handler_context, 0, sizeof(config->handler_context)); } @@ -604,7 +605,6 @@ bool read_config(FILE *file, struct sway_config *config) { case CMD_BLOCK_SEAT: wlr_log(L_DEBUG, "End of seat block"); - current_seat_config = NULL; block = CMD_BLOCK_END; break; -- cgit v1.2.3 From c353e01c85049cfbc09510657e453b6aa5fd9c2d Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 20 Jan 2018 14:10:11 -0500 Subject: add kill command --- include/sway/config.h | 1 + include/sway/input/input-manager.h | 3 +++ include/sway/view.h | 1 + sway/commands.c | 1 + sway/commands/kill.c | 25 +++++++++++++++++++++++++ sway/desktop/wl_shell.c | 9 +++++++++ sway/desktop/xdg_shell_v6.c | 11 +++++++++++ sway/desktop/xwayland.c | 8 ++++++++ sway/input/input-manager.c | 11 +++++++++++ sway/input/keyboard.c | 9 ++++++--- sway/meson.build | 1 + 11 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 sway/commands/kill.c (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 27fae0c6..be29082e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -355,6 +355,7 @@ struct sway_config { struct { struct input_config *input_config; struct seat_config *seat_config; + struct sway_seat *seat; } handler_context; }; diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 58a93fe3..2bf297ce 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -43,4 +43,7 @@ void sway_input_manager_apply_input_config(struct sway_input_manager *input, void sway_input_manager_apply_seat_config(struct sway_input_manager *input, struct seat_config *seat_config); +struct sway_seat *sway_input_manager_get_default_seat( + struct sway_input_manager *input); + #endif diff --git a/include/sway/view.h b/include/sway/view.h index 08c5480b..240ffaa5 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -92,6 +92,7 @@ struct sway_view { void (*set_position)(struct sway_view *view, double ox, double oy); void (*set_activated)(struct sway_view *view, bool activated); + void (*close)(struct sway_view *view); } iface; // only used for unmanaged views (shell specific) diff --git a/sway/commands.c b/sway/commands.c index 414ef809..28943963 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -132,6 +132,7 @@ static struct cmd_handler handlers[] = { { "exit", cmd_exit }, { "include", cmd_include }, { "input", cmd_input }, + { "kill", cmd_kill }, { "output", cmd_output }, { "seat", cmd_seat }, { "set", cmd_set }, diff --git a/sway/commands/kill.c b/sway/commands/kill.c new file mode 100644 index 00000000..4bbf94e5 --- /dev/null +++ b/sway/commands/kill.c @@ -0,0 +1,25 @@ +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" +#include "sway/view.h" +#include "sway/commands.h" + +struct cmd_results *cmd_kill(int argc, char **argv) { + struct sway_seat *seat = config->handler_context.seat; + if (!seat) { + seat = sway_input_manager_get_default_seat(input_manager); + } + + // TODO context for arbitrary sway containers (when we get criteria + // working) will make seat context not explicitly required + if (!seat) { + return cmd_results_new(CMD_FAILURE, NULL, "no seat context given"); + } + + struct sway_view *view = seat->focus->sway_view; + + if (view->iface.close) { + view->iface.close(view); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index e34f5160..0cde6583 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -51,6 +51,14 @@ static void set_activated(struct sway_view *view, bool activated) { // no way to activate wl_shell } +static void close(struct sway_view *view) { + if (!assert_wl_shell(view)) { + return; + } + + wl_client_destroy(view->wlr_wl_shell_surface->client); +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_wl_shell_surface *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -103,6 +111,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { sway_view->iface.set_size = set_size; sway_view->iface.set_position = set_position; sway_view->iface.set_activated = set_activated; + sway_view->iface.close = close; sway_view->wlr_wl_shell_surface = shell_surface; sway_view->sway_wl_shell_surface = sway_surface; sway_view->surface = shell_surface->surface; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index df48345c..4b50093f 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -57,6 +57,16 @@ static void set_activated(struct sway_view *view, bool activated) { } } +static void close(struct sway_view *view) { + if (!assert_xdg(view)) { + return; + } + struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; + if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { + wlr_xdg_toplevel_v6_send_close(surface); + } +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xdg_surface_v6 *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -107,6 +117,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_view->iface.set_size = set_size; sway_view->iface.set_position = set_position; sway_view->iface.set_activated = set_activated; + sway_view->iface.close = close; sway_view->wlr_xdg_surface_v6 = xdg_surface; sway_view->sway_xdg_surface_v6 = sway_surface; sway_view->surface = xdg_surface->surface; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index a4d9687d..7603d3ca 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -80,6 +80,13 @@ static void set_activated(struct sway_view *view, bool activated) { wlr_xwayland_surface_activate(surface, activated); } +static void close(struct sway_view *view) { + if (!assert_xwayland(view)) { + return; + } + wlr_xwayland_surface_close(view->wlr_xwayland_surface); +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -192,6 +199,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { sway_view->iface.set_size = set_size; sway_view->iface.set_position = set_position; sway_view->iface.set_activated = set_activated; + sway_view->iface.close = close; sway_view->wlr_xwayland_surface = xsurface; sway_view->sway_xwayland_surface = sway_surface; sway_view->surface = xsurface->surface; diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 26cf5035..7b19991b 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -369,3 +369,14 @@ void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { sway_seat_configure_xcursor(seat); } } + +struct sway_seat *sway_input_manager_get_default_seat( + struct sway_input_manager *input) { + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + if (strcmp(seat->wlr_seat->name, "seat0") == 0) { + return seat; + } + } + return seat; +} diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 5827a1ca..6dc57d46 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -89,9 +89,12 @@ static bool binding_matches_key_state(struct sway_binding *binding, return false; } -static void binding_execute_command(struct sway_binding *binding) { +static void keyboard_execute_command(struct sway_keyboard *keyboard, + struct sway_binding *binding) { wlr_log(L_DEBUG, "running command for binding: %s", binding->command); + config_clear_handler_context(config); + config->handler_context.seat = keyboard->seat_device->sway_seat; struct cmd_results *results = handle_command(binding->command); if (results->status != CMD_SUCCESS) { wlr_log(L_DEBUG, "could not run command for binding: %s", @@ -160,7 +163,7 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, } if (match) { - binding_execute_command(binding); + keyboard_execute_command(keyboard, binding); return true; } } @@ -267,7 +270,7 @@ static bool keyboard_execute_bindcode(struct sway_keyboard *keyboard, for (int i = 0; i < keycode_bindings->length; ++i) { struct sway_binding *binding = keycode_bindings->items[i]; if (binding_matches_keycodes(wlr_keyboard, binding, event)) { - binding_execute_command(binding); + keyboard_execute_command(keyboard, binding); return true; } } diff --git a/sway/meson.build b/sway/meson.build index 30ec166b..d5dead42 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -10,6 +10,7 @@ sway_sources = files( 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', + 'commands/kill.c', 'commands/include.c', 'commands/input.c', 'commands/seat.c', -- cgit v1.2.3 From 6a1d71b8b8f33bdea3fb41bcd0de9439c0452682 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 20 Jan 2018 16:21:45 -0500 Subject: basic command criteria --- include/sway/config.h | 1 + include/sway/container.h | 2 + include/sway/criteria.h | 42 +++++ sway/commands.c | 68 +++++++- sway/commands/kill.c | 8 +- sway/criteria.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++ sway/meson.build | 2 + sway/tree/container.c | 22 +++ 8 files changed, 549 insertions(+), 9 deletions(-) create mode 100644 include/sway/criteria.h create mode 100644 sway/criteria.c (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index be29082e..d07a71df 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -356,6 +356,7 @@ struct sway_config { struct input_config *input_config; struct seat_config *seat_config; struct sway_seat *seat; + swayc_t *current_container; } handler_context; }; diff --git a/include/sway/container.h b/include/sway/container.h index 9a5e312b..a99e2694 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -145,4 +145,6 @@ swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); swayc_t *swayc_at(swayc_t *parent, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); +void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data); + #endif diff --git a/include/sway/criteria.h b/include/sway/criteria.h new file mode 100644 index 00000000..c5ed9857 --- /dev/null +++ b/include/sway/criteria.h @@ -0,0 +1,42 @@ +#ifndef _SWAY_CRITERIA_H +#define _SWAY_CRITERIA_H + +#include "container.h" +#include "list.h" + +/** + * Maps criteria (as a list of criteria tokens) to a command list. + * + * A list of tokens together represent a single criteria string (e.g. + * '[class="abc" title="xyz"]' becomes two criteria tokens). + * + * for_window: Views matching all criteria will have the bound command list + * executed on them. + * + * Set via `for_window `. + */ +struct criteria { + list_t *tokens; // struct crit_token, contains compiled regex. + char *crit_raw; // entire criteria string (for logging) + + char *cmdlist; +}; + +int criteria_cmp(const void *item, const void *data); +void free_criteria(struct criteria *crit); + +// Pouplate list with crit_tokens extracted from criteria string, returns error +// string or NULL if successful. +char *extract_crit_tokens(list_t *tokens, const char *criteria); + +// Returns list of criteria that match given container. These criteria have +// been set with `for_window` commands and have an associated cmdlist. +list_t *criteria_for(swayc_t *cont); + +// Returns a list of all containers that match the given list of tokens. +list_t *container_for(list_t *tokens); + +// Returns true if any criteria in the given list matches this container +bool criteria_any(swayc_t *cont, list_t *criteria); + +#endif diff --git a/sway/commands.c b/sway/commands.c index 28943963..c1e25c5f 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -8,6 +8,7 @@ #include #include "sway/commands.h" #include "sway/config.h" +#include "sway/criteria.h" #include "sway/security.h" #include "sway/input/input-manager.h" #include "stringop.h" @@ -201,9 +202,41 @@ struct cmd_results *handle_command(char *_exec) { char *head = exec; char *cmdlist; char *cmd; + list_t *containers = NULL; head = exec; do { + // Extract criteria (valid for this command list only). + bool has_criteria = false; + if (*head == '[') { + has_criteria = true; + ++head; + char *criteria_string = argsep(&head, "]"); + if (head) { + ++head; + list_t *tokens = create_list(); + char *error; + + if ((error = extract_crit_tokens(tokens, criteria_string))) { + wlr_log(L_DEBUG, "criteria string parse error: %s", error); + results = cmd_results_new(CMD_INVALID, criteria_string, + "Can't parse criteria string: %s", error); + free(error); + free(tokens); + goto cleanup; + } + containers = container_for(tokens); + + free(tokens); + } else { + if (!results) { + results = cmd_results_new(CMD_INVALID, criteria_string, "Unmatched ["); + } + goto cleanup; + } + // Skip leading whitespace + head += strspn(head, whitespace); + } // Split command list cmdlist = argsep(&head, ";"); cmdlist += strspn(cmdlist, whitespace); @@ -236,16 +269,35 @@ struct cmd_results *handle_command(char *_exec) { free_argv(argc, argv); goto cleanup; } - struct cmd_results *res = handler->handle(argc-1, argv+1); - if (res->status != CMD_SUCCESS) { - free_argv(argc, argv); - if (results) { - free_cmd_results(results); + + if (!has_criteria) { + config->handler_context.current_container = NULL; + struct cmd_results *res = handler->handle(argc-1, argv+1); + if (res->status != CMD_SUCCESS) { + free_argv(argc, argv); + if (results) { + free_cmd_results(results); + } + results = res; + goto cleanup; + } + free_cmd_results(res); + } else { + wlr_log(L_DEBUG, "@@ running command on containers"); + for (int i = 0; i < containers->length; ++i) { + config->handler_context.current_container = containers->items[i]; + struct cmd_results *res = handler->handle(argc-1, argv+1); + if (res->status != CMD_SUCCESS) { + free_argv(argc, argv); + if (results) { + free_cmd_results(results); + } + results = res; + goto cleanup; + } + free_cmd_results(res); } - results = res; - goto cleanup; } - free_cmd_results(res); free_argv(argc, argv); } while(cmdlist); } while(head); diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 4bbf94e5..f0e3722a 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -15,7 +15,13 @@ struct cmd_results *cmd_kill(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, NULL, "no seat context given"); } - struct sway_view *view = seat->focus->sway_view; + struct sway_view *view = NULL; + + if (config->handler_context.current_container) { + view = config->handler_context.current_container->sway_view; + } else { + view = seat->focus->sway_view; + } if (view->iface.close) { view->iface.close(view); diff --git a/sway/criteria.c b/sway/criteria.c new file mode 100644 index 00000000..c15f6354 --- /dev/null +++ b/sway/criteria.c @@ -0,0 +1,413 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include +#include "sway/criteria.h" +#include "sway/container.h" +#include "sway/config.h" +#include "sway/view.h" +#include "stringop.h" +#include "list.h" +#include "log.h" + +enum criteria_type { // *must* keep in sync with criteria_strings[] + CRIT_APP_ID, + CRIT_CLASS, + CRIT_CON_ID, + CRIT_CON_MARK, + CRIT_FLOATING, + CRIT_ID, + CRIT_INSTANCE, + CRIT_TILING, + CRIT_TITLE, + CRIT_URGENT, + CRIT_WINDOW_ROLE, + CRIT_WINDOW_TYPE, + CRIT_WORKSPACE, + CRIT_LAST +}; + +static const char * const criteria_strings[CRIT_LAST] = { + [CRIT_APP_ID] = "app_id", + [CRIT_CLASS] = "class", + [CRIT_CON_ID] = "con_id", + [CRIT_CON_MARK] = "con_mark", + [CRIT_FLOATING] = "floating", + [CRIT_ID] = "id", + [CRIT_INSTANCE] = "instance", + [CRIT_TILING] = "tiling", + [CRIT_TITLE] = "title", + [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ... + [CRIT_WINDOW_ROLE] = "window_role", + [CRIT_WINDOW_TYPE] = "window_type", + [CRIT_WORKSPACE] = "workspace" +}; + +/** + * A single criteria token (ie. value/regex pair), + * e.g. 'class="some class regex"'. + */ +struct crit_token { + enum criteria_type type; + pcre *regex; + char *raw; +}; + +static void free_crit_token(struct crit_token *crit) { + pcre_free(crit->regex); + free(crit->raw); + free(crit); +} + +static void free_crit_tokens(list_t *crit_tokens) { + for (int i = 0; i < crit_tokens->length; i++) { + free_crit_token(crit_tokens->items[i]); + } + list_free(crit_tokens); +} + +// Extracts criteria string from its brackets. Returns new (duplicate) +// substring. +static char *criteria_from(const char *arg) { + char *criteria = NULL; + if (*arg == '[') { + criteria = strdup(arg + 1); + } else { + criteria = strdup(arg); + } + + int last = strlen(criteria) - 1; + if (criteria[last] == ']') { + criteria[last] = '\0'; + } + return criteria; +} + +// Return instances of c found in str. +static int countchr(char *str, char c) { + int found = 0; + for (int i = 0; str[i]; i++) { + if (str[i] == c) { + ++found; + } + } + return found; +} + +// criteria_str is e.g. '[class="some class regex" instance="instance name"]'. +// +// Will create array of pointers in buf, where first is duplicate of given +// string (must be freed) and the rest are pointers to names and values in the +// base string (every other, naturally). argc will be populated with the length +// of buf. +// +// Returns error string or NULL if successful. +static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str) { + wlr_log(L_DEBUG, "Parsing criteria: '%s'", criteria_str); + char *base = criteria_from(criteria_str); + char *head = base; + char *namep = head; // start of criteria name + char *valp = NULL; // start of value + + // We're going to place EOS markers where we need to and fill up an array + // of pointers to the start of each token (either name or value). + int pairs = countchr(base, '='); + int max_tokens = pairs * 2 + 1; // this gives us at least enough slots + + char **argv = *buf = calloc(max_tokens, sizeof(char*)); + argv[0] = base; // this needs to be freed by caller + bool quoted = true; + + *argc = 1; // uneven = name, even = value + while (*head && *argc < max_tokens) { + if (namep != head && *(head - 1) == '\\') { + // escaped character: don't try to parse this + } else if (*head == '=' && namep != head) { + if (*argc % 2 != 1) { + // we're not expecting a name + return strdup("Unable to parse criteria: " + "Found out of place equal sign"); + } else { + // name ends here + char *end = head; // don't want to rewind the head + while (*(end - 1) == ' ') { + --end; + } + *end = '\0'; + if (*(namep) == ' ') { + namep = strrchr(namep, ' ') + 1; + } + argv[*argc] = namep; + *argc += 1; + } + } else if (*head == '"') { + if (*argc % 2 != 0) { + // we're not expecting a value + return strdup("Unable to parse criteria: " + "Found quoted value where it was not expected"); + } else if (!valp) { // value starts here + valp = head + 1; + quoted = true; + } else { + // value ends here + argv[*argc] = valp; + *argc += 1; + *head = '\0'; + valp = NULL; + namep = head + 1; + } + } else if (*argc % 2 == 0 && *head != ' ') { + // parse unquoted values + if (!valp) { + quoted = false; + valp = head; // value starts here + } + } else if (valp && !quoted && *head == ' ') { + // value ends here + argv[*argc] = valp; + *argc += 1; + *head = '\0'; + valp = NULL; + namep = head + 1; + } + head++; + } + + // catch last unquoted value if needed + if (valp && !quoted && !*head) { + argv[*argc] = valp; + *argc += 1; + } + + return NULL; +} + +// Returns error string on failure or NULL otherwise. +static char *parse_criteria_name(enum criteria_type *type, char *name) { + *type = CRIT_LAST; + for (int i = 0; i < CRIT_LAST; i++) { + if (strcmp(criteria_strings[i], name) == 0) { + *type = (enum criteria_type) i; + break; + } + } + if (*type == CRIT_LAST) { + const char *fmt = "Criteria type '%s' is invalid or unsupported."; + int len = strlen(name) + strlen(fmt) - 1; + char *error = malloc(len); + snprintf(error, len, fmt, name); + return error; + } else if (*type == CRIT_URGENT || *type == CRIT_WINDOW_ROLE || + *type == CRIT_WINDOW_TYPE) { + // (we're just being helpful here) + const char *fmt = "\"%s\" criteria currently unsupported, " + "no window will match this"; + int len = strlen(fmt) + strlen(name) - 1; + char *error = malloc(len); + snprintf(error, len, fmt, name); + return error; + } + return NULL; +} + +// Returns error string on failure or NULL otherwise. +static char *generate_regex(pcre **regex, char *value) { + const char *reg_err; + int offset; + + *regex = pcre_compile(value, PCRE_UTF8 | PCRE_UCP, ®_err, &offset, NULL); + + if (!*regex) { + const char *fmt = "Regex compilation (for '%s') failed: %s"; + int len = strlen(fmt) + strlen(value) + strlen(reg_err) - 3; + char *error = malloc(len); + snprintf(error, len, fmt, value, reg_err); + return error; + } + return NULL; +} + +// Test whether the criterion corresponds to the currently focused window +static bool crit_is_focused(const char *value) { + return !strcmp(value, "focused") || !strcmp(value, "__focused__"); +} + +// Populate list with crit_tokens extracted from criteria string, returns error +// string or NULL if successful. +char *extract_crit_tokens(list_t *tokens, const char * const criteria) { + int argc; + char **argv = NULL, *error = NULL; + if ((error = crit_tokens(&argc, &argv, criteria))) { + goto ect_cleanup; + } + for (int i = 1; i + 1 < argc; i += 2) { + char* name = argv[i], *value = argv[i + 1]; + struct crit_token *token = calloc(1, sizeof(struct crit_token)); + token->raw = strdup(value); + + if ((error = parse_criteria_name(&token->type, name))) { + free_crit_token(token); + goto ect_cleanup; + } else if (token->type == CRIT_URGENT || crit_is_focused(value)) { + wlr_log(L_DEBUG, "%s -> \"%s\"", name, value); + list_add(tokens, token); + } else if((error = generate_regex(&token->regex, value))) { + free_crit_token(token); + goto ect_cleanup; + } else { + wlr_log(L_DEBUG, "%s -> /%s/", name, value); + list_add(tokens, token); + } + } +ect_cleanup: + free(argv[0]); // base string + free(argv); + return error; +} + +static int regex_cmp(const char *item, const pcre *regex) { + return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); +} + +// test a single view if it matches list of criteria tokens (all of them). +static bool criteria_test(swayc_t *cont, list_t *tokens) { + if (cont->type != C_VIEW) { + return false; + } + struct sway_view *view = cont->sway_view; + + int matches = 0; + for (int i = 0; i < tokens->length; i++) { + struct crit_token *crit = tokens->items[i]; + switch (crit->type) { + case CRIT_CLASS: // TODO + break; + case CRIT_CON_ID: { + char *endptr; + size_t crit_id = strtoul(crit->raw, &endptr, 10); + + if (*endptr == 0 && cont->id == crit_id) { + ++matches; + } + break; + } + case CRIT_CON_MARK: // TODO + break; + case CRIT_FLOATING: // TODO + break; + case CRIT_ID: // TODO + break; + case CRIT_APP_ID: + if (!view->iface.get_prop) { + break; + } + + const char *app_id = + cont->sway_view->iface.get_prop(view, VIEW_PROP_APP_ID); + + if (!app_id) { + break; + } + + if (crit->regex && regex_cmp(app_id, crit->regex) == 0) { + matches++; + } + break; + case CRIT_INSTANCE: // TODO + break; + case CRIT_TILING: // TODO + break; + case CRIT_TITLE: + if (!cont->name) { + // ignore + } else if (crit->regex && regex_cmp(cont->name, crit->regex) == 0) { + matches++; + } + break; + case CRIT_URGENT: // "latest" or "oldest" + break; + case CRIT_WINDOW_ROLE: + break; + case CRIT_WINDOW_TYPE: + break; + case CRIT_WORKSPACE: // TODO + break; + default: + sway_abort("Invalid criteria type (%i)", crit->type); + break; + } + } + return matches == tokens->length; +} + +int criteria_cmp(const void *a, const void *b) { + if (a == b) { + return 0; + } else if (!a) { + return -1; + } else if (!b) { + return 1; + } + const struct criteria *crit_a = a, *crit_b = b; + int cmp = lenient_strcmp(crit_a->cmdlist, crit_b->cmdlist); + if (cmp != 0) { + return cmp; + } + return lenient_strcmp(crit_a->crit_raw, crit_b->crit_raw); +} + +void free_criteria(struct criteria *crit) { + if (crit->tokens) { + free_crit_tokens(crit->tokens); + } + if (crit->cmdlist) { + free(crit->cmdlist); + } + if (crit->crit_raw) { + free(crit->crit_raw); + } + free(crit); +} + +bool criteria_any(swayc_t *cont, list_t *criteria) { + for (int i = 0; i < criteria->length; i++) { + struct criteria *bc = criteria->items[i]; + if (criteria_test(cont, bc->tokens)) { + return true; + } + } + return false; +} + +list_t *criteria_for(swayc_t *cont) { + list_t *criteria = config->criteria, *matches = create_list(); + for (int i = 0; i < criteria->length; i++) { + struct criteria *bc = criteria->items[i]; + if (criteria_test(cont, bc->tokens)) { + list_add(matches, bc); + } + } + return matches; +} + +struct list_tokens { + list_t *list; + list_t *tokens; +}; + +static void container_match_add(swayc_t *container, struct list_tokens *list_tokens) { + if (criteria_test(container, list_tokens->tokens)) { + list_add(list_tokens->list, container); + } +} + +list_t *container_for(list_t *tokens) { + struct list_tokens list_tokens = (struct list_tokens){create_list(), tokens}; + + container_map(&root_container, (void (*)(swayc_t *, void *))container_match_add, &list_tokens); + + // TODO look in the scratchpad + + return list_tokens.list; +} diff --git a/sway/meson.build b/sway/meson.build index d5dead42..46d79d44 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -38,6 +38,7 @@ sway_sources = files( 'config/output.c', 'config/seat.c', 'config/input.c', + 'criteria.c', 'ipc-json.c', 'ipc-server.c', 'desktop/output.c', @@ -51,6 +52,7 @@ sway_sources = files( ) sway_deps = [ + pcre, pixman, wayland_server, jsonc, diff --git a/sway/tree/container.c b/sway/tree/container.c index d241f69a..e224539f 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -321,3 +321,25 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, return NULL; } + +void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { + if (container) { + int i; + if (container->children) { + for (i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; + container_map(child, f, data); + } + } + // TODO + /* + if (container->floating) { + for (i = 0; i < container->floating->length; ++i) { + swayc_t *child = container->floating->items[i]; + container_map(child, f, data); + } + } + */ + f(container, data); + } +} -- cgit v1.2.3 From 874f009866abaf8ca43ed4cd88a69d22a3fbfc5a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 12:15:31 -0400 Subject: move tree includes to their own directory --- include/sway/config.h | 4 +- include/sway/container.h | 169 ------------------------------------------ include/sway/criteria.h | 2 +- include/sway/ipc-json.h | 2 +- include/sway/ipc-server.h | 4 +- include/sway/layout.h | 43 ----------- include/sway/tree/container.h | 136 +++++++++++++++++++++++++++++++++ include/sway/tree/layout.h | 51 +++++++++++++ include/sway/tree/view.h | 116 +++++++++++++++++++++++++++++ include/sway/tree/workspace.h | 26 +++++++ include/sway/view.h | 120 ------------------------------ include/sway/workspace.h | 20 ----- sway/commands/exec_always.c | 4 +- sway/commands/focus.c | 5 +- sway/commands/kill.c | 2 +- sway/commands/layout.c | 4 +- sway/commands/reload.c | 2 +- sway/commands/workspace.c | 2 +- sway/config.c | 2 +- sway/criteria.c | 4 +- sway/desktop/layer_shell.c | 2 +- sway/desktop/output.c | 6 +- sway/desktop/wl_shell.c | 6 +- sway/desktop/xdg_shell_v6.c | 6 +- sway/desktop/xwayland.c | 6 +- sway/input/cursor.c | 2 +- sway/input/seat.c | 4 +- sway/ipc-json.c | 2 +- sway/main.c | 2 +- sway/tree/container.c | 10 +-- sway/tree/layout.c | 6 +- sway/tree/view.c | 7 +- sway/tree/workspace.c | 4 +- 33 files changed, 380 insertions(+), 401 deletions(-) delete mode 100644 include/sway/container.h delete mode 100644 include/sway/layout.h create mode 100644 include/sway/tree/container.h create mode 100644 include/sway/tree/layout.h create mode 100644 include/sway/tree/view.h create mode 100644 include/sway/tree/workspace.h delete mode 100644 include/sway/view.h delete mode 100644 include/sway/workspace.h (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 48a8b0ab..48ebba3b 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -10,8 +10,8 @@ #include #include #include "list.h" -#include "layout.h" -#include "container.h" +#include "tree/layout.h" +#include "tree/container.h" /** * Describes a variable created via the `set` command. diff --git a/include/sway/container.h b/include/sway/container.h deleted file mode 100644 index f200a1a2..00000000 --- a/include/sway/container.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef _SWAY_CONTAINER_H -#define _SWAY_CONTAINER_H -#include -#include -#include -#include -#include "list.h" - -typedef struct sway_container swayc_t; - -extern swayc_t root_container; - -struct sway_view; -struct sway_seat; - -/** - * Different kinds of containers. - * - * This enum is in order. A container will never be inside of a container below - * it on this list. - */ -enum swayc_types { - C_ROOT, /**< The root container. Only one of these ever exists. */ - C_OUTPUT, /**< An output (aka monitor, head, etc). */ - C_WORKSPACE, /**< A workspace. */ - C_CONTAINER, /**< A manually created container. */ - C_VIEW, /**< A view (aka window). */ - - C_TYPES, -}; - -/** - * Different ways to arrange a container. - */ -enum swayc_layouts { - L_NONE, /**< Used for containers that have no layout (views, root) */ - L_HORIZ, - L_VERT, - L_STACKED, - L_TABBED, - L_FLOATING, /**< A psuedo-container, removed from the tree, to hold floating windows */ - - /* Awesome/Monad style auto layouts */ - L_AUTO_LEFT, - L_AUTO_RIGHT, - L_AUTO_TOP, - L_AUTO_BOTTOM, - - L_AUTO_FIRST = L_AUTO_LEFT, - L_AUTO_LAST = L_AUTO_BOTTOM, - - // Keep last - L_LAYOUTS, -}; - -enum swayc_border_types { - B_NONE, /**< No border */ - B_PIXEL, /**< 1px border */ - B_NORMAL, /**< Normal border with title bar */ -}; - -struct sway_root; -struct sway_output; -struct sway_view; - -/** - * Stores information about a container. - * - * The tree is made of these. Views are containers that cannot have children. - */ -struct sway_container { - union { - // TODO: Encapsulate state for other node types as well like C_CONTAINER - struct sway_root *sway_root; // C_ROOT - struct sway_output *sway_output; // C_OUTPUT - struct sway_view *sway_view; // C_VIEW - }; - - /** - * A unique ID to identify this container. Primarily used in the - * get_tree JSON output. - */ - size_t id; - - char *name; - - enum swayc_types type; - enum swayc_layouts layout; - enum swayc_layouts prev_layout; - enum swayc_layouts workspace_layout; - - /** - * The coordinates that this view appear at, relative to the output they - * are located on (output containers have absolute coordinates). - */ - double x, y; - - /** - * Width and height of this container, without borders or gaps. - */ - double width, height; - - list_t *children; - - /** - * The parent of this container. NULL for the root container. - */ - struct sway_container *parent; - - /** - * Number of master views in auto layouts. - */ - size_t nb_master; - - /** - * Number of slave groups (e.g. columns) in auto layouts. - */ - size_t nb_slave_groups; - - /** - * Marks applied to the container, list_t of char*. - */ - list_t *marks; - - struct { - struct wl_signal destroy; - } events; -}; - -void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, - void (*func)(swayc_t *item, void *data), void *data); - -swayc_t *new_output(struct sway_output *sway_output); -swayc_t *new_workspace(swayc_t *output, const char *name); -swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view); - -swayc_t *destroy_output(swayc_t *output); -swayc_t *destroy_view(swayc_t *view); - -swayc_t *next_view_sibling(struct sway_seat *seat); - -/** - * Finds a container based on test criteria. Returns the first container that - * passes the test. - */ -swayc_t *swayc_by_test(swayc_t *container, - bool (*test)(swayc_t *view, void *data), void *data); -/** - * Finds a parent container with the given swayc_type. - */ -swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); -/** - * Maps a container's children over a function. - */ -void container_map(swayc_t *container, - void (*f)(swayc_t *view, void *data), void *data); - -swayc_t *swayc_at(swayc_t *parent, double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy); - -/** - * Apply the function for each child of the container breadth first. - */ -void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), - void *data); - -swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout); - -#endif diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 9b4b4bef..431cfa3a 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -1,7 +1,7 @@ #ifndef _SWAY_CRITERIA_H #define _SWAY_CRITERIA_H -#include "container.h" +#include "tree/container.h" #include "list.h" /** diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index eef5a018..76b7d45b 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -1,7 +1,7 @@ #ifndef _SWAY_IPC_JSON_H #define _SWAY_IPC_JSON_H #include -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/input-manager.h" json_object *ipc_json_get_version(); diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index bcf1c433..db690b6e 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -1,13 +1,15 @@ #ifndef _SWAY_IPC_SERVER_H #define _SWAY_IPC_SERVER_H #include -#include "sway/container.h" +#include "sway/tree/container.h" #include "ipc.h" struct sway_server; void ipc_init(struct sway_server *server); + void ipc_terminate(void); + struct sockaddr_un *ipc_user_sockaddr(void); void ipc_event_window(swayc_t *window, const char *change); diff --git a/include/sway/layout.h b/include/sway/layout.h deleted file mode 100644 index e82c4442..00000000 --- a/include/sway/layout.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _SWAY_LAYOUT_H -#define _SWAY_LAYOUT_H - -#include -#include "sway/container.h" - -enum movement_direction { - MOVE_LEFT, - MOVE_RIGHT, - MOVE_UP, - MOVE_DOWN, - MOVE_PARENT, - MOVE_CHILD, - MOVE_NEXT, - MOVE_PREV, - MOVE_FIRST -}; - -struct sway_container; - -struct sway_root { - struct wlr_output_layout *output_layout; - - struct wl_listener output_layout_change; - - struct wl_list unmanaged_views; // sway_view::unmanaged_view_link - - struct { - struct wl_signal new_container; - } events; -}; - -void init_layout(void); -void add_child(struct sway_container *parent, struct sway_container *child); -swayc_t *add_sibling(swayc_t *parent, swayc_t *child); -struct sway_container *remove_child(struct sway_container *child); -enum swayc_layouts default_layout(struct sway_container *output); -void sort_workspaces(struct sway_container *output); -void arrange_windows(struct sway_container *container, double width, double height); -swayc_t *get_swayc_in_direction(swayc_t *container, - struct sway_seat *seat, enum movement_direction dir); - -#endif diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h new file mode 100644 index 00000000..5a2ae349 --- /dev/null +++ b/include/sway/tree/container.h @@ -0,0 +1,136 @@ +#ifndef _SWAY_CONTAINER_H +#define _SWAY_CONTAINER_H +#include +#include +#include +#include +#include "list.h" + +typedef struct sway_container swayc_t; + +extern swayc_t root_container; + +struct sway_view; +struct sway_seat; + +/** + * Different kinds of containers. + * + * This enum is in order. A container will never be inside of a container below + * it on this list. + */ +enum swayc_types { + C_ROOT, + C_OUTPUT, + C_WORKSPACE, + C_CONTAINER, + C_VIEW, + + C_TYPES, +}; + +enum swayc_layouts { + L_NONE, + L_HORIZ, + L_VERT, + L_STACKED, + L_TABBED, + L_FLOATING, + + // Keep last + L_LAYOUTS, +}; + +enum swayc_border_types { + B_NONE, + B_PIXEL, + B_NORMAL, +}; + +struct sway_root; +struct sway_output; +struct sway_view; + +struct sway_container { + union { + // TODO: Encapsulate state for other node types as well like C_CONTAINER + struct sway_root *sway_root; + struct sway_output *sway_output; + struct sway_view *sway_view; + }; + + /** + * A unique ID to identify this container. Primarily used in the + * get_tree JSON output. + */ + size_t id; + + char *name; + + enum swayc_types type; + enum swayc_layouts layout; + enum swayc_layouts prev_layout; + enum swayc_layouts workspace_layout; + + // TODO convert to layout coordinates + double x, y; + + // does not include borders or gaps. + double width, height; + + list_t *children; + + struct sway_container *parent; + + list_t *marks; // list of char* + + struct { + struct wl_signal destroy; + } events; +}; + +void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, + void (*func)(swayc_t *item, void *data), void *data); + +// TODO only one container create function and pass the type? +swayc_t *new_output(struct sway_output *sway_output); + +swayc_t *new_workspace(swayc_t *output, const char *name); + +swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view); + +swayc_t *destroy_output(swayc_t *output); +swayc_t *destroy_view(swayc_t *view); + +swayc_t *next_view_sibling(struct sway_seat *seat); + +/** + * Finds a container based on test criteria. Returns the first container that + * passes the test. + */ +swayc_t *swayc_by_test(swayc_t *container, + bool (*test)(swayc_t *view, void *data), void *data); + +/** + * Finds a parent container with the given swayc_type. + */ +swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); + +/** + * Maps a container's children over a function. + */ +void container_map(swayc_t *container, + void (*f)(swayc_t *view, void *data), void *data); + +swayc_t *swayc_at(swayc_t *parent, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy); + +/** + * Apply the function for each child of the container breadth first. + */ +void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), + void *data); + +swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout); + +#endif diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h new file mode 100644 index 00000000..39b7fb24 --- /dev/null +++ b/include/sway/tree/layout.h @@ -0,0 +1,51 @@ +#ifndef _SWAY_LAYOUT_H +#define _SWAY_LAYOUT_H + +#include +#include "sway/tree/container.h" + +enum movement_direction { + MOVE_LEFT, + MOVE_RIGHT, + MOVE_UP, + MOVE_DOWN, + MOVE_PARENT, + MOVE_CHILD, + MOVE_NEXT, + MOVE_PREV, + MOVE_FIRST +}; + +struct sway_container; + +struct sway_root { + struct wlr_output_layout *output_layout; + + struct wl_listener output_layout_change; + + struct wl_list unmanaged_views; // sway_view::unmanaged_view_link + + struct { + struct wl_signal new_container; + } events; +}; + +void init_layout(void); + +void add_child(struct sway_container *parent, struct sway_container *child); + +swayc_t *add_sibling(swayc_t *parent, swayc_t *child); + +struct sway_container *remove_child(struct sway_container *child); + +enum swayc_layouts default_layout(struct sway_container *output); + +void sort_workspaces(struct sway_container *output); + +void arrange_windows(struct sway_container *container, + double width, double height); + +swayc_t *get_swayc_in_direction(swayc_t *container, + struct sway_seat *seat, enum movement_direction dir); + +#endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h new file mode 100644 index 00000000..e5f53f4e --- /dev/null +++ b/include/sway/tree/view.h @@ -0,0 +1,116 @@ +#ifndef _SWAY_VIEW_H +#define _SWAY_VIEW_H +#include +#include +#include +#include + +struct sway_container; +struct sway_view; + +struct sway_xdg_surface_v6 { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +struct sway_xwayland_surface { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener request_configure; + struct wl_listener unmap_notify; + struct wl_listener map_notify; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +struct sway_wl_shell_surface { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +enum sway_view_type { + SWAY_WL_SHELL_VIEW, + SWAY_XDG_SHELL_V6_VIEW, + SWAY_XWAYLAND_VIEW, + // Keep last + SWAY_VIEW_TYPES, +}; + +enum sway_view_prop { + VIEW_PROP_TITLE, + VIEW_PROP_APP_ID, + VIEW_PROP_CLASS, + VIEW_PROP_INSTANCE, +}; + +struct sway_view { + enum sway_view_type type; + struct sway_container *swayc; + struct wlr_surface *surface; + int width, height; + + union { + struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; + struct wlr_xwayland_surface *wlr_xwayland_surface; + struct wlr_wl_shell_surface *wlr_wl_shell_surface; + }; + + union { + struct sway_xdg_surface_v6 *sway_xdg_surface_v6; + struct sway_xwayland_surface *sway_xwayland_surface; + struct sway_wl_shell_surface *sway_wl_shell_surface; + }; + + struct { + const char *(*get_prop)(struct sway_view *view, + enum sway_view_prop prop); + void (*set_size)(struct sway_view *view, + int width, int height); + void (*set_position)(struct sway_view *view, + double ox, double oy); + void (*set_activated)(struct sway_view *view, bool activated); + void (*close)(struct sway_view *view); + } iface; + + // only used for unmanaged views (shell specific) + struct wl_list unmanaged_view_link; // sway_root::unmanaged views +}; + +const char *view_get_title(struct sway_view *view); + +const char *view_get_app_id(struct sway_view *view); + +const char *view_get_class(struct sway_view *view); + +const char *view_get_instance(struct sway_view *view); + +void view_set_size(struct sway_view *view, int width, int height); + +void view_set_position(struct sway_view *view, double ox, double oy); + +void view_set_activated(struct sway_view *view, bool activated); + +void view_close(struct sway_view *view); + +void view_update_outputs(struct sway_view *view, const struct wlr_box *before); + +#endif diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h new file mode 100644 index 00000000..c8ce40d1 --- /dev/null +++ b/include/sway/tree/workspace.h @@ -0,0 +1,26 @@ +#ifndef _SWAY_WORKSPACE_H +#define _SWAY_WORKSPACE_H + +#include "sway/tree/container.h" + +extern char *prev_workspace_name; + +char *workspace_next_name(const char *output_name); + +swayc_t *workspace_create(const char *name); + +bool workspace_switch(swayc_t *workspace); + +struct sway_container *workspace_by_number(const char* name); + +swayc_t *workspace_by_name(const char*); + +struct sway_container *workspace_output_next(swayc_t *current); + +struct sway_container *workspace_next(swayc_t *current); + +struct sway_container *workspace_output_prev(swayc_t *current); + +struct sway_container *workspace_prev(swayc_t *current); + +#endif diff --git a/include/sway/view.h b/include/sway/view.h deleted file mode 100644 index b2886211..00000000 --- a/include/sway/view.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef _SWAY_VIEW_H -#define _SWAY_VIEW_H -#include -#include -#include -#include - -struct sway_container; -struct sway_view; - -struct sway_xdg_surface_v6 { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -struct sway_xwayland_surface { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener request_configure; - struct wl_listener unmap_notify; - struct wl_listener map_notify; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -struct sway_wl_shell_surface { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -enum sway_view_type { - SWAY_WL_SHELL_VIEW, - SWAY_XDG_SHELL_V6_VIEW, - SWAY_XWAYLAND_VIEW, - // Keep last - SWAY_VIEW_TYPES, -}; - -enum sway_view_prop { - VIEW_PROP_TITLE, - VIEW_PROP_APP_ID, - VIEW_PROP_CLASS, - VIEW_PROP_INSTANCE, -}; - -/** - * sway_view is a state container for surfaces that are arranged in the sway - * tree (shell surfaces). - */ -struct sway_view { - enum sway_view_type type; - struct sway_container *swayc; - struct wlr_surface *surface; - int width, height; - - union { - struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; - struct wlr_xwayland_surface *wlr_xwayland_surface; - struct wlr_wl_shell_surface *wlr_wl_shell_surface; - }; - - union { - struct sway_xdg_surface_v6 *sway_xdg_surface_v6; - struct sway_xwayland_surface *sway_xwayland_surface; - struct sway_wl_shell_surface *sway_wl_shell_surface; - }; - - struct { - const char *(*get_prop)(struct sway_view *view, - enum sway_view_prop prop); - void (*set_size)(struct sway_view *view, - int width, int height); - void (*set_position)(struct sway_view *view, - double ox, double oy); - void (*set_activated)(struct sway_view *view, bool activated); - void (*close)(struct sway_view *view); - } iface; - - // only used for unmanaged views (shell specific) - struct wl_list unmanaged_view_link; // sway_root::unmanaged views -}; - -const char *view_get_title(struct sway_view *view); - -const char *view_get_app_id(struct sway_view *view); - -const char *view_get_class(struct sway_view *view); - -const char *view_get_instance(struct sway_view *view); - -void view_set_size(struct sway_view *view, int width, int height); - -void view_set_position(struct sway_view *view, double ox, double oy); - -void view_set_activated(struct sway_view *view, bool activated); - -void view_close(struct sway_view *view); - -void view_update_outputs(struct sway_view *view, const struct wlr_box *before); - -#endif diff --git a/include/sway/workspace.h b/include/sway/workspace.h deleted file mode 100644 index fee54255..00000000 --- a/include/sway/workspace.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _SWAY_WORKSPACE_H -#define _SWAY_WORKSPACE_H - -#include "sway/container.h" - -extern char *prev_workspace_name; - -char *workspace_next_name(const char *output_name); -swayc_t *workspace_create(const char *name); -bool workspace_switch(swayc_t *workspace); - -struct sway_container *workspace_by_number(const char* name); -swayc_t *workspace_by_name(const char*); - -struct sway_container *workspace_output_next(swayc_t *current); -struct sway_container *workspace_next(swayc_t *current); -struct sway_container *workspace_output_prev(swayc_t *current); -struct sway_container *workspace_prev(swayc_t *current); - -#endif diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 61870c51..954950e7 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -6,8 +6,8 @@ #include #include "sway/commands.h" #include "sway/config.h" -#include "sway/container.h" -#include "sway/workspace.h" +#include "sway/tree/container.h" +#include "sway/tree/workspace.h" #include "log.h" #include "stringop.h" diff --git a/sway/commands/focus.c b/sway/commands/focus.c index f1a8078f..18e9e0bf 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -3,10 +3,11 @@ #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/commands.h" -static bool parse_movement_direction(const char *name, enum movement_direction *out) { +static bool parse_movement_direction(const char *name, + enum movement_direction *out) { if (strcasecmp(name, "left") == 0) { *out = MOVE_LEFT; } else if (strcasecmp(name, "right") == 0) { diff --git a/sway/commands/kill.c b/sway/commands/kill.c index f408ce2a..c0faed7a 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -2,7 +2,7 @@ #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/commands.h" struct cmd_results *cmd_kill(int argc, char **argv) { diff --git a/sway/commands/layout.c b/sway/commands/layout.c index b0fc5d66..2b193136 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -1,8 +1,8 @@ #include #include #include "sway/commands.h" -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "log.h" struct cmd_results *cmd_layout(int argc, char **argv) { diff --git a/sway/commands/reload.c b/sway/commands/reload.c index d54d40db..8cef789b 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -1,6 +1,6 @@ #include "sway/commands.h" #include "sway/config.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" struct cmd_results *cmd_reload(int argc, char **argv) { struct cmd_results *error = NULL; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index fa891398..8751dffe 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -4,7 +4,7 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/input/seat.h" -#include "sway/workspace.h" +#include "sway/tree/workspace.h" #include "list.h" #include "log.h" #include "stringop.h" diff --git a/sway/config.c b/sway/config.c index 213e7680..0b29735a 100644 --- a/sway/config.c +++ b/sway/config.c @@ -24,7 +24,7 @@ #include "sway/input/seat.h" #include "sway/commands.h" #include "sway/config.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "readline.h" #include "stringop.h" #include "list.h" diff --git a/sway/criteria.c b/sway/criteria.c index 2eee331c..b8b581ed 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -4,9 +4,9 @@ #include #include #include "sway/criteria.h" -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/config.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "stringop.h" #include "list.h" #include "log.h" diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index bd62f84a..137b3260 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -7,7 +7,7 @@ #include #include #include "sway/layers.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "sway/output.h" #include "sway/server.h" diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9e7fbcc6..debda396 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -11,14 +11,14 @@ #include #include #include "log.h" -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/layers.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "sway/output.h" #include "sway/server.h" -#include "sway/view.h" +#include "sway/tree/view.h" /** * Rotate a child's position relative to a parent. The parent size is (pw, ph), diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 0356aa81..bb97fad4 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/server.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" #include "log.h" diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 7bc17149..25ffacbb 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/server.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" #include "log.h" diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index f9b5242b..7f66f746 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -5,10 +5,10 @@ #include #include #include -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/server.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/output.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 8a0d1df5..c0e14265 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -7,7 +7,7 @@ #include #include #include "sway/input/cursor.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "list.h" #include "log.h" diff --git a/sway/input/seat.c b/sway/input/seat.c index 648e7914..56b39766 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,13 +1,13 @@ #define _XOPEN_SOURCE 700 #include #include -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/seat.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" #include "sway/output.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "log.h" static void seat_device_destroy(struct sway_seat_device *seat_device) { diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 977f1ecb..ebd5e43a 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -3,7 +3,7 @@ #include #include "log.h" #include "sway/ipc-json.h" -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/output.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" diff --git a/sway/main.c b/sway/main.c index f2f24be3..31bf617b 100644 --- a/sway/main.c +++ b/sway/main.c @@ -18,7 +18,7 @@ #include #include "sway/config.h" #include "sway/server.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "sway/ipc-server.h" #include "ipc-client.h" #include "readline.h" diff --git a/sway/tree/container.c b/sway/tree/container.c index bbafe9ec..805d5644 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -7,14 +7,14 @@ #include #include #include "sway/config.h" -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "sway/output.h" #include "sway/server.h" -#include "sway/view.h" -#include "sway/workspace.h" +#include "sway/tree/view.h" +#include "sway/tree/workspace.h" #include "sway/ipc-server.h" #include "log.h" @@ -82,8 +82,6 @@ static swayc_t *new_swayc(enum swayc_types type) { c->layout = L_NONE; c->workspace_layout = L_NONE; c->type = type; - c->nb_master = 1; - c->nb_slave_groups = 1; if (type != C_VIEW) { c->children = create_list(); } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index de9e7b58..5a15f3a2 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -6,10 +6,10 @@ #include #include #include -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/output.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/input/seat.h" #include "list.h" #include "log.h" diff --git a/sway/tree/view.c b/sway/tree/view.c index 9499adca..20e657a2 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,8 +1,8 @@ #include #include -#include "sway/container.h" -#include "sway/layout.h" -#include "sway/view.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" +#include "sway/tree/view.h" const char *view_get_title(struct sway_view *view) { if (view->iface.get_prop) { @@ -45,6 +45,7 @@ void view_set_size(struct sway_view *view, int width, int height) { } } +// TODO make view coordinates void view_set_position(struct sway_view *view, double ox, double oy) { if (view->iface.set_position) { struct wlr_box box = { diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 861fda4d..3da3fde6 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/workspace.h" +#include "sway/tree/workspace.h" #include "log.h" #include "util.h" -- cgit v1.2.3 From 83d09cf5945ba10a703dc5cc977a6d2814f0fd64 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 14:31:10 -0400 Subject: remove swayc_t typedef --- include/sway/config.h | 5 +++-- include/sway/criteria.h | 4 ++-- include/sway/input/input-manager.h | 4 ++-- include/sway/input/seat.h | 11 +++++----- include/sway/ipc-json.h | 4 ++-- include/sway/ipc-server.h | 2 +- include/sway/tree/container.h | 45 ++++++++++++++++++++------------------ include/sway/tree/layout.h | 7 +++--- include/sway/tree/workspace.h | 14 ++++++------ sway/input/input-manager.c | 4 ++-- 10 files changed, 53 insertions(+), 47 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 48ebba3b..e9910be4 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -356,7 +356,7 @@ struct sway_config { struct input_config *input_config; struct seat_config *seat_config; struct sway_seat *seat; - swayc_t *current_container; + struct sway_container *current_container; } handler_context; }; @@ -416,7 +416,8 @@ void output_get_identifier(char *identifier, size_t len, struct sway_output *output); struct output_config *new_output_config(const char *name); void merge_output_config(struct output_config *dst, struct output_config *src); -void apply_output_config(struct output_config *oc, swayc_t *output); +void apply_output_config(struct output_config *oc, + struct sway_container *output); void free_output_config(struct output_config *oc); /** diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 431cfa3a..ec256ddb 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -31,12 +31,12 @@ char *extract_crit_tokens(list_t *tokens, const char *criteria); // Returns list of criteria that match given container. These criteria have // been set with `for_window` commands and have an associated cmdlist. -list_t *criteria_for(swayc_t *cont); +list_t *criteria_for(struct sway_container *cont); // Returns a list of all containers that match the given list of tokens. list_t *container_for_crit_tokens(list_t *tokens); // Returns true if any criteria in the given list matches this container -bool criteria_any(swayc_t *cont, list_t *criteria); +bool criteria_any(struct sway_container *cont, list_t *criteria); #endif diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index eab7dc90..c6c73dba 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -31,10 +31,10 @@ struct sway_input_manager *sway_input_manager_create( struct sway_server *server); bool sway_input_manager_has_focus(struct sway_input_manager *input, - swayc_t *container); + struct sway_container *container); void sway_input_manager_set_focus(struct sway_input_manager *input, - swayc_t *container); + struct sway_container *container); void sway_input_manager_configure_xcursor(struct sway_input_manager *input); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 1d55bec7..e43e6fd4 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -14,7 +14,7 @@ struct sway_seat_device { struct sway_seat_container { struct sway_seat *seat; - swayc_t *container; + struct sway_container *container; struct wl_list link; // sway_seat::focus_stack @@ -54,9 +54,9 @@ void sway_seat_remove_device(struct sway_seat *seat, void sway_seat_configure_xcursor(struct sway_seat *seat); -void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); +void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); -swayc_t *sway_seat_get_focus(struct sway_seat *seat); +struct sway_container *sway_seat_get_focus(struct sway_seat *seat); /** * Return the last container to be focused for the seat (or the most recently @@ -67,9 +67,10 @@ swayc_t *sway_seat_get_focus(struct sway_seat *seat); * is destroyed, or focus moves to a container with children and we need to * descend into the next leaf in focus order. */ -swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container); +struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, + struct sway_container *container); -swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, +struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, enum swayc_types type); void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index 76b7d45b..3d2fdc4f 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -6,8 +6,8 @@ json_object *ipc_json_get_version(); -json_object *ipc_json_describe_container(swayc_t *c); -json_object *ipc_json_describe_container_recursive(swayc_t *c); +json_object *ipc_json_describe_container(struct sway_container *c); +json_object *ipc_json_describe_container_recursive(struct sway_container *c); json_object *ipc_json_describe_input(struct sway_input_device *device); #endif diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index db690b6e..d73006dc 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -12,6 +12,6 @@ void ipc_terminate(void); struct sockaddr_un *ipc_user_sockaddr(void); -void ipc_event_window(swayc_t *window, const char *change); +void ipc_event_window(struct sway_container *window, const char *change); #endif diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 5a2ae349..5def5e71 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -6,9 +6,7 @@ #include #include "list.h" -typedef struct sway_container swayc_t; - -extern swayc_t root_container; +extern struct sway_container root_container; struct sway_view; struct sway_seat; @@ -89,48 +87,53 @@ struct sway_container { } events; }; -void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, - void (*func)(swayc_t *item, void *data), void *data); +void swayc_descendants_of_type(struct sway_container *root, + enum swayc_types type, + void (*func)(struct sway_container *item, void *data), void *data); // TODO only one container create function and pass the type? -swayc_t *new_output(struct sway_output *sway_output); +struct sway_container *new_output(struct sway_output *sway_output); -swayc_t *new_workspace(swayc_t *output, const char *name); +struct sway_container *new_workspace(struct sway_container *output, + const char *name); -swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view); +struct sway_container *new_view(struct sway_container *sibling, + struct sway_view *sway_view); -swayc_t *destroy_output(swayc_t *output); -swayc_t *destroy_view(swayc_t *view); +struct sway_container *destroy_output(struct sway_container *output); +struct sway_container *destroy_view(struct sway_container *view); -swayc_t *next_view_sibling(struct sway_seat *seat); +struct sway_container *next_view_sibling(struct sway_seat *seat); /** * Finds a container based on test criteria. Returns the first container that * passes the test. */ -swayc_t *swayc_by_test(swayc_t *container, - bool (*test)(swayc_t *view, void *data), void *data); +struct sway_container *swayc_by_test(struct sway_container *container, + bool (*test)(struct sway_container *view, void *data), void *data); /** * Finds a parent container with the given swayc_type. */ -swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); +struct sway_container *swayc_parent_by_type(struct sway_container *container, + enum swayc_types type); /** * Maps a container's children over a function. */ -void container_map(swayc_t *container, - void (*f)(swayc_t *view, void *data), void *data); +void container_map(struct sway_container *container, + void (*f)(struct sway_container *view, void *data), void *data); -swayc_t *swayc_at(swayc_t *parent, double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy); +struct sway_container *swayc_at(struct sway_container *parent, double lx, + double ly, struct wlr_surface **surface, double *sx, double *sy); /** * Apply the function for each child of the container breadth first. */ -void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), - void *data); +void container_for_each_bfs(struct sway_container *con, void (*f)(struct + sway_container *con, void *data), void *data); -swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout); +struct sway_container *swayc_change_layout(struct sway_container *container, + enum swayc_layouts layout); #endif diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 39b7fb24..8bb9e075 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -34,7 +34,8 @@ void init_layout(void); void add_child(struct sway_container *parent, struct sway_container *child); -swayc_t *add_sibling(swayc_t *parent, swayc_t *child); +struct sway_container *add_sibling(struct sway_container *parent, + struct sway_container *child); struct sway_container *remove_child(struct sway_container *child); @@ -45,7 +46,7 @@ void sort_workspaces(struct sway_container *output); void arrange_windows(struct sway_container *container, double width, double height); -swayc_t *get_swayc_in_direction(swayc_t *container, - struct sway_seat *seat, enum movement_direction dir); +struct sway_container *get_swayc_in_direction(struct sway_container + *container, struct sway_seat *seat, enum movement_direction dir); #endif diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index c8ce40d1..d73b29c1 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -7,20 +7,20 @@ extern char *prev_workspace_name; char *workspace_next_name(const char *output_name); -swayc_t *workspace_create(const char *name); +struct sway_container *workspace_create(const char *name); -bool workspace_switch(swayc_t *workspace); +bool workspace_switch(struct sway_container *workspace); struct sway_container *workspace_by_number(const char* name); -swayc_t *workspace_by_name(const char*); +struct sway_container *workspace_by_name(const char*); -struct sway_container *workspace_output_next(swayc_t *current); +struct sway_container *workspace_output_next(struct sway_container *current); -struct sway_container *workspace_next(swayc_t *current); +struct sway_container *workspace_next(struct sway_container *current); -struct sway_container *workspace_output_prev(swayc_t *current); +struct sway_container *workspace_output_prev(struct sway_container *current); -struct sway_container *workspace_prev(swayc_t *current); +struct sway_container *workspace_prev(struct sway_container *current); #endif diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 27c2c72e..d421a03f 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -278,7 +278,7 @@ struct sway_input_manager *sway_input_manager_create( } bool sway_input_manager_has_focus(struct sway_input_manager *input, - swayc_t *container) { + struct sway_container *container) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { if (sway_seat_get_focus(seat) == container) { @@ -290,7 +290,7 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, } void sway_input_manager_set_focus(struct sway_input_manager *input, - swayc_t *container) { + struct sway_container *container) { struct sway_seat *seat ; wl_list_for_each(seat, &input->seats, link) { sway_seat_set_focus(seat, container); -- cgit v1.2.3 From b90099b4b7df8068446c658ab99b58ff83648954 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 16:17:55 -0400 Subject: rename container functions --- include/sway/config.h | 8 +- include/sway/input/seat.h | 2 +- include/sway/tree/container.h | 70 +++++++++------- include/sway/tree/layout.h | 2 +- sway/commands/focus.c | 4 +- sway/commands/kill.c | 2 +- sway/commands/layout.c | 4 +- sway/commands/output.c | 2 +- sway/commands/workspace.c | 12 +-- sway/config/output.c | 4 +- sway/criteria.c | 12 +-- sway/desktop/output.c | 14 ++-- sway/desktop/wl_shell.c | 6 +- sway/desktop/xdg_shell_v6.c | 6 +- sway/desktop/xwayland.c | 18 ++--- sway/input/cursor.c | 8 +- sway/input/seat.c | 34 ++++---- sway/ipc-json.c | 14 ++-- sway/ipc-server.c | 4 +- sway/tree/container.c | 182 +++++++++++++++++++++--------------------- sway/tree/layout.c | 86 ++++++++++---------- sway/tree/workspace.c | 70 ++++++++-------- swaybar/ipc.c | 2 +- 23 files changed, 287 insertions(+), 279 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index e9910be4..7fdd0be0 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -299,8 +299,8 @@ struct sway_config { char *floating_scroll_down_cmd; char *floating_scroll_left_cmd; char *floating_scroll_right_cmd; - enum swayc_layouts default_orientation; - enum swayc_layouts default_layout; + enum sway_container_layout default_orientation; + enum sway_container_layout default_layout; char *font; int font_height; @@ -324,8 +324,8 @@ struct sway_config { list_t *config_chain; const char *current_config; - enum swayc_border_types border; - enum swayc_border_types floating_border; + enum sway_container_border border; + enum sway_container_border floating_border; int border_thickness; int floating_border_thickness; enum edge_border_types hide_edge_borders; diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index e43e6fd4..496bfd5d 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -71,7 +71,7 @@ struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container); struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, - enum swayc_types type); + enum sway_container_type type); void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 5def5e71..0dfed455 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -17,7 +17,7 @@ struct sway_seat; * This enum is in order. A container will never be inside of a container below * it on this list. */ -enum swayc_types { +enum sway_container_type { C_ROOT, C_OUTPUT, C_WORKSPACE, @@ -27,7 +27,7 @@ enum swayc_types { C_TYPES, }; -enum swayc_layouts { +enum sway_container_layout { L_NONE, L_HORIZ, L_VERT, @@ -39,7 +39,7 @@ enum swayc_layouts { L_LAYOUTS, }; -enum swayc_border_types { +enum sway_container_border { B_NONE, B_PIXEL, B_NORMAL, @@ -65,10 +65,10 @@ struct sway_container { char *name; - enum swayc_types type; - enum swayc_layouts layout; - enum swayc_layouts prev_layout; - enum swayc_layouts workspace_layout; + enum sway_container_type type; + enum sway_container_layout layout; + enum sway_container_layout prev_layout; + enum sway_container_layout workspace_layout; // TODO convert to layout coordinates double x, y; @@ -87,53 +87,61 @@ struct sway_container { } events; }; -void swayc_descendants_of_type(struct sway_container *root, - enum swayc_types type, - void (*func)(struct sway_container *item, void *data), void *data); - // TODO only one container create function and pass the type? -struct sway_container *new_output(struct sway_output *sway_output); +struct sway_container *sway_container_output_create( + struct sway_output *sway_output); + +struct sway_container *sway_container_workspace_create( + struct sway_container *output, const char *name); -struct sway_container *new_workspace(struct sway_container *output, - const char *name); +struct sway_container *sway_container_view_create( + struct sway_container *sibling, struct sway_view *sway_view); -struct sway_container *new_view(struct sway_container *sibling, - struct sway_view *sway_view); +struct sway_container *sway_container_output_destroy( + struct sway_container *output); -struct sway_container *destroy_output(struct sway_container *output); -struct sway_container *destroy_view(struct sway_container *view); +struct sway_container *sway_container_view_destroy(struct sway_container *view); +struct sway_container *sway_container_set_layout( + struct sway_container *container, enum sway_container_layout layout); + +void sway_container_descendents(struct sway_container *root, + enum sway_container_type type, + void (*func)(struct sway_container *item, void *data), void *data); + +// XXX: what is this? struct sway_container *next_view_sibling(struct sway_seat *seat); /** * Finds a container based on test criteria. Returns the first container that * passes the test. */ -struct sway_container *swayc_by_test(struct sway_container *container, +struct sway_container *sway_container_find(struct sway_container *container, bool (*test)(struct sway_container *view, void *data), void *data); /** - * Finds a parent container with the given swayc_type. + * Finds a parent container with the given struct sway_containerype. */ -struct sway_container *swayc_parent_by_type(struct sway_container *container, - enum swayc_types type); +struct sway_container *sway_container_parent(struct sway_container *container, + enum sway_container_type type); /** - * Maps a container's children over a function. + * Run a function for each child. */ -void container_map(struct sway_container *container, +void sway_container_for_each(struct sway_container *container, void (*f)(struct sway_container *view, void *data), void *data); -struct sway_container *swayc_at(struct sway_container *parent, double lx, - double ly, struct wlr_surface **surface, double *sx, double *sy); +/** + * Find a container at the given coordinates. + */ +struct sway_container *sway_container_at(struct sway_container *parent, + double lx, double ly, struct wlr_surface **surface, + double *sx, double *sy); /** * Apply the function for each child of the container breadth first. */ -void container_for_each_bfs(struct sway_container *con, void (*f)(struct - sway_container *con, void *data), void *data); - -struct sway_container *swayc_change_layout(struct sway_container *container, - enum swayc_layouts layout); +void sway_container_for_each_bfs(struct sway_container *container, + void (*f)(struct sway_container *container, void *data), void *data); #endif diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 8bb9e075..f73b3880 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -39,7 +39,7 @@ struct sway_container *add_sibling(struct sway_container *parent, struct sway_container *remove_child(struct sway_container *child); -enum swayc_layouts default_layout(struct sway_container *output); +enum sway_container_layout default_layout(struct sway_container *output); void sort_workspaces(struct sway_container *output); diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 18e9e0bf..64b05904 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -32,7 +32,7 @@ static bool parse_movement_direction(const char *name, } struct cmd_results *cmd_focus(int argc, char **argv) { - swayc_t *con = config->handler_context.current_container; + struct sway_container *con = config->handler_context.current_container; struct sway_seat *seat = config->handler_context.seat; if (con->type < C_WORKSPACE) { return cmd_results_new(CMD_FAILURE, "focus", @@ -51,7 +51,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) { "Expected 'focus ' or 'focus output '"); } - swayc_t *next_focus = get_swayc_in_direction(con, seat, direction); + struct sway_container *next_focus = get_swayc_in_direction(con, seat, direction); if (next_focus) { sway_seat_set_focus(seat, next_focus); } diff --git a/sway/commands/kill.c b/sway/commands/kill.c index c0faed7a..f6774767 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -6,7 +6,7 @@ #include "sway/commands.h" struct cmd_results *cmd_kill(int argc, char **argv) { - enum swayc_types type = config->handler_context.current_container->type; + enum sway_container_type type = config->handler_context.current_container->type; if (type != C_VIEW && type != C_CONTAINER) { return cmd_results_new(CMD_INVALID, NULL, "Can only kill views and containers with this command"); diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 2b193136..e10334e2 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -10,7 +10,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { return error; } - swayc_t *parent = config->handler_context.current_container; + struct sway_container *parent = config->handler_context.current_container; // TODO: floating /* @@ -28,7 +28,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if (strcasecmp(argv[0], "default") == 0) { swayc_change_layout(parent, parent->prev_layout); if (parent->layout == L_NONE) { - swayc_t *output = swayc_parent_by_type(parent, C_OUTPUT); + struct sway_container *output = sway_container_parent(parent, C_OUTPUT); swayc_change_layout(parent, default_layout(output)); } } else { diff --git a/sway/commands/output.c b/sway/commands/output.c index 35bc8099..f7e3372c 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -296,7 +296,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { char identifier[128]; bool all = strcmp(output->name, "*") == 0; for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *cont = root_container.children->items[i]; + struct sway_container *cont = root_container.children->items[i]; if (cont->type != C_OUTPUT) { continue; } diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 8751dffe..8b7139a9 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -17,15 +17,15 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { int output_location = -1; - swayc_t *current_container = config->handler_context.current_container; - swayc_t *old_workspace = NULL, *old_output = NULL; + struct sway_container *current_container = config->handler_context.current_container; + struct sway_container *old_workspace = NULL, *old_output = NULL; if (current_container) { if (current_container->type == C_WORKSPACE) { old_workspace = current_container; } else { - old_workspace = swayc_parent_by_type(current_container, C_WORKSPACE); + old_workspace = sway_container_parent(current_container, C_WORKSPACE); } - old_output = swayc_parent_by_type(current_container, C_OUTPUT); + old_output = sway_container_parent(current_container, C_OUTPUT); } for (int i = 0; i < argc; ++i) { @@ -57,7 +57,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (config->reading || !config->active) { return cmd_results_new(CMD_DEFER, "workspace", NULL); } - swayc_t *ws = NULL; + struct sway_container *ws = NULL; if (strcasecmp(argv[0], "number") == 0) { if (!(ws = workspace_by_number(argv[1]))) { char *name = join_args(argv + 1, argc - 1); @@ -92,7 +92,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { workspace_switch(ws); current_container = sway_seat_get_focus(config->handler_context.seat); - swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); + struct sway_container *new_output = sway_container_parent(current_container, C_OUTPUT); if (config->mouse_warping && old_output != new_output) { // TODO: Warp mouse diff --git a/sway/config/output.c b/sway/config/output.c index 9e211861..5763bd21 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -120,14 +120,14 @@ void terminate_swaybg(pid_t pid) { } } -void apply_output_config(struct output_config *oc, swayc_t *output) { +void apply_output_config(struct output_config *oc, struct sway_container *output) { assert(output->type == C_OUTPUT); struct wlr_output *wlr_output = output->sway_output->wlr_output; if (oc && oc->enabled == 0) { wlr_output_layout_remove(root_container.sway_root->output_layout, wlr_output); - destroy_output(output); + sway_container_output_destroy(output); return; } diff --git a/sway/criteria.c b/sway/criteria.c index b8b581ed..70f8e305 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -272,7 +272,7 @@ static int regex_cmp(const char *item, const pcre *regex) { } // test a single view if it matches list of criteria tokens (all of them). -static bool criteria_test(swayc_t *cont, list_t *tokens) { +static bool criteria_test(struct sway_container *cont, list_t *tokens) { if (cont->type != C_VIEW) { return false; } @@ -398,7 +398,7 @@ void free_criteria(struct criteria *crit) { free(crit); } -bool criteria_any(swayc_t *cont, list_t *criteria) { +bool criteria_any(struct sway_container *cont, list_t *criteria) { for (int i = 0; i < criteria->length; i++) { struct criteria *bc = criteria->items[i]; if (criteria_test(cont, bc->tokens)) { @@ -408,7 +408,7 @@ bool criteria_any(swayc_t *cont, list_t *criteria) { return false; } -list_t *criteria_for(swayc_t *cont) { +list_t *criteria_for(struct sway_container *cont) { list_t *criteria = config->criteria, *matches = create_list(); for (int i = 0; i < criteria->length; i++) { struct criteria *bc = criteria->items[i]; @@ -424,7 +424,7 @@ struct list_tokens { list_t *tokens; }; -static void container_match_add(swayc_t *container, +static void container_match_add(struct sway_container *container, struct list_tokens *list_tokens) { if (criteria_test(container, list_tokens->tokens)) { list_add(list_tokens->list, container); @@ -435,8 +435,8 @@ list_t *container_for_crit_tokens(list_t *tokens) { struct list_tokens list_tokens = (struct list_tokens){create_list(), tokens}; - container_map(&root_container, - (void (*)(swayc_t *, void *))container_match_add, + sway_container_for_each(&root_container, + (void (*)(struct sway_container *, void *))container_match_add, &list_tokens); // TODO look in the scratchpad diff --git a/sway/desktop/output.c b/sway/desktop/output.c index debda396..3e7d8509 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -145,7 +145,7 @@ struct render_data { struct timespec *now; }; -static void output_frame_view(swayc_t *view, void *data) { +static void output_frame_view(struct sway_container *view, void *data) { struct render_data *rdata = data; struct sway_output *output = rdata->output; struct timespec *now = rdata->now; @@ -218,16 +218,16 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); - swayc_t *workspace = (focus->type == C_WORKSPACE ? + struct sway_container *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); + struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : - swayc_parent_by_type(focus, C_WORKSPACE)); + sway_container_parent(focus, C_WORKSPACE)); struct render_data rdata = { .output = soutput, .now = &now, }; - swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, &rdata); + sway_container_descendents(workspace, C_VIEW, output_frame_view, &rdata); // render unmanaged views on top struct sway_view *view; @@ -258,7 +258,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); - destroy_output(output->swayc); + sway_container_output_destroy(output->swayc); } static void handle_output_mode(struct wl_listener *listener, void *data) { @@ -286,7 +286,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { wlr_output_set_mode(wlr_output, mode); } - output->swayc = new_output(output); + output->swayc = sway_container_output_create(output); if (!output->swayc) { free(output); return; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index bb97fad4..bf41d7bf 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -74,7 +74,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_surface, destroy); wl_list_remove(&sway_surface->commit.link); wl_list_remove(&sway_surface->destroy.link); - swayc_t *parent = destroy_view(sway_surface->view->swayc); + struct sway_container *parent = sway_container_view_destroy(sway_surface->view->swayc); free(sway_surface->view); free(sway_surface); arrange_windows(parent, -1, -1); @@ -132,8 +132,8 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); - swayc_t *cont = new_view(focus, sway_view); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *cont = sway_container_view_create(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 25ffacbb..6b50d470 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -83,7 +83,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_xdg_surface, destroy); wl_list_remove(&sway_xdg_surface->commit.link); wl_list_remove(&sway_xdg_surface->destroy.link); - swayc_t *parent = destroy_view(sway_xdg_surface->view->swayc); + struct sway_container *parent = sway_container_view_destroy(sway_xdg_surface->view->swayc); free(sway_xdg_surface->view); free(sway_xdg_surface); arrange_windows(parent, -1, -1); @@ -136,8 +136,8 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); - swayc_t *cont = new_view(focus, sway_view); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *cont = sway_container_view_create(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 7f66f746..96edab51 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -49,11 +49,11 @@ static void set_position(struct sway_view *view, double ox, double oy) { if (!assert_xwayland(view)) { return; } - swayc_t *output = swayc_parent_by_type(view->swayc, C_OUTPUT); + struct sway_container *output = sway_container_parent(view->swayc, C_OUTPUT); if (!sway_assert(output, "view must be within tree to set position")) { return; } - swayc_t *root = swayc_parent_by_type(output, C_ROOT); + struct sway_container *root = sway_container_parent(output, C_ROOT); if (!sway_assert(root, "output must be within tree to set position")) { return; } @@ -114,7 +114,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } } - swayc_t *parent = destroy_view(sway_surface->view->swayc); + struct sway_container *parent = sway_container_view_destroy(sway_surface->view->swayc); if (parent) { arrange_windows(parent, -1, -1); } @@ -132,7 +132,7 @@ static void handle_unmap_notify(struct wl_listener *listener, void *data) { } // take it out of the tree - swayc_t *parent = destroy_view(sway_surface->view->swayc); + struct sway_container *parent = sway_container_view_destroy(sway_surface->view->swayc); if (parent) { arrange_windows(parent, -1, -1); } @@ -155,12 +155,12 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { &sway_surface->view->unmanaged_view_link); } else { struct sway_view *view = sway_surface->view; - destroy_view(view->swayc); + sway_container_view_destroy(view->swayc); - swayc_t *parent = root_container.children->items[0]; + struct sway_container *parent = root_container.children->items[0]; parent = parent->children->items[0]; // workspace - swayc_t *cont = new_view(parent, view); + struct sway_container *cont = sway_container_view_create(parent, view); view->swayc = cont; arrange_windows(cont->parent, -1, -1); @@ -238,8 +238,8 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { } struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); - swayc_t *cont = new_view(focus, sway_view); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *cont = sway_container_view_create(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index c0e14265..a0e4b9be 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -49,8 +49,8 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, } } - swayc_t *swayc = - swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + struct sway_container *swayc = + sway_container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); if (swayc) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); @@ -87,8 +87,8 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { if (event->button == BTN_LEFT) { struct wlr_surface *surface = NULL; double sx, sy; - swayc_t *swayc = - swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + struct sway_container *swayc = + sway_container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); sway_seat_set_focus(cursor->seat, swayc); } diff --git a/sway/input/seat.c b/sway/input/seat.c index 56b39766..f03a03b4 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -37,7 +37,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, struct sway_seat_container *seat_con = wl_container_of(listener, seat_con, destroy); struct sway_seat *seat = seat_con->seat; - swayc_t *con = seat_con->container; + struct sway_container *con = seat_con->container; bool is_focus = (sway_seat_get_focus(seat) == con); @@ -46,7 +46,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, if (is_focus) { // pick next focus sway_seat_set_focus(seat, NULL); - swayc_t *next = sway_seat_get_focus_inactive(seat, con->parent); + struct sway_container *next = sway_seat_get_focus_inactive(seat, con->parent); if (next == NULL) { next = con->parent; } @@ -59,7 +59,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, } static struct sway_seat_container *seat_container_from_container( - struct sway_seat *seat, swayc_t *con) { + struct sway_seat *seat, struct sway_container *con) { if (con->type < C_WORKSPACE) { // these don't get seat containers ever return NULL; @@ -89,11 +89,11 @@ static struct sway_seat_container *seat_container_from_container( static void handle_new_container(struct wl_listener *listener, void *data) { struct sway_seat *seat = wl_container_of(listener, seat, new_container); - swayc_t *con = data; + struct sway_container *con = data; seat_container_from_container(seat, con); } -static void collect_focus_iter(swayc_t *con, void *data) { +static void collect_focus_iter(struct sway_container *con, void *data) { struct sway_seat *seat = data; if (con->type > C_WORKSPACE) { return; @@ -130,7 +130,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, // init the focus stack wl_list_init(&seat->focus_stack); - container_for_each_bfs(&root_container, collect_focus_iter, seat); + sway_container_for_each_bfs(&root_container, collect_focus_iter, seat); wl_signal_add(&root_container.sway_root->events.new_container, &seat->new_container); @@ -166,7 +166,7 @@ static void seat_configure_keyboard(struct sway_seat *seat, sway_keyboard_configure(seat_device->keyboard); wlr_seat_set_keyboard(seat->wlr_seat, seat_device->input_device->wlr_device); - swayc_t *focus = sway_seat_get_focus(seat); + struct sway_container *focus = sway_seat_get_focus(seat); if (focus && focus->type == C_VIEW) { // force notify reenter to pick up the new configuration wlr_seat_keyboard_clear_focus(seat->wlr_seat); @@ -270,7 +270,7 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { } for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *output_container = root_container.children->items[i]; + struct sway_container *output_container = root_container.children->items[i]; struct wlr_output *output = output_container->sway_output->wlr_output; bool result = @@ -289,8 +289,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { - swayc_t *last_focus = sway_seat_get_focus(seat); +void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container) { + struct sway_container *last_focus = sway_seat_get_focus(seat); if (container && last_focus == container) { return; @@ -330,9 +330,9 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { seat->has_focus = (container != NULL); } -swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container) { +struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { struct sway_seat_container *current = NULL; - swayc_t *parent = NULL; + struct sway_container *parent = NULL; wl_list_for_each(current, &seat->focus_stack, link) { parent = current->container->parent; @@ -351,21 +351,21 @@ swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container return NULL; } -swayc_t *sway_seat_get_focus(struct sway_seat *seat) { +struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { if (!seat->has_focus) { return NULL; } return sway_seat_get_focus_inactive(seat, &root_container); } -swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, - enum swayc_types type) { - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); +struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, + enum sway_container_type type) { + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); if (focus->type == type) { return focus; } - return swayc_parent_by_type(focus, type); + return sway_container_parent(focus, type); } void sway_seat_set_config(struct sway_seat *seat, diff --git a/sway/ipc-json.c b/sway/ipc-json.c index ebd5e43a..7caa2457 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -25,7 +25,7 @@ json_object *ipc_json_get_version() { return version; } -static json_object *ipc_json_create_rect(swayc_t *c) { +static json_object *ipc_json_create_rect(struct sway_container *c) { json_object *rect = json_object_new_object(); json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); @@ -36,7 +36,7 @@ static json_object *ipc_json_create_rect(swayc_t *c) { return rect; } -static void ipc_json_describe_root(swayc_t *root, json_object *object) { +static void ipc_json_describe_root(struct sway_container *root, json_object *object) { json_object_object_add(object, "type", json_object_new_string("root")); json_object_object_add(object, "layout", json_object_new_string("splith")); } @@ -63,7 +63,7 @@ static const char *ipc_json_get_output_transform(enum wl_output_transform transf return NULL; } -static void ipc_json_describe_output(swayc_t *container, json_object *object) { +static void ipc_json_describe_output(struct sway_container *container, json_object *object) { struct wlr_output *wlr_output = container->sway_output->wlr_output; json_object_object_add(object, "type", json_object_new_string("output")); json_object_object_add(object, "active", json_object_new_boolean(true)); @@ -94,7 +94,7 @@ static void ipc_json_describe_output(swayc_t *container, json_object *object) { json_object_object_add(object, "modes", modes_array); } -static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { +static void ipc_json_describe_workspace(struct sway_container *workspace, json_object *object) { int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; json_object_object_add(object, "num", json_object_new_int(num)); @@ -102,11 +102,11 @@ static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) json_object_object_add(object, "type", json_object_new_string("workspace")); } -static void ipc_json_describe_view(swayc_t *c, json_object *object) { +static void ipc_json_describe_view(struct sway_container *c, json_object *object) { json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); } -json_object *ipc_json_describe_container(swayc_t *c) { +json_object *ipc_json_describe_container(struct sway_container *c) { if (!(sway_assert(c, "Container must not be null."))) { return NULL; } @@ -147,7 +147,7 @@ json_object *ipc_json_describe_container(swayc_t *c) { return object; } -json_object *ipc_json_describe_container_recursive(swayc_t *c) { +json_object *ipc_json_describe_container_recursive(struct sway_container *c) { json_object *object = ipc_json_describe_container(c); int i; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 156de380..50d0bcf3 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -279,7 +279,7 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) } } -void ipc_event_window(swayc_t *window, const char *change) { +void ipc_event_window(struct sway_container *window, const char *change) { wlr_log(L_DEBUG, "Sending window::%s event", change); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(change)); @@ -400,7 +400,7 @@ void ipc_client_handle_command(struct ipc_client *client) { { json_object *outputs = json_object_new_array(); for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *container = root_container.children->items[i]; + struct sway_container *container = root_container.children->items[i]; if (container->type == C_OUTPUT) { json_object_array_add(outputs, ipc_json_describe_container(container)); diff --git a/sway/tree/container.c b/sway/tree/container.c index 805d5644..d31966b3 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -33,48 +33,15 @@ static list_t *get_bfs_queue() { return bfs_queue; } -static void notify_new_container(swayc_t *container) { +static void notify_new_container(struct sway_container *container) { wl_signal_emit(&root_container.sway_root->events.new_container, container); ipc_event_window(container, "new"); } -swayc_t *swayc_by_test(swayc_t *container, - bool (*test)(swayc_t *view, void *data), void *data) { - if (!container->children) { - return NULL; - } - // TODO: floating windows - for (int i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - if (test(child, data)) { - return child; - } else { - swayc_t *res = swayc_by_test(child, test, data); - if (res) { - return res; - } - } - } - return NULL; -} - -void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, - void (*func)(swayc_t *item, void *data), void *data) { - for (int i = 0; i < root->children->length; ++i) { - swayc_t *item = root->children->items[i]; - if (item->type == type) { - func(item, data); - } - if (item->children && item->children->length) { - swayc_descendants_of_type(item, type, func, data); - } - } -} - -static swayc_t *new_swayc(enum swayc_types type) { +static struct sway_container *new_swayc(enum sway_container_type type) { // next id starts at 1 because 0 is assigned to root_container in layout.c static size_t next_id = 1; - swayc_t *c = calloc(1, sizeof(swayc_t)); + struct sway_container *c = calloc(1, sizeof(struct sway_container)); if (!c) { return NULL; } @@ -91,7 +58,7 @@ static swayc_t *new_swayc(enum swayc_types type) { return c; } -static void free_swayc(swayc_t *cont) { +static void free_swayc(struct sway_container *cont) { if (!sway_assert(cont, "free_swayc passed NULL")) { return; } @@ -119,7 +86,7 @@ static void free_swayc(swayc_t *cont) { free(cont); } -swayc_t *new_output(struct sway_output *sway_output) { +struct sway_container *sway_container_output_create(struct sway_output *sway_output) { struct wlr_box size; wlr_output_effective_resolution(sway_output->wlr_output, &size.width, &size.height); @@ -154,7 +121,7 @@ swayc_t *new_output(struct sway_output *sway_output) { return NULL; } - swayc_t *output = new_swayc(C_OUTPUT); + struct sway_container *output = new_swayc(C_OUTPUT); output->sway_output = sway_output; output->name = strdup(name); if (output->name == NULL) { @@ -169,7 +136,7 @@ swayc_t *new_output(struct sway_output *sway_output) { // Create workspace char *ws_name = workspace_next_name(output->name); wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); - swayc_t *ws = new_workspace(output, ws_name); + struct sway_container *ws = sway_container_workspace_create(output, ws_name); // Set each seat's focus if not already set struct sway_seat *seat = NULL; wl_list_for_each(seat, &input_manager->seats, link) { @@ -183,12 +150,12 @@ swayc_t *new_output(struct sway_output *sway_output) { return output; } -swayc_t *new_workspace(swayc_t *output, const char *name) { - if (!sway_assert(output, "new_workspace called with null output")) { +struct sway_container *sway_container_workspace_create(struct sway_container *output, const char *name) { + if (!sway_assert(output, "sway_container_workspace_create called with null output")) { return NULL; } wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); - swayc_t *workspace = new_swayc(C_WORKSPACE); + struct sway_container *workspace = new_swayc(C_WORKSPACE); workspace->x = output->x; workspace->y = output->y; @@ -205,12 +172,12 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { return workspace; } -swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { - if (!sway_assert(sibling, "new_view called with NULL sibling/parent")) { +struct sway_container *sway_container_view_create(struct sway_container *sibling, struct sway_view *sway_view) { + if (!sway_assert(sibling, "sway_container_view_create called with NULL sibling/parent")) { return NULL; } const char *title = view_get_title(sway_view); - swayc_t *swayc = new_swayc(C_VIEW); + struct sway_container *swayc = new_swayc(C_VIEW); wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d %s", swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); // Setup values @@ -230,8 +197,8 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { return swayc; } -swayc_t *destroy_output(swayc_t *output) { - if (!sway_assert(output, "null output passed to destroy_output")) { +struct sway_container *sway_container_output_destroy(struct sway_container *output) { + if (!sway_assert(output, "null output passed to sway_container_output_destroy")) { return NULL; } @@ -243,7 +210,7 @@ swayc_t *destroy_output(swayc_t *output) { int p = root_container.children->items[0] == output; // Move workspace from this output to another output while (output->children->length) { - swayc_t *child = output->children->items[0]; + struct sway_container *child = output->children->items[0]; remove_child(child); add_child(root_container.children->items[p], child); } @@ -262,12 +229,12 @@ swayc_t *destroy_output(swayc_t *output) { return &root_container; } -swayc_t *destroy_view(swayc_t *view) { +struct sway_container *sway_container_view_destroy(struct sway_container *view) { if (!view) { return NULL; } wlr_log(L_DEBUG, "Destroying view '%s'", view->name); - swayc_t *parent = view->parent; + struct sway_container *parent = view->parent; free_swayc(view); // TODO WLR: Destroy empty containers @@ -279,7 +246,52 @@ swayc_t *destroy_view(swayc_t *view) { return parent; } -swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { +struct sway_container *swayc_change_layout(struct sway_container *container, enum sway_container_layout layout) { + if (container->type == C_WORKSPACE) { + container->workspace_layout = layout; + if (layout == L_HORIZ || layout == L_VERT) { + container->layout = layout; + } + } else { + container->layout = layout; + } + return container; +} + +void sway_container_descendents(struct sway_container *root, enum sway_container_type type, + void (*func)(struct sway_container *item, void *data), void *data) { + for (int i = 0; i < root->children->length; ++i) { + struct sway_container *item = root->children->items[i]; + if (item->type == type) { + func(item, data); + } + if (item->children && item->children->length) { + sway_container_descendents(item, type, func, data); + } + } +} + +struct sway_container *sway_container_find(struct sway_container *container, + bool (*test)(struct sway_container *view, void *data), void *data) { + if (!container->children) { + return NULL; + } + // TODO: floating windows + for (int i = 0; i < container->children->length; ++i) { + struct sway_container *child = container->children->items[i]; + if (test(child, data)) { + return child; + } else { + struct sway_container *res = sway_container_find(child, test, data); + if (res) { + return res; + } + } + } + return NULL; +} + +struct sway_container *sway_container_parent(struct sway_container *container, enum sway_container_type type) { if (!sway_assert(container, "container is NULL")) { return NULL; } @@ -292,7 +304,29 @@ swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { return container; } -swayc_t *swayc_at(swayc_t *parent, double lx, double ly, +void sway_container_for_each(struct sway_container *container, void (*f)(struct sway_container *view, void *data), void *data) { + if (container) { + int i; + if (container->children) { + for (i = 0; i < container->children->length; ++i) { + struct sway_container *child = container->children->items[i]; + sway_container_for_each(child, f, data); + } + } + // TODO + /* + if (container->floating) { + for (i = 0; i < container->floating->length; ++i) { + struct sway_container *child = container->floating->items[i]; + container_map(child, f, data); + } + } + */ + f(container, data); + } +} + +struct sway_container *sway_container_at(struct sway_container *parent, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { list_t *queue = get_bfs_queue(); if (!queue) { @@ -301,13 +335,13 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, list_add(queue, parent); - swayc_t *swayc = NULL; + struct sway_container *swayc = NULL; while (queue->length) { swayc = queue->items[0]; list_del(queue, 0); if (swayc->type == C_VIEW) { struct sway_view *sview = swayc->sway_view; - swayc_t *soutput = swayc_parent_by_type(swayc, C_OUTPUT); + struct sway_container *soutput = sway_container_parent(swayc, C_OUTPUT); struct wlr_box *output_box = wlr_output_layout_get_box( root_container.sway_root->output_layout, @@ -377,29 +411,7 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, return NULL; } -void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { - if (container) { - int i; - if (container->children) { - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - container_map(child, f, data); - } - } - // TODO - /* - if (container->floating) { - for (i = 0; i < container->floating->length; ++i) { - swayc_t *child = container->floating->items[i]; - container_map(child, f, data); - } - } - */ - f(container, data); - } -} - -void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), +void sway_container_for_each_bfs(struct sway_container *con, void (*f)(struct sway_container *con, void *data), void *data) { list_t *queue = get_bfs_queue(); if (!queue) { @@ -413,7 +425,7 @@ void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), list_add(queue, con); - swayc_t *current = NULL; + struct sway_container *current = NULL; while (queue->length) { current = queue->items[0]; list_del(queue, 0); @@ -422,15 +434,3 @@ void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), list_cat(queue, current->children); } } - -swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) { - if (container->type == C_WORKSPACE) { - container->workspace_layout = layout; - if (layout == L_HORIZ || layout == L_VERT) { - container->layout = layout; - } - } else { - container->layout = layout; - } - return container; -} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 5a15f3a2..068fb39c 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -14,7 +14,7 @@ #include "list.h" #include "log.h" -swayc_t root_container; +struct sway_container root_container; static void output_layout_change_notify(struct wl_listener *listener, void *data) { struct wlr_box *layout_box = wlr_output_layout_get_box( @@ -23,7 +23,7 @@ static void output_layout_change_notify(struct wl_listener *listener, void *data root_container.height = layout_box->height; for (int i = 0 ; i < root_container.children->length; ++i) { - swayc_t *output_container = root_container.children->items[i]; + struct sway_container *output_container = root_container.children->items[i]; if (output_container->type != C_OUTPUT) { continue; } @@ -62,9 +62,9 @@ void init_layout(void) { &root_container.sway_root->output_layout_change); } -static int index_child(const swayc_t *child) { +static int index_child(const struct sway_container *child) { // TODO handle floating - swayc_t *parent = child->parent; + struct sway_container *parent = child->parent; int i, len; len = parent->children->length; for (i = 0; i < len; ++i) { @@ -79,16 +79,16 @@ static int index_child(const swayc_t *child) { return i; } -swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { +struct sway_container *add_sibling(struct sway_container *fixed, struct sway_container *active) { // TODO handle floating - swayc_t *parent = fixed->parent; + struct sway_container *parent = fixed->parent; int i = index_child(fixed); list_insert(parent->children, i + 1, active); active->parent = parent; return active->parent; } -void add_child(swayc_t *parent, swayc_t *child) { +void add_child(struct sway_container *parent, struct sway_container *child) { wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", child, child->type, child->width, child->height, parent, parent->type, parent->width, parent->height); @@ -102,9 +102,9 @@ void add_child(swayc_t *parent, swayc_t *child) { */ } -swayc_t *remove_child(swayc_t *child) { +struct sway_container *remove_child(struct sway_container *child) { int i; - swayc_t *parent = child->parent; + struct sway_container *parent = child->parent; for (i = 0; i < parent->children->length; ++i) { if (parent->children->items[i] == child) { list_del(parent->children, i); @@ -115,7 +115,7 @@ swayc_t *remove_child(swayc_t *child) { return parent; } -enum swayc_layouts default_layout(swayc_t *output) { +enum sway_container_layout default_layout(struct sway_container *output) { /* TODO WLR if (config->default_layout != L_NONE) { //return config->default_layout; @@ -129,8 +129,8 @@ enum swayc_layouts default_layout(swayc_t *output) { } static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { - swayc_t *a = *(void **)_a; - swayc_t *b = *(void **)_b; + struct sway_container *a = *(void **)_a; + struct sway_container *b = *(void **)_b; int retval = 0; if (isdigit(a->name[0]) && isdigit(b->name[0])) { @@ -146,21 +146,21 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { return retval; } -void sort_workspaces(swayc_t *output) { +void sort_workspaces(struct sway_container *output) { list_stable_sort(output->children, sort_workspace_cmp_qsort); } -static void apply_horiz_layout(swayc_t *container, const double x, +static void apply_horiz_layout(struct sway_container *container, const double x, const double y, const double width, const double height, const int start, const int end); -static void apply_vert_layout(swayc_t *container, const double x, +static void apply_vert_layout(struct sway_container *container, const double x, const double y, const double width, const double height, const int start, const int end); -void arrange_windows(swayc_t *container, double width, double height) { +void arrange_windows(struct sway_container *container, double width, double height) { int i; if (width == -1 || height == -1) { width = container->width; @@ -181,7 +181,7 @@ void arrange_windows(swayc_t *container, double width, double height) { case C_ROOT: // TODO: wlr_output_layout probably for (i = 0; i < container->children->length; ++i) { - swayc_t *output = container->children->items[i]; + struct sway_container *output = container->children->items[i]; wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); arrange_windows(output, -1, -1); @@ -197,13 +197,13 @@ void arrange_windows(swayc_t *container, double width, double height) { } // arrange all workspaces: for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; + struct sway_container *child = container->children->items[i]; arrange_windows(child, -1, -1); } return; case C_WORKSPACE: { - swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); + struct sway_container *output = sway_container_parent(container, C_OUTPUT); struct wlr_box *area = &output->sway_output->usable_area; wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", area->width, area->height, area->x, area->y); @@ -252,14 +252,14 @@ void arrange_windows(swayc_t *container, double width, double height) { } } -static void apply_horiz_layout(swayc_t *container, +static void apply_horiz_layout(struct sway_container *container, const double x, const double y, const double width, const double height, const int start, const int end) { double scale = 0; // Calculate total width for (int i = start; i < end; ++i) { - double *old_width = &((swayc_t *)container->children->items[i])->width; + double *old_width = &((struct sway_container *)container->children->items[i])->width; if (*old_width <= 0) { if (end - start > 1) { *old_width = width / (end - start - 1); @@ -276,7 +276,7 @@ static void apply_horiz_layout(swayc_t *container, if (scale > 0.1) { wlr_log(L_DEBUG, "Arranging %p horizontally", container); for (int i = start; i < end; ++i) { - swayc_t *child = container->children->items[i]; + struct sway_container *child = container->children->items[i]; wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); @@ -301,7 +301,7 @@ static void apply_horiz_layout(swayc_t *container, } } -void apply_vert_layout(swayc_t *container, +void apply_vert_layout(struct sway_container *container, const double x, const double y, const double width, const double height, const int start, const int end) { @@ -309,7 +309,7 @@ void apply_vert_layout(swayc_t *container, double scale = 0; // Calculate total height for (i = start; i < end; ++i) { - double *old_height = &((swayc_t *)container->children->items[i])->height; + double *old_height = &((struct sway_container *)container->children->items[i])->height; if (*old_height <= 0) { if (end - start > 1) { *old_height = height / (end - start - 1); @@ -326,7 +326,7 @@ void apply_vert_layout(swayc_t *container, if (scale > 0.1) { wlr_log(L_DEBUG, "Arranging %p vertically", container); for (i = start; i < end; ++i) { - swayc_t *child = container->children->items[i]; + struct sway_container *child = container->children->items[i]; wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); @@ -354,15 +354,15 @@ void apply_vert_layout(swayc_t *container, /** * Get swayc in the direction of newly entered output. */ -static swayc_t *get_swayc_in_output_direction(swayc_t *output, +static struct sway_container *get_swayc_in_output_direction(struct sway_container *output, enum movement_direction dir, struct sway_seat *seat) { if (!output) { return NULL; } - swayc_t *ws = sway_seat_get_focus_inactive(seat, output); + struct sway_container *ws = sway_seat_get_focus_inactive(seat, output); if (ws->type != C_WORKSPACE) { - ws = swayc_parent_by_type(ws, C_WORKSPACE); + ws = sway_container_parent(ws, C_WORKSPACE); } if (ws == NULL) { @@ -380,9 +380,9 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output, return ws->children->items[0]; case MOVE_UP: case MOVE_DOWN: { - swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); + struct sway_container *focused = sway_seat_get_focus_inactive(seat, ws); if (focused && focused->parent) { - swayc_t *parent = focused->parent; + struct sway_container *parent = focused->parent; if (parent->layout == L_VERT) { if (dir == MOVE_UP) { // get child furthest down on new output @@ -404,13 +404,13 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output, return ws; } -static void get_layout_center_position(swayc_t *container, int *x, int *y) { +static void get_layout_center_position(struct sway_container *container, int *x, int *y) { // FIXME view coords are inconsistently referred to in layout/output systems if (container->type == C_OUTPUT) { *x = container->x + container->width/2; *y = container->y + container->height/2; } else { - swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); + struct sway_container *output = sway_container_parent(container, C_OUTPUT); if (container->type == C_WORKSPACE) { // Workspace coordinates are actually wrong/arbitrary, but should // be same as output. @@ -444,12 +444,12 @@ static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out return true; } -static swayc_t *sway_output_from_wlr(struct wlr_output *output) { +static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { if (output == NULL) { return NULL; } for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *o = root_container.children->items[i]; + struct sway_container *o = root_container.children->items[i]; if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) { return o; } @@ -457,13 +457,13 @@ static swayc_t *sway_output_from_wlr(struct wlr_output *output) { return NULL; } -static swayc_t *get_swayc_in_direction_under(swayc_t *container, - enum movement_direction dir, struct sway_seat *seat, swayc_t *limit) { +static struct sway_container *get_swayc_in_direction_under(struct sway_container *container, + enum movement_direction dir, struct sway_seat *seat, struct sway_container *limit) { if (dir == MOVE_CHILD) { return sway_seat_get_focus_inactive(seat, container); } - swayc_t *parent = container->parent; + struct sway_container *parent = container->parent; if (dir == MOVE_PARENT) { if (parent->type == C_OUTPUT) { return NULL; @@ -496,9 +496,9 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, /* if (container->type == C_VIEW && swayc_is_fullscreen(container)) { wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); - container = swayc_parent_by_type(container, C_OUTPUT); + container = sway_container_parent(container, C_OUTPUT); get_layout_center_position(container, &abs_pos); - swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); + struct sway_container *output = swayc_adjacent_output(container, dir, &abs_pos, true); return get_swayc_in_output_direction(output, dir); } if (container->type == C_WORKSPACE && container->fullscreen) { @@ -507,7 +507,7 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, } */ - swayc_t *wrap_candidate = NULL; + struct sway_container *wrap_candidate = NULL; while (true) { // Test if we can even make a difference here bool can_move = false; @@ -525,12 +525,12 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output(layout, wlr_dir, container->sway_output->wlr_output, lx, ly); - swayc_t *adjacent = sway_output_from_wlr(wlr_adjacent); + struct sway_container *adjacent = sway_output_from_wlr(wlr_adjacent); if (!adjacent || adjacent == container) { return wrap_candidate; } - swayc_t *next = get_swayc_in_output_direction(adjacent, dir, seat); + struct sway_container *next = get_swayc_in_output_direction(adjacent, dir, seat); if (next == NULL) { return NULL; } @@ -587,7 +587,7 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, } } -swayc_t *get_swayc_in_direction(swayc_t *container, struct sway_seat *seat, +struct sway_container *get_swayc_in_direction(struct sway_container *container, struct sway_seat *seat, enum movement_direction dir) { return get_swayc_in_direction_under(container, dir, seat, NULL); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 3da3fde6..32e82845 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -17,7 +17,7 @@ struct workspace_by_number_data { const char *name; }; -void next_name_map(swayc_t *ws, void *data) { +void next_name_map(struct sway_container *ws, void *data) { int *count = data; ++count; } @@ -37,7 +37,7 @@ char *workspace_next_name(const char *output_name) { return name; } -static bool _workspace_by_number(swayc_t *view, void *data) { +static bool _workspace_by_number(struct sway_container *view, void *data) { if (view->type != C_WORKSPACE) { return false; } @@ -46,27 +46,27 @@ static bool _workspace_by_number(swayc_t *view, void *data) { return a == wbnd->len && strncmp(view->name, wbnd->name, a) == 0; } -swayc_t *workspace_by_number(const char* name) { +struct sway_container *workspace_by_number(const char* name) { struct workspace_by_number_data wbnd = {0, "1234567890", name}; wbnd.len = strspn(name, wbnd.cset); if (wbnd.len <= 0) { return NULL; } - return swayc_by_test(&root_container, _workspace_by_number, (void *) &wbnd); + return sway_container_find(&root_container, _workspace_by_number, (void *) &wbnd); } -static bool _workspace_by_name(swayc_t *view, void *data) { +static bool _workspace_by_name(struct sway_container *view, void *data) { return (view->type == C_WORKSPACE) && (strcasecmp(view->name, (char *) data) == 0); } -swayc_t *workspace_by_name(const char *name) { +struct sway_container *workspace_by_name(const char *name) { struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *current_workspace = NULL, *current_output = NULL; - swayc_t *focus = sway_seat_get_focus(seat); + struct sway_container *current_workspace = NULL, *current_output = NULL; + struct sway_container *focus = sway_seat_get_focus(seat); if (focus) { - current_workspace = swayc_parent_by_type(focus, C_WORKSPACE); - current_output = swayc_parent_by_type(focus, C_OUTPUT); + current_workspace = sway_container_parent(focus, C_WORKSPACE); + current_output = sway_container_parent(focus, C_OUTPUT); } if (strcmp(name, "prev") == 0) { return workspace_prev(current_workspace); @@ -79,12 +79,12 @@ swayc_t *workspace_by_name(const char *name) { } else if (strcmp(name, "current") == 0) { return current_workspace; } else { - return swayc_by_test(&root_container, _workspace_by_name, (void *) name); + return sway_container_find(&root_container, _workspace_by_name, (void *) name); } } -swayc_t *workspace_create(const char *name) { - swayc_t *parent; +struct sway_container *workspace_create(const char *name) { + struct sway_container *parent; // Search for workspace<->output pair int i, e = config->workspace_outputs->length; for (i = 0; i < e; ++i) { @@ -95,7 +95,7 @@ swayc_t *workspace_create(const char *name) { for (i = 0; i < e; ++i) { parent = root_container.children->items[i]; if (strcmp(parent->name, wso->output) == 0) { - return new_workspace(parent, name); + return sway_container_workspace_create(parent, name); } } break; @@ -103,10 +103,10 @@ swayc_t *workspace_create(const char *name) { } // Otherwise create a new one struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); parent = focus; - parent = swayc_parent_by_type(parent, C_OUTPUT); - return new_workspace(parent, name); + parent = sway_container_parent(parent, C_OUTPUT); + return sway_container_workspace_create(parent, name); } /** @@ -114,17 +114,17 @@ swayc_t *workspace_create(const char *name) { * the end and beginning. If next is false, the previous workspace is returned, * otherwise the next one is returned. */ -swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { +struct sway_container *workspace_output_prev_next_impl(struct sway_container *output, bool next) { if (!sway_assert(output->type == C_OUTPUT, "Argument must be an output, is %d", output->type)) { return NULL; } struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, output); - swayc_t *workspace = (focus->type == C_WORKSPACE ? + struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); + struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : - swayc_parent_by_type(focus, C_WORKSPACE)); + sway_container_parent(focus, C_WORKSPACE)); int i; for (i = 0; i < output->children->length; i++) { @@ -144,13 +144,13 @@ swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { * next is false, the previous workspace is returned, otherwise the next one is * returned. */ -swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) { +struct sway_container *workspace_prev_next_impl(struct sway_container *workspace, bool next) { if (!sway_assert(workspace->type == C_WORKSPACE, "Argument must be a workspace, is %d", workspace->type)) { return NULL; } - swayc_t *current_output = workspace->parent; + struct sway_container *current_output = workspace->parent; int offset = next ? 1 : -1; int start = next ? 0 : 1; int end; @@ -170,7 +170,7 @@ swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) { int num_outputs = root_container.children->length; for (i = 0; i < num_outputs; i++) { if (root_container.children->items[i] == current_output) { - swayc_t *next_output = root_container.children->items[ + struct sway_container *next_output = root_container.children->items[ wrap(i + offset, num_outputs)]; return workspace_output_prev_next_impl(next_output, next); } @@ -180,40 +180,40 @@ swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) { return NULL; } -swayc_t *workspace_output_next(swayc_t *current) { +struct sway_container *workspace_output_next(struct sway_container *current) { return workspace_output_prev_next_impl(current, true); } -swayc_t *workspace_next(swayc_t *current) { +struct sway_container *workspace_next(struct sway_container *current) { return workspace_prev_next_impl(current, true); } -swayc_t *workspace_output_prev(swayc_t *current) { +struct sway_container *workspace_output_prev(struct sway_container *current) { return workspace_output_prev_next_impl(current, false); } -swayc_t *workspace_prev(swayc_t *current) { +struct sway_container *workspace_prev(struct sway_container *current) { return workspace_prev_next_impl(current, false); } -bool workspace_switch(swayc_t *workspace) { +bool workspace_switch(struct sway_container *workspace) { if (!workspace) { return false; } struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); if (!seat || !focus) { return false; } - swayc_t *active_ws = focus; + struct sway_container *active_ws = focus; if (active_ws->type != C_WORKSPACE) { - swayc_parent_by_type(focus, C_WORKSPACE); + sway_container_parent(focus, C_WORKSPACE); } if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { - swayc_t *new_ws = workspace_by_name(prev_workspace_name); + struct sway_container *new_ws = workspace_by_name(prev_workspace_name); workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); } @@ -231,12 +231,12 @@ bool workspace_switch(swayc_t *workspace) { // TODO: Deal with sticky containers wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); - swayc_t *next = sway_seat_get_focus_inactive(seat, workspace); + struct sway_container *next = sway_seat_get_focus_inactive(seat, workspace); if (next == NULL) { next = workspace; } sway_seat_set_focus(seat, next); - swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); + struct sway_container *output = sway_container_parent(workspace, C_OUTPUT); arrange_windows(output, -1, -1); return true; } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 93d1219c..f9df0d10 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -352,7 +352,7 @@ void ipc_bar_init(struct bar *bar, const char *bar_id) { } // add bar to the output - struct output *bar_output = new_output(name); + struct output *bar_output = sway_container_output_create(name); bar_output->idx = i; list_add(bar->outputs, bar_output); } -- cgit v1.2.3 From cab1352801b62d1b8a12ca1c995cb24445ce4bc9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 23:04:20 -0400 Subject: Start port of swaybar to layer shell This starts up the event loop and wayland display and shims out the basic top level rendering concepts. Also includes some changes to incorporate pango into the 1.x codebase properly. --- common/meson.build | 3 + common/pango.c | 67 ++++++ include/pango.h | 16 ++ include/sway/config.h | 7 +- include/swaybar/bar.h | 89 +++----- include/swaybar/config.h | 43 +--- include/swaybar/event_loop.h | 4 +- include/swaybar/ipc.h | 22 +- include/swaybar/render.h | 22 +- meson.build | 3 + swaybar/bar.c | 444 ++++++++---------------------------- swaybar/config.c | 37 ++- swaybar/event_loop.c | 10 +- swaybar/ipc.c | 410 --------------------------------- swaybar/main.c | 33 ++- swaybar/meson.build | 25 ++ swaybar/render.c | 388 ++++--------------------------- swaybar/status_line.c | 530 ------------------------------------------- swaybar/tray/dbus.c | 197 ---------------- swaybar/tray/icon.c | 400 -------------------------------- swaybar/tray/sni.c | 481 --------------------------------------- swaybar/tray/sni_watcher.c | 497 ---------------------------------------- swaybar/tray/tray.c | 398 -------------------------------- 23 files changed, 342 insertions(+), 3784 deletions(-) create mode 100644 common/pango.c create mode 100644 include/pango.h delete mode 100644 swaybar/ipc.c create mode 100644 swaybar/meson.build delete mode 100644 swaybar/status_line.c delete mode 100644 swaybar/tray/dbus.c delete mode 100644 swaybar/tray/icon.c delete mode 100644 swaybar/tray/sni.c delete mode 100644 swaybar/tray/sni_watcher.c delete mode 100644 swaybar/tray/tray.c (limited to 'include/sway/config.h') diff --git a/common/meson.build b/common/meson.build index 01736ca6..4ad47077 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,5 +1,7 @@ deps = [ cairo, + pango, + pangocairo, wlroots ] @@ -14,6 +16,7 @@ lib_sway_common = static_library( 'ipc-client.c', 'log.c', 'list.c', + 'pango.c', 'readline.c', 'stringop.c', 'util.c' diff --git a/common/pango.c b/common/pango.c new file mode 100644 index 00000000..212d96cf --- /dev/null +++ b/common/pango.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, + const char *text, int32_t scale, bool markup) { + PangoLayout *layout = pango_cairo_create_layout(cairo); + PangoAttrList *attrs; + if (markup) { + char *buf; + pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, NULL); + pango_layout_set_markup(layout, buf, -1); + free(buf); + } else { + attrs = pango_attr_list_new(); + pango_layout_set_text(layout, text, -1); + } + pango_attr_list_insert(attrs, pango_attr_scale_new(scale)); + PangoFontDescription *desc = pango_font_description_from_string(font); + pango_layout_set_font_description(layout, desc); + pango_layout_set_single_paragraph_mode(layout, 1); + pango_layout_set_attributes(layout, attrs); + pango_attr_list_unref(attrs); + pango_font_description_free(desc); + return layout; +} + +void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, + int32_t scale, bool markup, const char *fmt, ...) { + char *buf = malloc(2048); + + va_list args; + va_start(args, fmt); + if (vsnprintf(buf, 2048, fmt, args) >= 2048) { + strcpy(buf, "[buffer overflow]"); + } + va_end(args); + + PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); + pango_cairo_update_layout(cairo, layout); + pango_layout_get_pixel_size(layout, width, height); + g_object_unref(layout); + free(buf); +} + +void pango_printf(cairo_t *cairo, const char *font, + int32_t scale, bool markup, const char *fmt, ...) { + char *buf = malloc(2048); + + va_list args; + va_start(args, fmt); + if (vsnprintf(buf, 2048, fmt, args) >= 2048) { + strcpy(buf, "[buffer overflow]"); + } + va_end(args); + + PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); + pango_cairo_update_layout(cairo, layout); + pango_cairo_show_layout(cairo, layout); + g_object_unref(layout); + free(buf); +} diff --git a/include/pango.h b/include/pango.h new file mode 100644 index 00000000..f6325f28 --- /dev/null +++ b/include/pango.h @@ -0,0 +1,16 @@ +#ifndef _SWAY_PANGO_H +#define _SWAY_PANGO_H +#include +#include +#include +#include +#include + +PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, + const char *text, int32_t scale, bool markup); +void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, + int32_t scale, bool markup, const char *fmt, ...); +void pango_printf(cairo_t *cairo, const char *font, + int32_t scale, bool markup, const char *fmt, ...); + +#endif diff --git a/include/sway/config.h b/include/sway/config.h index 48a8b0ab..8c9e04de 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -1,17 +1,16 @@ #ifndef _SWAY_CONFIG_H #define _SWAY_CONFIG_H - #define PID_WORKSPACE_TIMEOUT 60 - #include #include #include +#include #include #include -#include #include "list.h" #include "layout.h" #include "container.h" +#include "wlr-layer-shell-unstable-v1-protocol.h" /** * Describes a variable created via the `set` command. @@ -152,7 +151,7 @@ struct bar_config { char *id; uint32_t modifier; list_t *outputs; - //enum desktop_shell_panel_position position; // TODO + char *position; list_t *bindings; char *status_command; bool pango_markup; diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 50d36e76..3ae8c0b3 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -1,72 +1,45 @@ #ifndef _SWAYBAR_BAR_H #define _SWAYBAR_BAR_H - -#include "client/registry.h" -#include "client/window.h" +#include +#include "pool-buffer.h" #include "list.h" -struct bar { - struct config *config; - struct status_line *status; - list_t *outputs; - struct output *focused_output; +struct swaybar_config; +struct swaybar_output; +struct swaybar_workspace; + +struct swaybar { + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; - int ipc_event_socketfd; - int ipc_socketfd; - int status_read_fd; - int status_write_fd; - pid_t status_command_pid; + struct swaybar_config *config; + struct swaybar_output *focused_output; + + struct wl_list outputs; }; -struct output { - struct window *window; - struct registry *registry; - list_t *workspaces; -#ifdef ENABLE_TRAY - list_t *items; -#endif +struct swaybar_output { + struct wl_list link; + struct swaybar *bar; + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + char *name; int idx; bool focused; -}; -struct workspace { - int num; - char *name; - bool focused; - bool visible; - bool urgent; + uint32_t width, height; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; }; -/** Global bar state */ -extern struct bar swaybar; +void bar_setup(struct swaybar *bar, + const char *socket_path, + const char *bar_id); +void bar_run(struct swaybar *bar); +void bar_teardown(struct swaybar *bar); -/** True if sway needs to render */ -extern bool dirty; - -/** - * Setup bar. - */ -void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id); - -/** - * Create new output struct from name. - */ -struct output *new_output(const char *name); - -/** - * Bar mainloop. - */ -void bar_run(struct bar *bar); - -/** - * free workspace list. - */ -void free_workspaces(list_t *workspaces); - -/** - * Teardown bar. - */ -void bar_teardown(struct bar *bar); - -#endif /* _SWAYBAR_BAR_H */ +#endif diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 651f0ee3..1bfe4843 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -1,9 +1,7 @@ #ifndef _SWAYBAR_CONFIG_H #define _SWAYBAR_CONFIG_H - -#include #include - +#include #include "list.h" #include "util.h" @@ -19,10 +17,10 @@ struct box_colors { /** * Swaybar config. */ -struct config { +struct swaybar_config { char *status_command; bool pango_markup; - uint32_t position; + uint32_t position; // zwlr_layer_surface_v1_anchor char *font; char *sep_symbol; char *mode; @@ -32,18 +30,6 @@ struct config { bool workspace_buttons; bool all_outputs; list_t *outputs; - -#ifdef ENABLE_TRAY - // Tray - char *tray_output; - char *icon_theme; - - uint32_t tray_padding; - uint32_t activate_button; - uint32_t context_button; - uint32_t secondary_button; -#endif - int height; struct { @@ -63,24 +49,7 @@ struct config { } colors; }; -/** - * Parse position top|bottom|left|right. - */ -uint32_t parse_position(const char *position); - -/** - * Parse font. - */ -char *parse_font(const char *font); - -/** - * Initialize default sway config. - */ -struct config *init_config(); - -/** - * Free config struct. - */ -void free_config(struct config *config); +struct swaybar_config *init_config(); +void free_config(struct swaybar_config *config); -#endif /* _SWAYBAR_CONFIG_H */ +#endif diff --git a/include/swaybar/event_loop.h b/include/swaybar/event_loop.h index a0cde07f..99f6ed36 100644 --- a/include/swaybar/event_loop.h +++ b/include/swaybar/event_loop.h @@ -1,6 +1,5 @@ #ifndef _SWAYBAR_EVENT_LOOP_H #define _SWAYBAR_EVENT_LOOP_H - #include #include @@ -23,4 +22,5 @@ bool remove_timer(timer_t timer); void event_loop_poll(); void init_event_loop(); -#endif /*_SWAYBAR_EVENT_LOOP_H */ + +#endif diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index c11931d0..57a1b925 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -1,23 +1,9 @@ #ifndef _SWAYBAR_IPC_H #define _SWAYBAR_IPC_H +#include "swaybar/bar.h" -#include "bar.h" - -/** - * Initialize ipc connection to sway and get sway state, outputs, bar_config. - */ -void ipc_bar_init(struct bar *bar, const char *bar_id); - -/** - * Handle ipc event from sway. - */ -bool handle_ipc_event(struct bar *bar); - - -/** - * Send workspace command to sway - */ +void ipc_bar_init(struct swaybar *bar, const char *bar_id); +bool handle_ipc_event(struct swaybar *bar); void ipc_send_workspace_command(const char *workspace_name); -#endif /* _SWAYBAR_IPC_H */ - +#endif diff --git a/include/swaybar/render.h b/include/swaybar/render.h index 114f43f4..071e2298 100644 --- a/include/swaybar/render.h +++ b/include/swaybar/render.h @@ -1,22 +1,10 @@ #ifndef _SWAYBAR_RENDER_H #define _SWAYBAR_RENDER_H -#include "config.h" -#include "bar.h" +struct swaybar; +struct swaybar_output; +struct swaybar_config; -/** - * Render swaybar. - */ -void render(struct output *output, struct config *config, struct status_line *line); +void render_frame(struct swaybar *bar, struct swaybar_output *output); -/** - * Set window height and modify internal spacing accordingly. - */ -void set_window_height(struct window *window, int height); - -/** - * Compute the size of a workspace name - */ -void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height); - -#endif /* _SWAYBAR_RENDER_H */ +#endif diff --git a/meson.build b/meson.build index b681f43a..49824b30 100644 --- a/meson.build +++ b/meson.build @@ -35,6 +35,7 @@ pixman = dependency('pixman-1') libcap = dependency('libcap') libinput = dependency('libinput') math = cc.find_library('m') +rt = cc.find_library('rt') git = find_program('git', required: false) a2x = find_program('a2x', required: false) @@ -99,8 +100,10 @@ subdir('protocols') subdir('common') subdir('sway') subdir('swaymsg') + subdir('client') subdir('swaybg') +subdir('swaybar') config = configuration_data() config.set('sysconfdir', join_paths(prefix, sysconfdir)) diff --git a/swaybar/bar.c b/swaybar/bar.c index f12923a8..e1d594b4 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -1,390 +1,146 @@ #define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include #include -#include #include -#include -#include #include -#include -#include -#ifdef __FreeBSD__ -#include -#else -#include -#endif -#ifdef ENABLE_TRAY -#include -#include "swaybar/tray/sni_watcher.h" -#include "swaybar/tray/tray.h" -#include "swaybar/tray/sni.h" -#endif -#include "swaybar/ipc.h" +#include +#include +#include #include "swaybar/render.h" #include "swaybar/config.h" -#include "swaybar/status_line.h" #include "swaybar/event_loop.h" #include "swaybar/bar.h" -#include "ipc-client.h" #include "list.h" -#include "log.h" +#include "pango.h" +#include "pool-buffer.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" -static void bar_init(struct bar *bar) { +static void bar_init(struct swaybar *bar) { bar->config = init_config(); - bar->status = init_status_line(); - bar->outputs = create_list(); + wl_list_init(&bar->outputs); } -static void spawn_status_cmd_proc(struct bar *bar) { - if (bar->config->status_command) { - int pipe_read_fd[2]; - int pipe_write_fd[2]; - - if (pipe(pipe_read_fd) != 0) { - sway_log(L_ERROR, "Unable to create pipes for status_command fork"); - return; - } - if (pipe(pipe_write_fd) != 0) { - sway_log(L_ERROR, "Unable to create pipe for status_command fork (write)"); - close(pipe_read_fd[0]); - close(pipe_read_fd[1]); - return; - } - - bar->status_command_pid = fork(); - if (bar->status_command_pid == 0) { - close(pipe_read_fd[0]); - dup2(pipe_read_fd[1], STDOUT_FILENO); - close(pipe_read_fd[1]); - - dup2(pipe_write_fd[0], STDIN_FILENO); - close(pipe_write_fd[0]); - close(pipe_write_fd[1]); - - char *const cmd[] = { - "sh", - "-c", - bar->config->status_command, - NULL, - }; - execvp(cmd[0], cmd); - return; - } - - close(pipe_read_fd[1]); - bar->status_read_fd = pipe_read_fd[0]; - fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK); - - close(pipe_write_fd[0]); - bar->status_write_fd = pipe_write_fd[1]; - fcntl(bar->status_write_fd, F_SETFL, O_NONBLOCK); - } -} - -struct output *new_output(const char *name) { - struct output *output = malloc(sizeof(struct output)); +struct swaybar_output *new_output(const char *name) { + struct swaybar_output *output = malloc(sizeof(struct swaybar_output)); output->name = strdup(name); - output->window = NULL; - output->registry = NULL; - output->workspaces = create_list(); -#ifdef ENABLE_TRAY - output->items = create_list(); -#endif return output; } -static void mouse_button_notify(struct window *window, int x, int y, - uint32_t button, uint32_t state_w) { - sway_log(L_DEBUG, "Mouse button %d clicked at %d %d %d", button, x, y, state_w); - if (!state_w) { - return; - } - - struct output *clicked_output = NULL; - for (int i = 0; i < swaybar.outputs->length; i++) { - struct output *output = swaybar.outputs->items[i]; - if (window == output->window) { - clicked_output = output; - break; - } - } - - if (!sway_assert(clicked_output != NULL, "Got pointer event for non-existing output")) { - return; - } - - double button_x = 0.5; - for (int i = 0; i < clicked_output->workspaces->length; i++) { - struct workspace *workspace = clicked_output->workspaces->items[i]; - int button_width, button_height; - - workspace_button_size(window, workspace->name, &button_width, &button_height); - - button_x += button_width; - if (x <= button_x) { - ipc_send_workspace_command(workspace->name); - break; - } - } - - switch (button) { - case BTN_LEFT: - status_line_mouse_event(&swaybar, x, y, 1); - break; - case BTN_MIDDLE: - status_line_mouse_event(&swaybar, x, y, 2); - break; - case BTN_RIGHT: - status_line_mouse_event(&swaybar, x, y, 3); - break; - } - -#ifdef ENABLE_TRAY - tray_mouse_event(clicked_output, x, y, button, state_w); -#endif - +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t width, uint32_t height) { + struct swaybar_output *output = data; + output->width = width; + output->height = height; + zwlr_layer_surface_v1_ack_configure(surface, serial); + render_frame(output->bar, output); } -static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) { - sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down"); - - // If there are status blocks and click_events are enabled - // check if the position is within the status area and if so - // tell the status line to output the event and skip workspace - // switching below. - int num_blocks = swaybar.status->block_line->length; - if (swaybar.status->click_events && num_blocks > 0) { - struct status_block *first_block = swaybar.status->block_line->items[0]; - int x = window->pointer_input.last_x; - int y = window->pointer_input.last_y; - if (x > first_block->x) { - if (direction == SCROLL_UP) { - status_line_mouse_event(&swaybar, x, y, 4); - } else { - status_line_mouse_event(&swaybar, x, y, 5); - } - return; - } - } +static void layer_surface_closed(void *_output, + struct zwlr_layer_surface_v1 *surface) { + // TODO: Deal with hotplugging + struct swaybar_output *output = output; + zwlr_layer_surface_v1_destroy(output->layer_surface); + wl_surface_destroy(output->surface); +} - if (!swaybar.config->wrap_scroll) { - // Find output this window lives on - int i; - struct output *output = NULL; - for (i = 0; i < swaybar.outputs->length; ++i) { - output = swaybar.outputs->items[i]; - if (output->window == window) { - break; - } - } - if (!sway_assert(i != swaybar.outputs->length, "Unknown window in scroll event")) { - return; - } - int focused = -1; - for (i = 0; i < output->workspaces->length; ++i) { - struct workspace *ws = output->workspaces->items[i]; - if (ws->focused) { - focused = i; - break; - } - } - if (!sway_assert(focused != -1, "Scroll wheel event received on inactive output")) { - return; - } - if ((focused == 0 && direction == SCROLL_UP) || - (focused == output->workspaces->length - 1 && direction == SCROLL_DOWN)) { - // Do not wrap - return; - } +struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed, +}; + +static void handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + struct swaybar *bar = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + bar->compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + bar->shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + static int idx = 0; + struct swaybar_output *output = + calloc(1, sizeof(struct swaybar_output)); + output->bar = bar; + output->output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + output->idx = idx++; + wl_list_insert(&bar->outputs, &output->link); + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + bar->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); } +} - const char *workspace_name = direction == SCROLL_UP ? "prev_on_output" : "next_on_output"; - ipc_send_workspace_command(workspace_name); +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares } -void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { - /* initialize bar with default values */ - bar_init(bar); +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; - /* Initialize event loop lists */ +void bar_setup(struct swaybar *bar, + const char *socket_path, const char *bar_id) { + bar_init(bar); init_event_loop(); - /* connect to sway ipc */ - bar->ipc_socketfd = ipc_open_socket(socket_path); - bar->ipc_event_socketfd = ipc_open_socket(socket_path); - - ipc_bar_init(bar, bar_id); - - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *bar_output = bar->outputs->items[i]; - - bar_output->registry = registry_poll(); - - if (!bar_output->registry->desktop_shell) { - sway_abort("swaybar requires the compositor to support the desktop-shell extension."); - } - - struct output_state *output = bar_output->registry->outputs->items[bar_output->idx]; - - bar_output->window = window_setup(bar_output->registry, - output->width / output->scale, 30, output->scale, false); - if (!bar_output->window) { - sway_abort("Failed to create window."); - } - desktop_shell_set_panel(bar_output->registry->desktop_shell, - output->output, bar_output->window->surface); - desktop_shell_set_panel_position(bar_output->registry->desktop_shell, + assert(bar->display = wl_display_connect(NULL)); + + struct wl_registry *registry = wl_display_get_registry(bar->display); + wl_registry_add_listener(registry, ®istry_listener, bar); + wl_display_roundtrip(bar->display); + assert(bar->compositor && bar->layer_shell && bar->shm); + + // TODO: we might not necessarily be meant to do all of the outputs + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + assert(output->surface = wl_compositor_create_surface(bar->compositor)); + output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + bar->layer_shell, output->surface, output->output, + ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); + assert(output->layer_surface); + zwlr_layer_surface_v1_add_listener(output->layer_surface, + &layer_surface_listener, output); + zwlr_layer_surface_v1_set_anchor(output->layer_surface, bar->config->position); - - window_make_shell(bar_output->window); - - /* set font */ - bar_output->window->font = bar->config->font; - - /* set mouse event callbacks */ - bar_output->window->pointer_input.notify_button = mouse_button_notify; - bar_output->window->pointer_input.notify_scroll = mouse_scroll_notify; - - /* set window height */ - set_window_height(bar_output->window, bar->config->height); + render_frame(bar, output); } - /* spawn status command */ - spawn_status_cmd_proc(bar); - -#ifdef ENABLE_TRAY - init_tray(bar); -#endif } -bool dirty = true; - -static void respond_ipc(int fd, short mask, void *_bar) { - struct bar *bar = (struct bar *)_bar; - sway_log(L_DEBUG, "Got IPC event."); - dirty = handle_ipc_event(bar); -} - -static void respond_command(int fd, short mask, void *_bar) { - struct bar *bar = (struct bar *)_bar; - dirty = handle_status_line(bar); -} - -static void respond_output(int fd, short mask, void *_output) { - struct output *output = (struct output *)_output; - if (wl_display_dispatch(output->registry->display) == -1) { - sway_log(L_ERROR, "failed to dispatch wl: %d", errno); +static void display_in(int fd, short mask, void *_bar) { + struct swaybar *bar = (struct swaybar *)_bar; + if (wl_display_dispatch(bar->display) == -1) { + wlr_log(L_ERROR, "failed to dispatch wl: %d", errno); } } -void bar_run(struct bar *bar) { - add_event(bar->ipc_event_socketfd, POLLIN, respond_ipc, bar); - add_event(bar->status_read_fd, POLLIN, respond_command, bar); - - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *output = bar->outputs->items[i]; - add_event(wl_display_get_fd(output->registry->display), - POLLIN, respond_output, output); - } - +void bar_run(struct swaybar *bar) { + add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); while (1) { - if (dirty) { - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *output = bar->outputs->items[i]; - if (window_prerender(output->window) && output->window->cairo) { - render(output, bar->config, bar->status); - window_render(output->window); - wl_display_flush(output->registry->display); - } - } - } - - dirty = false; - event_loop_poll(); -#ifdef ENABLE_TRAY - dispatch_dbus(); -#endif } } -void free_workspaces(list_t *workspaces) { - int i; - for (i = 0; i < workspaces->length; ++i) { - struct workspace *ws = workspaces->items[i]; - free(ws->name); - free(ws); +static void free_outputs(struct wl_list *list) { + struct swaybar_output *output, *tmp; + wl_list_for_each_safe(output, tmp, list, link) { + wl_list_remove(&output->link); + free(output->name); + free(output); } - list_free(workspaces); } -static void free_output(struct output *output) { - window_teardown(output->window); - if (output->registry) { - registry_teardown(output->registry); - } - - free(output->name); - - if (output->workspaces) { - free_workspaces(output->workspaces); - } - - free(output); -} - -static void free_outputs(list_t *outputs) { - int i; - for (i = 0; i < outputs->length; ++i) { - free_output(outputs->items[i]); - } - list_free(outputs); -} - -static void terminate_status_command(pid_t pid) { - if (pid) { - // terminate status_command process - int ret = kill(pid, SIGTERM); - if (ret != 0) { - sway_log(L_ERROR, "Unable to terminate status_command [pid: %d]", pid); - } else { - int status; - waitpid(pid, &status, 0); - } - } -} - -void bar_teardown(struct bar *bar) { +void bar_teardown(struct swaybar *bar) { + free_outputs(&bar->outputs); if (bar->config) { free_config(bar->config); } - - if (bar->outputs) { - free_outputs(bar->outputs); - } - - if (bar->status) { - free_status_line(bar->status); - } - - /* close sockets/pipes */ - if (bar->status_read_fd) { - close(bar->status_read_fd); - } - - if (bar->status_write_fd) { - close(bar->status_write_fd); - } - - if (bar->ipc_socketfd) { - close(bar->ipc_socketfd); - } - - if (bar->ipc_event_socketfd) { - close(bar->ipc_event_socketfd); - } - - /* terminate status command process */ - terminate_status_command(bar->status_command_pid); } diff --git a/swaybar/config.c b/swaybar/config.c index 8fe552f2..0c2b57e0 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -1,21 +1,24 @@ #define _XOPEN_SOURCE 500 #include #include -#include "wayland-desktop-shell-client-protocol.h" -#include "log.h" #include "swaybar/config.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" uint32_t parse_position(const char *position) { + uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + uint32_t vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; if (strcmp("top", position) == 0) { - return DESKTOP_SHELL_PANEL_POSITION_TOP; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | horiz; } else if (strcmp("bottom", position) == 0) { - return DESKTOP_SHELL_PANEL_POSITION_BOTTOM; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | horiz; } else if (strcmp("left", position) == 0) { - return DESKTOP_SHELL_PANEL_POSITION_LEFT; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | vert; } else if (strcmp("right", position) == 0) { - return DESKTOP_SHELL_PANEL_POSITION_RIGHT; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | vert; } else { - return DESKTOP_SHELL_PANEL_POSITION_BOTTOM; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | horiz; } } @@ -30,11 +33,11 @@ char *parse_font(const char *font) { return new_font; } -struct config *init_config() { - struct config *config = calloc(1, sizeof(struct config)); +struct swaybar_config *init_config() { + struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); config->status_command = NULL; config->pango_markup = false; - config->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM; + config->position = parse_position("bottom"); config->font = strdup("monospace 10"); config->mode = NULL; config->sep_symbol = NULL; @@ -48,18 +51,6 @@ struct config *init_config() { /* height */ config->height = 0; -#ifdef ENABLE_TRAY - config->tray_output = NULL; - config->icon_theme = NULL; - config->tray_padding = 2; - /** - * These constants are used by wayland and are defined in - * linux/input-event-codes.h - */ - config->activate_button = 0x110; /* BTN_LEFT */ - config->context_button = 0x111; /* BTN_RIGHT */ -#endif - /* colors */ config->colors.background = 0x000000FF; config->colors.statusline = 0xFFFFFFFF; @@ -88,7 +79,7 @@ struct config *init_config() { return config; } -void free_config(struct config *config) { +void free_config(struct swaybar_config *config) { free(config->status_command); free(config->font); free(config->mode); diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c index 0d1be1da..748372ed 100644 --- a/swaybar/event_loop.c +++ b/swaybar/event_loop.c @@ -4,19 +4,18 @@ #include #include #include -#include "swaybar/bar.h" +#include #include "swaybar/event_loop.h" #include "list.h" -#include "log.h" struct event_item { - void(*cb)(int fd, short mask, void *data); + void (*cb)(int fd, short mask, void *data); void *data; }; struct timer_item { timer_t timer; - void(*cb)(timer_t timer, void *data); + void (*cb)(timer_t timer, void *data); void *data; }; @@ -138,7 +137,8 @@ void event_loop_poll() { void init_event_loop() { event_loop.fds.length = 0; event_loop.fds.capacity = 10; - event_loop.fds.items = malloc(event_loop.fds.capacity * sizeof(struct pollfd)); + event_loop.fds.items = malloc( + event_loop.fds.capacity * sizeof(struct pollfd)); event_loop.items = create_list(); event_loop.timers = create_list(); } diff --git a/swaybar/ipc.c b/swaybar/ipc.c deleted file mode 100644 index 93d1219c..00000000 --- a/swaybar/ipc.c +++ /dev/null @@ -1,410 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include "swaybar/config.h" -#include "swaybar/ipc.h" -#include "ipc-client.h" -#include "list.h" -#include "log.h" - -void ipc_send_workspace_command(const char *workspace_name) { - uint32_t size = strlen("workspace \"\"") + strlen(workspace_name) + 1; - - char command[size]; - sprintf(command, "workspace \"%s\"", workspace_name); - - ipc_single_command(swaybar.ipc_socketfd, IPC_COMMAND, command, &size); -} - -static void ipc_parse_config(struct config *config, const char *payload) { - json_object *bar_config = json_tokener_parse(payload); - json_object *markup, *mode, *hidden_bar, *position, *status_command; - json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; - json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; -#ifdef ENABLE_TRAY - json_object *tray_output, *icon_theme, *tray_padding, *activate_button, *context_button; - json_object *secondary_button; - json_object_object_get_ex(bar_config, "tray_output", &tray_output); - json_object_object_get_ex(bar_config, "icon_theme", &icon_theme); - json_object_object_get_ex(bar_config, "tray_padding", &tray_padding); - json_object_object_get_ex(bar_config, "activate_button", &activate_button); - json_object_object_get_ex(bar_config, "context_button", &context_button); - json_object_object_get_ex(bar_config, "secondary_button", &secondary_button); -#endif - json_object_object_get_ex(bar_config, "mode", &mode); - json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); - json_object_object_get_ex(bar_config, "position", &position); - json_object_object_get_ex(bar_config, "status_command", &status_command); - json_object_object_get_ex(bar_config, "font", &font); - json_object_object_get_ex(bar_config, "bar_height", &bar_height); - json_object_object_get_ex(bar_config, "wrap_scroll", &wrap_scroll); - json_object_object_get_ex(bar_config, "workspace_buttons", &workspace_buttons); - json_object_object_get_ex(bar_config, "strip_workspace_numbers", &strip_workspace_numbers); - json_object_object_get_ex(bar_config, "binding_mode_indicator", &binding_mode_indicator); - json_object_object_get_ex(bar_config, "verbose", &verbose); - json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol); - json_object_object_get_ex(bar_config, "colors", &colors); - json_object_object_get_ex(bar_config, "outputs", &outputs); - json_object_object_get_ex(bar_config, "pango_markup", &markup); - - if (status_command) { - free(config->status_command); - config->status_command = strdup(json_object_get_string(status_command)); - } - - if (position) { - config->position = parse_position(json_object_get_string(position)); - } - - if (font) { - free(config->font); - config->font = parse_font(json_object_get_string(font)); - } - - if (sep_symbol) { - free(config->sep_symbol); - config->sep_symbol = strdup(json_object_get_string(sep_symbol)); - } - - if (strip_workspace_numbers) { - config->strip_workspace_numbers = json_object_get_boolean(strip_workspace_numbers); - } - - if (binding_mode_indicator) { - config->binding_mode_indicator = json_object_get_boolean(binding_mode_indicator); - } - - if (wrap_scroll) { - config->wrap_scroll = json_object_get_boolean(wrap_scroll); - } - - if (workspace_buttons) { - config->workspace_buttons = json_object_get_boolean(workspace_buttons); - } - - if (bar_height) { - config->height = json_object_get_int(bar_height); - } - - if (markup) { - config->pango_markup = json_object_get_boolean(markup); - } - -#ifdef ENABLE_TRAY - if (tray_output) { - free(config->tray_output); - config->tray_output = strdup(json_object_get_string(tray_output)); - } - - if (icon_theme) { - free(config->icon_theme); - config->icon_theme = strdup(json_object_get_string(icon_theme)); - } - - if (tray_padding) { - config->tray_padding = json_object_get_int(tray_padding); - } - - if (activate_button) { - config->activate_button = json_object_get_int(activate_button); - } - - if (context_button) { - config->context_button = json_object_get_int(context_button); - } - - if (secondary_button) { - config->secondary_button = json_object_get_int(secondary_button); - } -#endif - - // free previous outputs list - int i; - for (i = 0; i < config->outputs->length; ++i) { - free(config->outputs->items[i]); - } - list_free(config->outputs); - config->outputs = create_list(); - - if (outputs) { - int length = json_object_array_length(outputs); - json_object *output; - const char *output_str; - for (i = 0; i < length; ++i) { - output = json_object_array_get_idx(outputs, i); - output_str = json_object_get_string(output); - if (strcmp("*", output_str) == 0) { - config->all_outputs = true; - break; - } - list_add(config->outputs, strdup(output_str)); - } - } else { - config->all_outputs = true; - } - - if (colors) { - json_object *background, *statusline, *separator; - json_object *focused_background, *focused_statusline, *focused_separator; - json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text; - json_object *inactive_workspace_border, *inactive_workspace_bg, *inactive_workspace_text; - json_object *active_workspace_border, *active_workspace_bg, *active_workspace_text; - json_object *urgent_workspace_border, *urgent_workspace_bg, *urgent_workspace_text; - json_object *binding_mode_border, *binding_mode_bg, *binding_mode_text; - json_object_object_get_ex(colors, "background", &background); - json_object_object_get_ex(colors, "statusline", &statusline); - json_object_object_get_ex(colors, "separator", &separator); - json_object_object_get_ex(colors, "focused_background", &focused_background); - json_object_object_get_ex(colors, "focused_statusline", &focused_statusline); - json_object_object_get_ex(colors, "focused_separator", &focused_separator); - json_object_object_get_ex(colors, "focused_workspace_border", &focused_workspace_border); - json_object_object_get_ex(colors, "focused_workspace_bg", &focused_workspace_bg); - json_object_object_get_ex(colors, "focused_workspace_text", &focused_workspace_text); - json_object_object_get_ex(colors, "active_workspace_border", &active_workspace_border); - json_object_object_get_ex(colors, "active_workspace_bg", &active_workspace_bg); - json_object_object_get_ex(colors, "active_workspace_text", &active_workspace_text); - json_object_object_get_ex(colors, "inactive_workspace_border", &inactive_workspace_border); - json_object_object_get_ex(colors, "inactive_workspace_bg", &inactive_workspace_bg); - json_object_object_get_ex(colors, "inactive_workspace_text", &inactive_workspace_text); - json_object_object_get_ex(colors, "urgent_workspace_border", &urgent_workspace_border); - json_object_object_get_ex(colors, "urgent_workspace_bg", &urgent_workspace_bg); - json_object_object_get_ex(colors, "urgent_workspace_text", &urgent_workspace_text); - json_object_object_get_ex(colors, "binding_mode_border", &binding_mode_border); - json_object_object_get_ex(colors, "binding_mode_bg", &binding_mode_bg); - json_object_object_get_ex(colors, "binding_mode_text", &binding_mode_text); - if (background) { - config->colors.background = parse_color(json_object_get_string(background)); - } - - if (statusline) { - config->colors.statusline = parse_color(json_object_get_string(statusline)); - } - - if (separator) { - config->colors.separator = parse_color(json_object_get_string(separator)); - } - - if (focused_background) { - config->colors.focused_background = parse_color(json_object_get_string(focused_background)); - } - - if (focused_statusline) { - config->colors.focused_statusline = parse_color(json_object_get_string(focused_statusline)); - } - - if (focused_separator) { - config->colors.focused_separator = parse_color(json_object_get_string(focused_separator)); - } - - if (focused_workspace_border) { - config->colors.focused_workspace.border = parse_color(json_object_get_string(focused_workspace_border)); - } - - if (focused_workspace_bg) { - config->colors.focused_workspace.background = parse_color(json_object_get_string(focused_workspace_bg)); - } - - if (focused_workspace_text) { - config->colors.focused_workspace.text = parse_color(json_object_get_string(focused_workspace_text)); - } - - if (active_workspace_border) { - config->colors.active_workspace.border = parse_color(json_object_get_string(active_workspace_border)); - } - - if (active_workspace_bg) { - config->colors.active_workspace.background = parse_color(json_object_get_string(active_workspace_bg)); - } - - if (active_workspace_text) { - config->colors.active_workspace.text = parse_color(json_object_get_string(active_workspace_text)); - } - - if (inactive_workspace_border) { - config->colors.inactive_workspace.border = parse_color(json_object_get_string(inactive_workspace_border)); - } - - if (inactive_workspace_bg) { - config->colors.inactive_workspace.background = parse_color(json_object_get_string(inactive_workspace_bg)); - } - - if (inactive_workspace_text) { - config->colors.inactive_workspace.text = parse_color(json_object_get_string(inactive_workspace_text)); - } - - if (binding_mode_border) { - config->colors.binding_mode.border = parse_color(json_object_get_string(binding_mode_border)); - } - - if (binding_mode_bg) { - config->colors.binding_mode.background = parse_color(json_object_get_string(binding_mode_bg)); - } - - if (binding_mode_text) { - config->colors.binding_mode.text = parse_color(json_object_get_string(binding_mode_text)); - } - } - - json_object_put(bar_config); -} - -static void ipc_update_workspaces(struct bar *bar) { - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *output = bar->outputs->items[i]; - if (output->workspaces) { - free_workspaces(output->workspaces); - } - output->workspaces = create_list(); - } - - uint32_t len = 0; - char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); - json_object *results = json_tokener_parse(res); - if (!results) { - free(res); - return; - } - - int length = json_object_array_length(results); - json_object *ws_json; - json_object *num, *name, *visible, *focused, *out, *urgent; - for (i = 0; i < length; ++i) { - ws_json = json_object_array_get_idx(results, i); - - json_object_object_get_ex(ws_json, "num", &num); - json_object_object_get_ex(ws_json, "name", &name); - json_object_object_get_ex(ws_json, "visible", &visible); - json_object_object_get_ex(ws_json, "focused", &focused); - json_object_object_get_ex(ws_json, "output", &out); - json_object_object_get_ex(ws_json, "urgent", &urgent); - - int j; - for (j = 0; j < bar->outputs->length; ++j) { - struct output *output = bar->outputs->items[j]; - if (strcmp(json_object_get_string(out), output->name) == 0) { - struct workspace *ws = malloc(sizeof(struct workspace)); - ws->num = json_object_get_int(num); - ws->name = strdup(json_object_get_string(name)); - ws->visible = json_object_get_boolean(visible); - ws->focused = json_object_get_boolean(focused); - if (ws->focused) { - if (bar->focused_output) { - bar->focused_output->focused = false; - } - bar->focused_output = output; - output->focused = true; - } - ws->urgent = json_object_get_boolean(urgent); - list_add(output->workspaces, ws); - } - } - } - - json_object_put(results); - free(res); -} - -void ipc_bar_init(struct bar *bar, const char *bar_id) { - // Get bar config - uint32_t len = strlen(bar_id); - char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len); - - ipc_parse_config(bar->config, res); - free(res); - - // Get outputs - len = 0; - res = ipc_single_command(bar->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len); - json_object *outputs = json_tokener_parse(res); - int i; - int length = json_object_array_length(outputs); - json_object *output, *output_name, *output_active; - const char *name; - bool active; - for (i = 0; i < length; ++i) { - output = json_object_array_get_idx(outputs, i); - json_object_object_get_ex(output, "name", &output_name); - json_object_object_get_ex(output, "active", &output_active); - name = json_object_get_string(output_name); - active = json_object_get_boolean(output_active); - if (!active) { - continue; - } - - bool use_output = false; - if (bar->config->all_outputs) { - use_output = true; - } else { - int j = 0; - for (j = 0; j < bar->config->outputs->length; ++j) { - const char *conf_name = bar->config->outputs->items[j]; - if (strcasecmp(name, conf_name) == 0) { - use_output = true; - break; - } - } - } - - if (!use_output) { - continue; - } - - // add bar to the output - struct output *bar_output = new_output(name); - bar_output->idx = i; - list_add(bar->outputs, bar_output); - } - free(res); - json_object_put(outputs); - - const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; - len = strlen(subscribe_json); - res = ipc_single_command(bar->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); - free(res); - - ipc_update_workspaces(bar); -} - -bool handle_ipc_event(struct bar *bar) { - struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); - if (!resp) { - return false; - } - switch (resp->type) { - case IPC_EVENT_WORKSPACE: - ipc_update_workspaces(bar); - break; - case IPC_EVENT_MODE: { - json_object *result = json_tokener_parse(resp->payload); - if (!result) { - free_ipc_response(resp); - sway_log(L_ERROR, "failed to parse payload as json"); - return false; - } - json_object *json_change; - if (json_object_object_get_ex(result, "change", &json_change)) { - const char *change = json_object_get_string(json_change); - - free(bar->config->mode); - if (strcmp(change, "default") == 0) { - bar->config->mode = NULL; - } else { - bar->config->mode = strdup(change); - } - } else { - sway_log(L_ERROR, "failed to parse response"); - } - - json_object_put(result); - break; - } - default: - free_ipc_response(resp); - return false; - } - - free_ipc_response(resp); - return true; -} diff --git a/swaybar/main.c b/swaybar/main.c index 0abd0755..c897e1c9 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -4,21 +4,20 @@ #include #include #include +#include #include "swaybar/bar.h" #include "ipc-client.h" -#include "log.h" -/* global bar state */ -struct bar swaybar; +static struct swaybar swaybar; -void sway_terminate(int exit_code) { +void sig_handler(int signal) { bar_teardown(&swaybar); - exit(exit_code); + exit(0); } -void sig_handler(int signal) { +void sway_terminate(int code) { bar_teardown(&swaybar); - exit(0); + exit(code); } int main(int argc, char **argv) { @@ -75,20 +74,23 @@ int main(int argc, char **argv) { } } - if (!bar_id) { - sway_abort("No bar_id passed. Provide --bar_id or let sway start swaybar"); - } - if (debug) { - init_log(L_DEBUG); + wlr_log_init(L_DEBUG, NULL); } else { - init_log(L_ERROR); + wlr_log_init(L_ERROR, NULL); + } + + if (!bar_id) { + wlr_log(L_ERROR, "No bar_id passed. " + "Provide --bar_id or let sway start swaybar"); + return 1; } if (!socket_path) { socket_path = get_socketpath(); if (!socket_path) { - sway_abort("Unable to retrieve socket path"); + wlr_log(L_ERROR, "Unable to retrieve socket path"); + return 1; } } @@ -100,9 +102,6 @@ int main(int argc, char **argv) { free(bar_id); bar_run(&swaybar); - - // gracefully shutdown swaybar and status_command bar_teardown(&swaybar); - return 0; } diff --git a/swaybar/meson.build b/swaybar/meson.build new file mode 100644 index 00000000..fd87e51d --- /dev/null +++ b/swaybar/meson.build @@ -0,0 +1,25 @@ +executable( + 'swaybar', + [ + 'bar.c', + 'config.c', + 'event_loop.c', + 'main.c', + 'render.c', + ], + include_directories: [sway_inc], + dependencies: [ + cairo, + client_protos, + gdk_pixbuf, + jsonc, + math, + pango, + pangocairo, + rt, + wayland_client, + wlroots, + ], + link_with: [lib_sway_common, lib_sway_client], + install: true +) diff --git a/swaybar/render.c b/swaybar/render.c index 6fc09078..2eaa0195 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -1,367 +1,63 @@ #include #include #include - -#include "client/cairo.h" -#include "client/pango.h" -#include "client/window.h" +#include +#include "cairo.h" +#include "pango.h" +#include "pool-buffer.h" +#include "swaybar/bar.h" #include "swaybar/config.h" -#include "swaybar/status_line.h" #include "swaybar/render.h" -#ifdef ENABLE_TRAY -#include "swaybar/tray/tray.h" -#include "swaybar/tray/sni.h" -#endif -#include "log.h" - - -/* internal spacing */ -static int margin = 3; -static int ws_horizontal_padding = 5; -static double ws_vertical_padding = 1.5; -static int ws_spacing = 1; - -/** - * Renders a sharp line of any width and height. - * - * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0 - * if the line has a width/height of one pixel, respectively. - */ -static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) { - cairo_set_source_u32(cairo, color); - - if (width > 1 && height > 1) { - cairo_rectangle(cairo, x, y, width, height); - cairo_fill(cairo); - } else { - if (width == 1) { - x += 0.5; - height += y; - width = x; - } - - if (height == 1) { - y += 0.5; - width += x; - height = y; - } - - cairo_move_to(cairo, x, y); - cairo_set_line_width(cairo, 1.0); - cairo_line_to(cairo, width, height); - cairo_stroke(cairo); - } -} - -static void render_block(struct window *window, struct config *config, struct status_block *block, double *x, bool edge, bool is_focused) { - int width, height, sep_width; - get_text_size(window->cairo, window->font, &width, &height, - window->scale, block->markup, "%s", block->full_text); - - int textwidth = width; - double block_width = width; - - if (width < block->min_width) { - width = block->min_width; - } - - *x -= width; - - if (block->border != 0 && block->border_left > 0) { - *x -= (block->border_left + margin); - block_width += block->border_left + margin; - } - - if (block->border != 0 && block->border_right > 0) { - *x -= (block->border_right + margin); - block_width += block->border_right + margin; - } - - // Add separator - if (!edge) { - if (config->sep_symbol) { - get_text_size(window->cairo, window->font, &sep_width, &height, - window->scale, false, "%s", config->sep_symbol); - if (sep_width > block->separator_block_width) { - block->separator_block_width = sep_width + margin * 2; - } - } - - *x -= block->separator_block_width; - } else { - *x -= margin; - } - - double pos = *x; - - block->x = (int)pos; - block->width = (int)block_width; - - // render background - if (block->background != 0x0) { - cairo_set_source_u32(window->cairo, block->background); - cairo_rectangle(window->cairo, pos - 0.5, 1, block_width, (window->height * window->scale) - 2); - cairo_fill(window->cairo); - } - - // render top border - if (block->border != 0 && block->border_top > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block_width, - block->border_top); - } - - // render bottom border - if (block->border != 0 && block->border_bottom > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - (window->height * window->scale) - 1 - block->border_bottom, - block_width, - block->border_bottom); - } - - // render left border - if (block->border != 0 && block->border_left > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block->border_left, - (window->height * window->scale) - 2); - - pos += block->border_left + margin; - } - - // render text - double offset = 0; - - if (strncmp(block->align, "left", 5) == 0) { - offset = pos; - } else if (strncmp(block->align, "right", 5) == 0) { - offset = pos + width - textwidth; - } else if (strncmp(block->align, "center", 6) == 0) { - offset = pos + (width - textwidth) / 2; - } - - cairo_move_to(window->cairo, offset, margin); - cairo_set_source_u32(window->cairo, block->color); - pango_printf(window->cairo, window->font, window->scale, - block->markup, "%s", block->full_text); - - pos += width; +#include "wlr-layer-shell-unstable-v1-client-protocol.h" - // render right border - if (block->border != 0 && block->border_right > 0) { - pos += margin; - - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block->border_right, - (window->height * window->scale) - 2); - - pos += block->border_right; - } - - // render separator - if (!edge && block->separator) { - if (is_focused) { - cairo_set_source_u32(window->cairo, config->colors.focused_separator); - } else { - cairo_set_source_u32(window->cairo, config->colors.separator); - } - if (config->sep_symbol) { - offset = pos + (block->separator_block_width - sep_width) / 2; - cairo_move_to(window->cairo, offset, margin); - pango_printf(window->cairo, window->font, window->scale, - false, "%s", config->sep_symbol); - } else { - cairo_set_line_width(window->cairo, 1); - cairo_move_to(window->cairo, pos + block->separator_block_width/2, - margin); - cairo_line_to(window->cairo, pos + block->separator_block_width/2, - (window->height * window->scale) - margin); - cairo_stroke(window->cairo); - } - } +static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, + struct swaybar_output *output) { + struct swaybar_config *config = bar->config; -} - -static const char *strip_workspace_name(bool strip_num, const char *ws_name) { - bool strip = false; - int i; - - if (strip_num) { - int len = strlen(ws_name); - for (i = 0; i < len; ++i) { - if (!('0' <= ws_name[i] && ws_name[i] <= '9')) { - if (':' == ws_name[i] && i < len-1 && i > 0) { - strip = true; - ++i; - } - break; - } - } - } - - if (strip) { - return ws_name + i; - } - - return ws_name; -} - -void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height) { - const char *stripped_name = strip_workspace_name(swaybar.config->strip_workspace_numbers, workspace_name); - - get_text_size(window->cairo, window->font, width, height, - window->scale, true, "%s", stripped_name); - *width += 2 * ws_horizontal_padding; - *height += 2 * ws_vertical_padding; -} - -static void render_workspace_button(struct window *window, struct config *config, struct workspace *ws, double *x) { - const char *stripped_name = strip_workspace_name(config->strip_workspace_numbers, ws->name); - - struct box_colors box_colors; - if (ws->urgent) { - box_colors = config->colors.urgent_workspace; - } else if (ws->focused) { - box_colors = config->colors.focused_workspace; - } else if (ws->visible) { - box_colors = config->colors.active_workspace; - } else { - box_colors = config->colors.inactive_workspace; - } - - int width, height; - workspace_button_size(window, stripped_name, &width, &height); - - // background - cairo_set_source_u32(window->cairo, box_colors.background); - cairo_rectangle(window->cairo, *x, 1.5, width - 1, height); - cairo_fill(window->cairo); - - // border - cairo_set_source_u32(window->cairo, box_colors.border); - cairo_rectangle(window->cairo, *x, 1.5, width - 1, height); - cairo_stroke(window->cairo); - - // text - cairo_set_source_u32(window->cairo, box_colors.text); - cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin); - pango_printf(window->cairo, window->font, window->scale, - true, "%s", stripped_name); - - *x += width + ws_spacing; -} - -static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) { - int width, height; - get_text_size(window->cairo, window->font, &width, &height, - window->scale, false, "%s", config->mode); - - // background - cairo_set_source_u32(window->cairo, config->colors.binding_mode.background); - cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); - cairo_fill(window->cairo); - - // border - cairo_set_source_u32(window->cairo, config->colors.binding_mode.border); - cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); - cairo_stroke(window->cairo); - - // text - cairo_set_source_u32(window->cairo, config->colors.binding_mode.text); - cairo_move_to(window->cairo, (int)pos + ws_horizontal_padding, margin); - pango_printf(window->cairo, window->font, window->scale, - false, "%s", config->mode); -} - -void render(struct output *output, struct config *config, struct status_line *line) { - int i; - - struct window *window = output->window; - cairo_t *cairo = window->cairo; - bool is_focused = output->focused; - - // Clear cairo_save(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); cairo_restore(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - - // Background - if (is_focused) { + if (output->focused) { cairo_set_source_u32(cairo, config->colors.focused_background); } else { cairo_set_source_u32(cairo, config->colors.background); } cairo_paint(cairo); -#ifdef ENABLE_TRAY - uint32_t tray_width = tray_render(output, config); -#else - const uint32_t tray_width = window->width * window->scale; -#endif - - // Command output - if (is_focused) { - cairo_set_source_u32(cairo, config->colors.focused_statusline); + // TODO: use actual height + return 20; +} + +void render_frame(struct swaybar *bar, + struct swaybar_output *output) { + cairo_surface_t *recorder = cairo_recording_surface_create( + CAIRO_CONTENT_COLOR_ALPHA, NULL); + cairo_t *cairo = cairo_create(recorder); + uint32_t height = render_to_cairo(cairo, bar, output); + if (height != output->height) { + // Reconfigure surface + zwlr_layer_surface_v1_set_size( + output->layer_surface, 0, height); + // TODO: this could infinite loop if the compositor assigns us a + // different height than what we asked for + wl_surface_commit(output->surface); + wl_display_roundtrip(bar->display); } else { - cairo_set_source_u32(cairo, config->colors.statusline); - } - - int width, height; - - if (line->protocol == TEXT) { - get_text_size(window->cairo, window->font, &width, &height, - window->scale, config->pango_markup, "%s", line->text_line); - cairo_move_to(cairo, tray_width - margin - width, margin); - pango_printf(window->cairo, window->font, window->scale, - config->pango_markup, "%s", line->text_line); - } else if (line->protocol == I3BAR && line->block_line) { - double pos = tray_width - 0.5; - bool edge = true; - for (i = line->block_line->length - 1; i >= 0; --i) { - struct status_block *block = line->block_line->items[i]; - if (block->full_text && block->full_text[0]) { - render_block(window, config, block, &pos, edge, is_focused); - edge = false; - } - } - } - - cairo_set_line_width(cairo, 1.0); - double x = 0.5; - - // Workspaces - if (config->workspace_buttons) { - for (i = 0; i < output->workspaces->length; ++i) { - struct workspace *ws = output->workspaces->items[i]; - render_workspace_button(window, config, ws, &x); - } - } - - // binding mode indicator - if (config->mode && config->binding_mode_indicator) { - render_binding_mode_indicator(window, config, x); - } -} - -void set_window_height(struct window *window, int height) { - int text_width, text_height; - get_text_size(window->cairo, window->font, - &text_width, &text_height, window->scale, false, - "Test string for measuring purposes"); - if (height > 0) { - margin = (height - text_height) / 2; - ws_vertical_padding = margin - 1.5; - } - window->height = (text_height + margin * 2) / window->scale; + // Replay recording into shm and send it off + output->current_buffer = get_next_buffer(bar->shm, + output->buffers, output->width, output->height); + cairo_t *shm = output->current_buffer->cairo; + cairo_set_source_surface(shm, recorder, 0.0, 0.0); + cairo_paint(shm); + wl_surface_attach(output->surface, + output->current_buffer->buffer, 0, 0); + wl_surface_damage(output->surface, 0, 0, output->width, output->height); + wl_surface_commit(output->surface); + wl_display_roundtrip(bar->display); + } + cairo_surface_destroy(recorder); + cairo_destroy(cairo); } diff --git a/swaybar/status_line.c b/swaybar/status_line.c deleted file mode 100644 index 87e90caf..00000000 --- a/swaybar/status_line.c +++ /dev/null @@ -1,530 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include - -#include "swaybar/config.h" -#include "swaybar/status_line.h" -#include "log.h" -#include "util.h" - -#define I3JSON_MAXDEPTH 4 -#define I3JSON_UNKNOWN 0 -#define I3JSON_ARRAY 1 -#define I3JSON_STRING 2 - -struct { - int bufsize; - char *buffer; - char *line_start; - char *parserpos; - bool escape; - int depth; - int bar[I3JSON_MAXDEPTH+1]; -} i3json_state = { 0, NULL, NULL, NULL, false, 0, { I3JSON_UNKNOWN } }; - -static char line[1024]; -static char line_rest[1024]; - -static char event_buff[1024]; - -static void free_status_block(void *item) { - if (!item) { - return; - } - struct status_block *sb = (struct status_block*)item; - if (sb->full_text) { - free(sb->full_text); - } - if (sb->short_text) { - free(sb->short_text); - } - if (sb->align) { - free(sb->align); - } - if (sb->name) { - free(sb->name); - } - if (sb->instance) { - free(sb->instance); - } - free(sb); -} - -static void parse_json(struct bar *bar, const char *text) { - json_object *results = json_tokener_parse(text); - if (!results) { - sway_log(L_DEBUG, "Failed to parse json"); - return; - } - - if (json_object_array_length(results) < 1) { - return; - } - - if (bar->status->block_line) { - list_foreach(bar->status->block_line, free_status_block); - list_free(bar->status->block_line); - } - - bar->status->block_line = create_list(); - - int i; - for (i = 0; i < json_object_array_length(results); ++i) { - json_object *full_text, *short_text, *color, *min_width, *align, *urgent; - json_object *name, *instance, *separator, *separator_block_width; - json_object *background, *border, *border_top, *border_bottom; - json_object *border_left, *border_right, *markup; - - json_object *json = json_object_array_get_idx(results, i); - if (!json) { - continue; - } - - json_object_object_get_ex(json, "full_text", &full_text); - json_object_object_get_ex(json, "short_text", &short_text); - json_object_object_get_ex(json, "color", &color); - json_object_object_get_ex(json, "min_width", &min_width); - json_object_object_get_ex(json, "align", &align); - json_object_object_get_ex(json, "urgent", &urgent); - json_object_object_get_ex(json, "name", &name); - json_object_object_get_ex(json, "instance", &instance); - json_object_object_get_ex(json, "markup", &markup); - json_object_object_get_ex(json, "separator", &separator); - json_object_object_get_ex(json, "separator_block_width", &separator_block_width); - json_object_object_get_ex(json, "background", &background); - json_object_object_get_ex(json, "border", &border); - json_object_object_get_ex(json, "border_top", &border_top); - json_object_object_get_ex(json, "border_bottom", &border_bottom); - json_object_object_get_ex(json, "border_left", &border_left); - json_object_object_get_ex(json, "border_right", &border_right); - - struct status_block *new = calloc(1, sizeof(struct status_block)); - - if (full_text) { - new->full_text = strdup(json_object_get_string(full_text)); - } - - if (short_text) { - new->short_text = strdup(json_object_get_string(short_text)); - } - - if (color) { - new->color = parse_color(json_object_get_string(color)); - } else { - new->color = bar->config->colors.statusline; - } - - if (min_width) { - json_type type = json_object_get_type(min_width); - if (type == json_type_int) { - new->min_width = json_object_get_int(min_width); - } else if (type == json_type_string) { - /* the width will be calculated when rendering */ - new->min_width = 0; - } - } - - if (align) { - new->align = strdup(json_object_get_string(align)); - } else { - new->align = strdup("left"); - } - - if (urgent) { - new->urgent = json_object_get_int(urgent); - } - - if (name) { - new->name = strdup(json_object_get_string(name)); - } - - if (instance) { - new->instance = strdup(json_object_get_string(instance)); - } - - if (markup) { - new->markup = false; - const char *markup_str = json_object_get_string(markup); - if (strcmp(markup_str, "pango") == 0) { - new->markup = true; - } - } - - if (separator) { - new->separator = json_object_get_int(separator); - } else { - new->separator = true; // i3bar spec - } - - if (separator_block_width) { - new->separator_block_width = json_object_get_int(separator_block_width); - } else { - new->separator_block_width = 9; // i3bar spec - } - - // Airblader features - if (background) { - new->background = parse_color(json_object_get_string(background)); - } else { - new->background = 0x0; // transparent - } - - if (border) { - new->border = parse_color(json_object_get_string(border)); - } else { - new->border = 0x0; // transparent - } - - if (border_top) { - new->border_top = json_object_get_int(border_top); - } else { - new->border_top = 1; - } - - if (border_bottom) { - new->border_bottom = json_object_get_int(border_bottom); - } else { - new->border_bottom = 1; - } - - if (border_left) { - new->border_left = json_object_get_int(border_left); - } else { - new->border_left = 1; - } - - if (border_right) { - new->border_right = json_object_get_int(border_right); - } else { - new->border_right = 1; - } - - list_add(bar->status->block_line, new); - } - - json_object_put(results); -} - -// continue parsing from last parserpos -static int i3json_parse(struct bar *bar) { - char *c = i3json_state.parserpos; - int handled = 0; - while (*c) { - if (i3json_state.bar[i3json_state.depth] == I3JSON_STRING) { - if (!i3json_state.escape && *c == '"') { - --i3json_state.depth; - } - i3json_state.escape = !i3json_state.escape && *c == '\\'; - } else { - switch (*c) { - case '[': - ++i3json_state.depth; - if (i3json_state.depth > I3JSON_MAXDEPTH) { - sway_abort("JSON too deep"); - } - i3json_state.bar[i3json_state.depth] = I3JSON_ARRAY; - if (i3json_state.depth == 2) { - i3json_state.line_start = c; - } - break; - case ']': - if (i3json_state.bar[i3json_state.depth] != I3JSON_ARRAY) { - sway_abort("JSON malformed"); - } - --i3json_state.depth; - if (i3json_state.depth == 1) { - // c[1] is valid since c[0] != '\0' - char p = c[1]; - c[1] = '\0'; - parse_json(bar, i3json_state.line_start); - c[1] = p; - ++handled; - i3json_state.line_start = c+1; - } - break; - case '"': - ++i3json_state.depth; - if (i3json_state.depth > I3JSON_MAXDEPTH) { - sway_abort("JSON too deep"); - } - i3json_state.bar[i3json_state.depth] = I3JSON_STRING; - break; - } - } - ++c; - } - i3json_state.parserpos = c; - return handled; -} - -// Read line from file descriptor, only show the line tail if it is too long. -// In non-blocking mode treat "no more data" as a linebreak. -// If data after a line break has been read, return it in rest. -// If rest is non-empty, then use that as the start of the next line. -static int read_line_tail(int fd, char *buf, int nbyte, char *rest) { - if (fd < 0 || !buf || !nbyte) { - return -1; - } - int l; - char *buffer = malloc(nbyte*2+1); - char *readpos = buffer; - char *lf; - // prepend old data to new line if necessary - if (rest) { - l = strlen(rest); - if (l > nbyte) { - strcpy(buffer, rest + l - nbyte); - readpos += nbyte; - } else if (l) { - strcpy(buffer, rest); - readpos += l; - } - } - // read until a linefeed is found or no more data is available - while ((l = read(fd, readpos, nbyte)) > 0) { - readpos[l] = '\0'; - lf = strchr(readpos, '\n'); - if (lf) { - // linefeed found, replace with \0 - *lf = '\0'; - // give data from the end of the line, try to fill the buffer - if (lf-buffer > nbyte) { - strcpy(buf, lf - nbyte + 1); - } else { - strcpy(buf, buffer); - } - // we may have read data from the next line, save it to rest - if (rest) { - rest[0] = '\0'; - strcpy(rest, lf + 1); - } - free(buffer); - return strlen(buf); - } else { - // no linefeed found, slide data back. - int overflow = readpos - buffer + l - nbyte; - if (overflow > 0) { - memmove(buffer, buffer + overflow , nbyte + 1); - } - } - } - if (l < 0) { - free(buffer); - return l; - } - readpos[l]='\0'; - if (rest) { - rest[0] = '\0'; - } - if (nbyte < readpos - buffer + l - 1) { - memcpy(buf, readpos - nbyte + l + 1, nbyte); - } else { - strncpy(buf, buffer, nbyte); - } - buf[nbyte-1] = '\0'; - free(buffer); - return strlen(buf); -} - -// make sure that enough buffer space is available starting from parserpos -static void i3json_ensure_free(int min_free) { - int _step = 10240; - int r = min_free % _step; - if (r) { - min_free += _step - r; - } - if (!i3json_state.buffer) { - i3json_state.buffer = malloc(min_free); - i3json_state.bufsize = min_free; - i3json_state.parserpos = i3json_state.buffer; - } else { - int len = 0; - int pos = 0; - if (i3json_state.line_start) { - len = strlen(i3json_state.line_start); - pos = i3json_state.parserpos - i3json_state.line_start; - if (i3json_state.line_start != i3json_state.buffer) { - memmove(i3json_state.buffer, i3json_state.line_start, len+1); - } - } else { - len = strlen(i3json_state.buffer); - } - if (i3json_state.bufsize < len+min_free) { - i3json_state.bufsize += min_free; - if (i3json_state.bufsize > 1024000) { - sway_abort("Status line json too long or malformed."); - } - i3json_state.buffer = realloc(i3json_state.buffer, i3json_state.bufsize); - if (!i3json_state.buffer) { - sway_abort("Could not allocate json buffer"); - } - } - if (i3json_state.line_start) { - i3json_state.line_start = i3json_state.buffer; - i3json_state.parserpos = i3json_state.buffer + pos; - } else { - i3json_state.parserpos = i3json_state.buffer; - } - } - if (!i3json_state.buffer) { - sway_abort("Could not allocate buffer."); - } -} - -// append data and parse it. -static int i3json_handle_data(struct bar *bar, char *data) { - int len = strlen(data); - i3json_ensure_free(len); - strcpy(i3json_state.parserpos, data); - return i3json_parse(bar); -} - -// read data from fd and parse it. -static int i3json_handle_fd(struct bar *bar) { - i3json_ensure_free(10240); - // get fresh data at the end of the buffer - int readlen = read(bar->status_read_fd, i3json_state.parserpos, 10239); - if (readlen < 0) { - return readlen; - } - i3json_state.parserpos[readlen] = '\0'; - return i3json_parse(bar); -} - -bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button) { - sway_log(L_DEBUG, "status_line_mouse_event."); - if (!bar->status->click_events) { - sway_log(L_DEBUG, "click_events are not enabled."); - return false; - } - - if (bar->status->protocol == I3BAR) { - sway_log(L_DEBUG, "Sending click event."); - - // find clicked block - struct status_block *clicked_block = NULL; - struct status_block *current_block = NULL; - int num_blocks = bar->status->block_line->length; - - if (num_blocks == 0) { - return false; - } else { - current_block = bar->status->block_line->items[0]; - if (x < current_block->x) { - return false; - } - } - - for (int i = 0; i < num_blocks; i++) { - current_block = bar->status->block_line->items[i]; - if (x < (current_block->x + current_block->width)) { - clicked_block = current_block; - break; - } - } - - if (!clicked_block || !clicked_block->name) { - return false; - } - - // event example {"name":"capture","instance":"label","button":1,"x":3431,"y":18} - - struct json_object *event_json = json_object_new_object(); - json_object_object_add(event_json, "name", json_object_new_string(clicked_block->name)); - if (clicked_block->instance) { - json_object_object_add(event_json, "instance", json_object_new_string(clicked_block->instance)); - } - json_object_object_add(event_json, "button", json_object_new_int(button)); - json_object_object_add(event_json, "x", json_object_new_int(x)); - json_object_object_add(event_json, "y", json_object_new_int(y)); - - int len = snprintf(event_buff, sizeof(event_buff), "%s\n", json_object_to_json_string(event_json)); - - json_object_put(event_json); - - if (len <= (int)sizeof(event_buff)) { // if not truncated - write(bar->status_write_fd, event_buff, len); - return true; - } - } - - return false; -} - -bool handle_status_line(struct bar *bar) { - bool dirty = false; - - switch (bar->status->protocol) { - case I3BAR: - sway_log(L_DEBUG, "Got i3bar protocol."); - if (i3json_handle_fd(bar) > 0) { - dirty = true; - } - break; - case TEXT: - sway_log(L_DEBUG, "Got text protocol."); - read_line_tail(bar->status_read_fd, line, sizeof(line), line_rest); - dirty = true; - bar->status->text_line = line; - break; - case UNDEF: - sway_log(L_DEBUG, "Detecting protocol..."); - if (read_line_tail(bar->status_read_fd, line, sizeof(line), line_rest) < 0) { - break; - } - dirty = true; - bar->status->text_line = line; - bar->status->protocol = TEXT; - if (line[0] == '{') { - // detect i3bar json protocol - json_object *proto = json_tokener_parse(line); - if (proto) { - - json_object *version; - if (json_object_object_get_ex(proto, "version", &version) - && json_object_get_int(version) == 1 - ) { - sway_log(L_DEBUG, "Switched to i3bar protocol."); - bar->status->protocol = I3BAR; - } - - json_object *click_events; - if (json_object_object_get_ex(proto, "click_events", &click_events) - && json_object_get_boolean(click_events)) { - - sway_log(L_DEBUG, "Enabling click events."); - bar->status->click_events = true; - - const char *events_array = "[\n"; - write(bar->status_write_fd, events_array, strlen(events_array)); - } - - i3json_handle_data(bar, line_rest); - - json_object_put(proto); - } - } - break; - } - - return dirty; -} - -struct status_line *init_status_line() { - struct status_line *line = malloc(sizeof(struct status_line)); - line->block_line = create_list(); - line->text_line = NULL; - line->protocol = UNDEF; - line->click_events = false; - - return line; -} - -void free_status_line(struct status_line *line) { - if (line->block_line) { - list_foreach(line->block_line, free_status_block); - list_free(line->block_line); - } -} diff --git a/swaybar/tray/dbus.c b/swaybar/tray/dbus.c deleted file mode 100644 index 8e719fd9..00000000 --- a/swaybar/tray/dbus.c +++ /dev/null @@ -1,197 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include -#include -#include -#include "swaybar/tray/dbus.h" -#include "swaybar/event_loop.h" -#include "log.h" - -DBusConnection *conn = NULL; - -static void dispatch_watch(int fd, short mask, void *data) { - sway_log(L_DEBUG, "Dispatching watch"); - DBusWatch *watch = data; - - if (!dbus_watch_get_enabled(watch)) { - return; - } - - uint32_t flags = 0; - - if (mask & POLLIN) { - flags |= DBUS_WATCH_READABLE; - } if (mask & POLLOUT) { - flags |= DBUS_WATCH_WRITABLE; - } if (mask & POLLHUP) { - flags |= DBUS_WATCH_HANGUP; - } if (mask & POLLERR) { - flags |= DBUS_WATCH_ERROR; - } - - dbus_watch_handle(watch, flags); -} - -static dbus_bool_t add_watch(DBusWatch *watch, void *_data) { - if (!dbus_watch_get_enabled(watch)) { - // Watch should not be polled - return TRUE; - } - - short mask = 0; - uint32_t flags = dbus_watch_get_flags(watch); - - if (flags & DBUS_WATCH_READABLE) { - mask |= POLLIN; - } if (flags & DBUS_WATCH_WRITABLE) { - mask |= POLLOUT; - } - - int fd = dbus_watch_get_unix_fd(watch); - - sway_log(L_DEBUG, "Adding DBus watch fd: %d", fd); - add_event(fd, mask, dispatch_watch, watch); - - return TRUE; -} - -static void remove_watch(DBusWatch *watch, void *_data) { - int fd = dbus_watch_get_unix_fd(watch); - - remove_event(fd); -} - -static void dispatch_timeout(timer_t timer, void *data) { - sway_log(L_DEBUG, "Dispatching DBus timeout"); - DBusTimeout *timeout = data; - - if (dbus_timeout_get_enabled(timeout)) { - dbus_timeout_handle(timeout); - } -} - -static dbus_bool_t add_timeout(DBusTimeout *timeout, void *_data) { - if (!dbus_timeout_get_enabled(timeout)) { - return TRUE; - } - - timer_t *timer = malloc(sizeof(timer_t)); - if (!timer) { - sway_log(L_ERROR, "Cannot allocate memory"); - return FALSE; - } - struct sigevent ev = { - .sigev_notify = SIGEV_NONE, - }; - - if (timer_create(CLOCK_MONOTONIC, &ev, timer)) { - sway_log(L_ERROR, "Could not create DBus timer"); - return FALSE; - } - - int interval = dbus_timeout_get_interval(timeout); - int interval_sec = interval / 1000; - int interval_msec = (interval_sec * 1000) - interval; - - struct timespec period = { - (time_t) interval_sec, - ((long) interval_msec) * 1000 * 1000, - }; - struct itimerspec time = { - period, - period, - }; - - timer_settime(*timer, 0, &time, NULL); - - dbus_timeout_set_data(timeout, timer, NULL); - - sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec); - add_timer(*timer, dispatch_timeout, timeout); - - return TRUE; -} -static void remove_timeout(DBusTimeout *timeout, void *_data) { - timer_t *timer = (timer_t *) dbus_timeout_get_data(timeout); - sway_log(L_DEBUG, "Removing DBus timeout."); - - if (timer) { - remove_timer(*timer); - timer_delete(*timer); - free(timer); - } -} - -static bool should_dispatch = true; - -static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_status, - void *_data) { - if (new_status == DBUS_DISPATCH_DATA_REMAINS) { - should_dispatch = true; - } -} - -/* Public functions below */ - -void dispatch_dbus() { - if (!should_dispatch || !conn) { - return; - } - - DBusDispatchStatus status; - - do { - status = dbus_connection_dispatch(conn); - } while (status == DBUS_DISPATCH_DATA_REMAINS); - - if (status != DBUS_DISPATCH_COMPLETE) { - sway_log(L_ERROR, "Cannot dispatch dbus events: %d", status); - } - - should_dispatch = false; -} - -int dbus_init() { - DBusError error; - dbus_error_init(&error); - - conn = dbus_bus_get(DBUS_BUS_SESSION, &error); - if (conn == NULL) { - sway_log(L_INFO, "Compiled with dbus support, but unable to connect to dbus"); - sway_log(L_INFO, "swaybar will be unable to display tray icons."); - return -1; - } - - dbus_connection_set_exit_on_disconnect(conn, FALSE); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "Cannot get bus connection: %s\n", error.message); - conn = NULL; - return -1; - } - - sway_log(L_INFO, "Unique name: %s\n", dbus_bus_get_unique_name(conn)); - - // Will be called if dispatch status changes - dbus_connection_set_dispatch_status_function(conn, dispatch_status, NULL, NULL); - - if (!dbus_connection_set_watch_functions(conn, add_watch, remove_watch, - NULL, NULL, NULL)) { - dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); - sway_log(L_ERROR, "Failed to activate DBUS watch functions"); - return -1; - } - - if (!dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, - NULL, NULL, NULL)) { - dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); - dbus_connection_set_timeout_functions(conn, NULL, NULL, NULL, NULL, NULL); - sway_log(L_ERROR, "Failed to activate DBUS timeout functions"); - return -1; - } - - return 0; -} diff --git a/swaybar/tray/icon.c b/swaybar/tray/icon.c deleted file mode 100644 index c146bf32..00000000 --- a/swaybar/tray/icon.c +++ /dev/null @@ -1,400 +0,0 @@ -#define _XOPEN_SOURCE 700 -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "swaybar/tray/icon.h" -#include "swaybar/bar.h" -#include "swaybar/config.h" -#include "stringop.h" -#include "log.h" - -/** - * REVIEW: - * This file repeats lots of "costly" operations that are the same for every - * icon. It's possible to create a dictionary or some other structure to cache - * these, though it may complicate things somewhat. - * - * Also parsing (index.theme) is currently pretty messy, so that could be made - * much better as well. Over all, things work, but are not optimal. - */ - -/* Finds all themes that the given theme inherits */ -static list_t *find_inherits(const char *theme_dir) { - const char inherits[] = "Inherits"; - const char index_name[] = "index.theme"; - list_t *themes = create_list(); - FILE *index = NULL; - char *path = malloc(strlen(theme_dir) + sizeof(index_name)); - if (!path) { - goto fail; - } - if (!themes) { - goto fail; - } - - strcpy(path, theme_dir); - strcat(path, index_name); - - index = fopen(path, "r"); - if (!index) { - goto fail; - } - - char *buf = NULL; - size_t n = 0; - while (!feof(index) && getline(&buf, &n, index) != -1) { - if (n <= sizeof(inherits) + 1) { - continue; - } - if (strncmp(inherits, buf, sizeof(inherits) - 1) == 0) { - char *themestr = buf + sizeof(inherits); - themes = split_string(themestr, ","); - break; - } - } - free(buf); - -fail: - free(path); - if (index) { - fclose(index); - } - return themes; -} - -static bool isdir(const char *path) { - struct stat statbuf; - if (stat(path, &statbuf) != -1) { - if (S_ISDIR(statbuf.st_mode)) { - return true; - } - } - return false; - -} - -/** - * Returns the directory of a given theme if it exists. - * The returned pointer must be freed. - */ -static char *find_theme_dir(const char *theme) { - char *basedir; - char *icon_dir; - - if (!theme) { - return NULL; - } - - if (!(icon_dir = malloc(1024))) { - sway_log(L_ERROR, "Out of memory!"); - goto fail; - } - - if ((basedir = getenv("HOME"))) { - if (snprintf(icon_dir, 1024, "%s/.icons/%s", basedir, theme) >= 1024) { - sway_log(L_ERROR, "Path too long to render"); - // XXX perhaps just goto trying in /usr/share? This - // shouldn't happen anyway, but might with a long global - goto fail; - } - - if (isdir(icon_dir)) { - return icon_dir; - } - } - - if ((basedir = getenv("XDG_DATA_DIRS"))) { - if (snprintf(icon_dir, 1024, "%s/icons/%s", basedir, theme) >= 1024) { - sway_log(L_ERROR, "Path too long to render"); - // ditto - goto fail; - } - - if (isdir(icon_dir)) { - return icon_dir; - } - } - - // Spec says use "/usr/share/pixmaps/", but I see everything in - // "/usr/share/icons/" look it both, I suppose. - if (snprintf(icon_dir, 1024, "/usr/share/pixmaps/%s", theme) >= 1024) { - sway_log(L_ERROR, "Path too long to render"); - goto fail; - } - if (isdir(icon_dir)) { - return icon_dir; - } - - if (snprintf(icon_dir, 1024, "/usr/share/icons/%s", theme) >= 1024) { - sway_log(L_ERROR, "Path too long to render"); - goto fail; - } - if (isdir(icon_dir)) { - return icon_dir; - } - -fail: - free(icon_dir); - sway_log(L_ERROR, "Could not find dir for theme: %s", theme); - return NULL; -} - -/** - * Returns all theme dirs needed to be looked in for an icon. - * Does not check for duplicates - */ -static list_t *find_all_theme_dirs(const char *theme) { - list_t *dirs = create_list(); - if (!dirs) { - return NULL; - } - char *dir = find_theme_dir(theme); - if (dir) { - list_add(dirs, dir); - list_t *inherits = find_inherits(dir); - list_cat(dirs, inherits); - list_free(inherits); - } - dir = find_theme_dir("hicolor"); - if (dir) { - list_add(dirs, dir); - } - - return dirs; -} - -struct subdir { - int size; - char name[]; -}; - -static int subdir_str_cmp(const void *_subdir, const void *_str) { - const struct subdir *subdir = _subdir; - const char *str = _str; - return strcmp(subdir->name, str); -} -/** - * Helper to find_subdirs. Acts similar to `split_string(subdirs, ",")` but - * generates a list of struct subdirs - */ -static list_t *split_subdirs(char *subdir_str) { - list_t *subdir_list = create_list(); - char *copy = strdup(subdir_str); - if (!subdir_list || !copy) { - list_free(subdir_list); - free(copy); - return NULL; - } - - char *token; - token = strtok(copy, ","); - while(token) { - int len = strlen(token) + 1; - struct subdir *subdir = - malloc(sizeof(struct subdir) + sizeof(char [len])); - if (!subdir) { - // Return what we have - return subdir_list; - } - subdir->size = 0; - strcpy(subdir->name, token); - - list_add(subdir_list, subdir); - - token = strtok(NULL, ","); - } - free(copy); - - return subdir_list; -} -/** - * Returns a list of all subdirectories of a theme. - * Take note: the subdir names are all relative to `theme_dir` and must be - * combined with it to form a valid directory. - * - * Each member of the list is of type (struct subdir *) this struct contains - * the name of the subdir, along with size information. These must be freed - * bye the caller. - * - * This currently ignores min and max sizes of icons. - */ -static list_t* find_theme_subdirs(const char *theme_dir) { - const char index_name[] = "/index.theme"; - list_t *dirs = NULL; - char *path = malloc(strlen(theme_dir) + sizeof(index_name)); - FILE *index = NULL; - if (!path) { - sway_log(L_ERROR, "Failed to allocate memory"); - goto fail; - } - - strcpy(path, theme_dir); - strcat(path, index_name); - - index = fopen(path, "r"); - if (!index) { - sway_log(L_ERROR, "Could not open file: %s", path); - goto fail; - } - - char *buf = NULL; - size_t n = 0; - const char directories[] = "Directories"; - while (!feof(index) && getline(&buf, &n, index) != -1) { - if (n <= sizeof(directories) + 1) { - continue; - } - if (strncmp(directories, buf, sizeof(directories) - 1) == 0) { - char *dirstr = buf + sizeof(directories); - dirs = split_subdirs(dirstr); - break; - } - } - // Now, find the size of each dir - struct subdir *current_subdir = NULL; - const char size[] = "Size"; - while (!feof(index) && getline(&buf, &n, index) != -1) { - if (buf[0] == '[') { - int len = strlen(buf); - if (buf[len-1] == '\n') { - len--; - } - // replace ']' - buf[len-1] = '\0'; - - int index; - if ((index = list_seq_find(dirs, subdir_str_cmp, buf+1)) != -1) { - current_subdir = (dirs->items[index]); - } - } - - if (strncmp(size, buf, sizeof(size) - 1) == 0) { - if (current_subdir) { - current_subdir->size = atoi(buf + sizeof(size)); - } - } - } - free(buf); -fail: - free(path); - if (index) { - fclose(index); - } - return dirs; -} - -/* Returns the file of an icon given its name and size */ -static char *find_icon_file(const char *name, int size) { - int namelen = strlen(name); - list_t *dirs = find_all_theme_dirs(swaybar.config->icon_theme); - if (!dirs) { - return NULL; - } - int min_size_diff = INT_MAX; - char *current_file = NULL; - - for (int i = 0; i < dirs->length; ++i) { - char *dir = dirs->items[i]; - list_t *subdirs = find_theme_subdirs(dir); - - if (!subdirs) { - continue; - } - - for (int i = 0; i < subdirs->length; ++i) { - struct subdir *subdir = subdirs->items[i]; - - // Only use an unsized if we don't already have a - // canidate this should probably change to allow svgs - if (!subdir->size && current_file) { - continue; - } - - int size_diff = abs(size - subdir->size); - - if (size_diff >= min_size_diff) { - continue; - } - - char *path = malloc(strlen(subdir->name) + strlen(dir) + 2); - - strcpy(path, dir); - path[strlen(dir)] = '/'; - strcpy(path + strlen(dir) + 1, subdir->name); - - DIR *icons = opendir(path); - if (!icons) { - free(path); - continue; - } - - struct dirent *direntry; - while ((direntry = readdir(icons)) != NULL) { - int len = strlen(direntry->d_name); - if (len <= namelen + 2) { //must have some ext - continue; - } - if (strncmp(direntry->d_name, name, namelen) == 0) { - char *ext = direntry->d_name + namelen + 1; -#ifdef WITH_GDK_PIXBUF - if (strcmp(ext, "png") == 0 || - strcmp(ext, "xpm") == 0 || - strcmp(ext, "svg") == 0) { -#else - if (strcmp(ext, "png") == 0) { -#endif - free(current_file); - char *icon_path = malloc(strlen(path) + len + 2); - - strcpy(icon_path, path); - icon_path[strlen(path)] = '/'; - strcpy(icon_path + strlen(path) + 1, direntry->d_name); - current_file = icon_path; - min_size_diff = size_diff; - } - } - } - free(path); - closedir(icons); - } - free_flat_list(subdirs); - } - free_flat_list(dirs); - - return current_file; -} - -cairo_surface_t *find_icon(const char *name, int size) { - char *image_path = find_icon_file(name, size); - if (image_path == NULL) { - return NULL; - } - - cairo_surface_t *image = NULL; -#ifdef WITH_GDK_PIXBUF - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); - if (!pixbuf) { - sway_log(L_ERROR, "Failed to load icon image: %s", err->message); - } - image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - // TODO make svg work? cairo supports it. maybe remove gdk alltogether - image = cairo_image_surface_create_from_png(image_path); -#endif //WITH_GDK_PIXBUF - if (!image) { - sway_log(L_ERROR, "Could not read icon image"); - return NULL; - } - - free(image_path); - return image; -} diff --git a/swaybar/tray/sni.c b/swaybar/tray/sni.c deleted file mode 100644 index c9d00657..00000000 --- a/swaybar/tray/sni.c +++ /dev/null @@ -1,481 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include -#include -#include "swaybar/tray/dbus.h" -#include "swaybar/tray/sni.h" -#include "swaybar/tray/icon.h" -#include "swaybar/bar.h" -#include "client/cairo.h" -#include "log.h" - -// Not sure what this is but cairo needs it. -static const cairo_user_data_key_t cairo_user_data_key; - -struct sni_icon_ref *sni_icon_ref_create(struct StatusNotifierItem *item, - int height) { - struct sni_icon_ref *sni_ref = malloc(sizeof(struct sni_icon_ref)); - if (!sni_ref) { - return NULL; - } - sni_ref->icon = cairo_image_surface_scale(item->image, height, height); - sni_ref->ref = item; - - return sni_ref; -} - -void sni_icon_ref_free(struct sni_icon_ref *sni_ref) { - if (!sni_ref) { - return; - } - cairo_surface_destroy(sni_ref->icon); - free(sni_ref); -} - -/* Gets the pixmap of an icon */ -static void reply_icon(DBusPendingCall *pending, void *_data) { - struct StatusNotifierItem *item = _data; - - DBusMessage *reply = dbus_pending_call_steal_reply(pending); - - if (!reply) { - sway_log(L_ERROR, "Did not get reply"); - goto bail; - } - - int message_type = dbus_message_get_type(reply); - - if (message_type == DBUS_MESSAGE_TYPE_ERROR) { - char *msg; - - dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &msg, - DBUS_TYPE_INVALID); - - sway_log(L_ERROR, "Message is error: %s", msg); - goto bail; - } - - DBusMessageIter iter; - DBusMessageIter variant; /* v[a(iiay)] */ - DBusMessageIter array; /* a(iiay) */ - DBusMessageIter d_struct; /* (iiay) */ - DBusMessageIter icon; /* ay */ - - dbus_message_iter_init(reply, &iter); - - // Each if here checks the types above before recursing - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { - sway_log(L_ERROR, "Relpy type incorrect"); - sway_log(L_ERROR, "Should be \"v\", is \"%s\"", - dbus_message_iter_get_signature(&iter)); - goto bail; - } - dbus_message_iter_recurse(&iter, &variant); - - if (strcmp("a(iiay)", dbus_message_iter_get_signature(&variant)) != 0) { - sway_log(L_ERROR, "Relpy type incorrect"); - sway_log(L_ERROR, "Should be \"a(iiay)\", is \"%s\"", - dbus_message_iter_get_signature(&variant)); - goto bail; - } - - if (dbus_message_iter_get_element_count(&variant) == 0) { - // Can't recurse if there are no items - sway_log(L_INFO, "Item has no icon"); - goto bail; - } - dbus_message_iter_recurse(&variant, &array); - - dbus_message_iter_recurse(&array, &d_struct); - - int width; - dbus_message_iter_get_basic(&d_struct, &width); - dbus_message_iter_next(&d_struct); - - int height; - dbus_message_iter_get_basic(&d_struct, &height); - dbus_message_iter_next(&d_struct); - - int len = dbus_message_iter_get_element_count(&d_struct); - - if (!len) { - sway_log(L_ERROR, "No icon data"); - goto bail; - } - - // Also implies len % 4 == 0, useful below - if (len != width * height * 4) { - sway_log(L_ERROR, "Incorrect array size passed"); - goto bail; - } - - dbus_message_iter_recurse(&d_struct, &icon); - - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); - // FIXME support a variable stride - // (works on my machine though for all tested widths) - if (!sway_assert(stride == width * 4, "Stride must be equal to byte length")) { - goto bail; - } - - // Data is by reference, no need to free - uint8_t *message_data; - dbus_message_iter_get_fixed_array(&icon, &message_data, &len); - - uint8_t *image_data = malloc(stride * height); - if (!image_data) { - sway_log(L_ERROR, "Could not allocate memory for icon"); - goto bail; - } - - // Transform from network byte order to host byte order - // Assumptions are safe because the equality above - uint32_t *network = (uint32_t *) message_data; - uint32_t *host = (uint32_t *)image_data; - for (int i = 0; i < width * height; ++i) { - host[i] = ntohl(network[i]); - } - - cairo_surface_t *image = cairo_image_surface_create_for_data( - image_data, CAIRO_FORMAT_ARGB32, - width, height, stride); - - if (image) { - if (item->image) { - cairo_surface_destroy(item->image); - } - item->image = image; - // Free the image data on surface destruction - cairo_surface_set_user_data(image, - &cairo_user_data_key, - image_data, - free); - item->dirty = true; - dirty = true; - - dbus_message_unref(reply); - dbus_pending_call_unref(pending); - return; - } else { - sway_log(L_ERROR, "Could not create image surface"); - free(image_data); - } - -bail: - if (reply) { - dbus_message_unref(reply); - } - dbus_pending_call_unref(pending); - sway_log(L_ERROR, "Could not get icon from item"); - return; -} -static void send_icon_msg(struct StatusNotifierItem *item) { - DBusPendingCall *pending; - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - "org.freedesktop.DBus.Properties", - "Get"); - const char *iface; - if (item->kde_special_snowflake) { - iface = "org.kde.StatusNotifierItem"; - } else { - iface = "org.freedesktop.StatusNotifierItem"; - } - const char *prop = "IconPixmap"; - - dbus_message_append_args(message, - DBUS_TYPE_STRING, &iface, - DBUS_TYPE_STRING, &prop, - DBUS_TYPE_INVALID); - - bool status = - dbus_connection_send_with_reply(conn, message, &pending, -1); - - dbus_message_unref(message); - - if (!(pending || status)) { - sway_log(L_ERROR, "Could not get item icon"); - return; - } - - dbus_pending_call_set_notify(pending, reply_icon, item, NULL); -} - -/* Get an icon by its name */ -static void reply_icon_name(DBusPendingCall *pending, void *_data) { - struct StatusNotifierItem *item = _data; - - DBusMessage *reply = dbus_pending_call_steal_reply(pending); - - if (!reply) { - sway_log(L_INFO, "Got no icon name reply from item"); - goto bail; - } - - int message_type = dbus_message_get_type(reply); - - if (message_type == DBUS_MESSAGE_TYPE_ERROR) { - char *msg; - - dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &msg, - DBUS_TYPE_INVALID); - - sway_log(L_INFO, "Could not get icon name: %s", msg); - goto bail; - } - - DBusMessageIter iter; /* v[s] */ - DBusMessageIter variant; /* s */ - - dbus_message_iter_init(reply, &iter); - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { - sway_log(L_ERROR, "Relpy type incorrect"); - sway_log(L_ERROR, "Should be \"v\", is \"%s\"", - dbus_message_iter_get_signature(&iter)); - goto bail; - } - dbus_message_iter_recurse(&iter, &variant); - - - if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_STRING) { - sway_log(L_ERROR, "Relpy type incorrect"); - sway_log(L_ERROR, "Should be \"s\", is \"%s\"", - dbus_message_iter_get_signature(&iter)); - goto bail; - } - - char *icon_name; - dbus_message_iter_get_basic(&variant, &icon_name); - - cairo_surface_t *image = find_icon(icon_name, 256); - - if (image) { - sway_log(L_DEBUG, "Icon for %s found with size %d", icon_name, - cairo_image_surface_get_width(image)); - if (item->image) { - cairo_surface_destroy(item->image); - } - item->image = image; - item->dirty = true; - dirty = true; - - dbus_message_unref(reply); - dbus_pending_call_unref(pending); - return; - } - -bail: - if (reply) { - dbus_message_unref(reply); - } - dbus_pending_call_unref(pending); - // Now try the pixmap - send_icon_msg(item); - return; -} -static void send_icon_name_msg(struct StatusNotifierItem *item) { - DBusPendingCall *pending; - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - "org.freedesktop.DBus.Properties", - "Get"); - const char *iface; - if (item->kde_special_snowflake) { - iface = "org.kde.StatusNotifierItem"; - } else { - iface = "org.freedesktop.StatusNotifierItem"; - } - const char *prop = "IconName"; - - dbus_message_append_args(message, - DBUS_TYPE_STRING, &iface, - DBUS_TYPE_STRING, &prop, - DBUS_TYPE_INVALID); - - bool status = - dbus_connection_send_with_reply(conn, message, &pending, -1); - - dbus_message_unref(message); - - if (!(pending || status)) { - sway_log(L_ERROR, "Could not get item icon name"); - return; - } - - dbus_pending_call_set_notify(pending, reply_icon_name, item, NULL); -} - -void get_icon(struct StatusNotifierItem *item) { - send_icon_name_msg(item); -} - -void sni_activate(struct StatusNotifierItem *item, uint32_t x, uint32_t y) { - const char *iface = - (item->kde_special_snowflake ? "org.kde.StatusNotifierItem" - : "org.freedesktop.StatusNotifierItem"); - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - iface, - "Activate"); - - dbus_message_append_args(message, - DBUS_TYPE_INT32, &x, - DBUS_TYPE_INT32, &y, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, message, NULL); - - dbus_message_unref(message); -} - -void sni_context_menu(struct StatusNotifierItem *item, uint32_t x, uint32_t y) { - const char *iface = - (item->kde_special_snowflake ? "org.kde.StatusNotifierItem" - : "org.freedesktop.StatusNotifierItem"); - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - iface, - "ContextMenu"); - - dbus_message_append_args(message, - DBUS_TYPE_INT32, &x, - DBUS_TYPE_INT32, &y, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, message, NULL); - - dbus_message_unref(message); -} -void sni_secondary(struct StatusNotifierItem *item, uint32_t x, uint32_t y) { - const char *iface = - (item->kde_special_snowflake ? "org.kde.StatusNotifierItem" - : "org.freedesktop.StatusNotifierItem"); - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - iface, - "SecondaryActivate"); - - dbus_message_append_args(message, - DBUS_TYPE_INT32, &x, - DBUS_TYPE_INT32, &y, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, message, NULL); - - dbus_message_unref(message); -} - -static void get_unique_name(struct StatusNotifierItem *item) { - // I think that we're fine being sync here becaues the message is - // directly to the message bus. Could be async though. - DBusMessage *message = dbus_message_new_method_call( - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "GetNameOwner"); - - dbus_message_append_args(message, - DBUS_TYPE_STRING, &item->name, - DBUS_TYPE_INVALID); - - DBusMessage *reply = dbus_connection_send_with_reply_and_block( - conn, message, -1, NULL); - - dbus_message_unref(message); - - if (!reply) { - sway_log(L_ERROR, "Could not get unique name for item: %s", - item->name); - return; - } - - char *unique_name; - if (!dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &unique_name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error parsing method args"); - } else { - if (item->unique_name) { - free(item->unique_name); - } - item->unique_name = strdup(unique_name); - } - - dbus_message_unref(reply); -} - -struct StatusNotifierItem *sni_create(const char *name) { - // Make sure `name` is well formed - if (!dbus_validate_bus_name(name, NULL)) { - sway_log(L_INFO, "Name (%s) is not a bus name. We cannot create an item.", name); - return NULL; - } - - struct StatusNotifierItem *item = malloc(sizeof(struct StatusNotifierItem)); - item->name = strdup(name); - item->unique_name = NULL; - item->image = NULL; - item->dirty = false; - - // If it doesn't use this name then assume that it uses the KDE spec - // This is because xembed-sni-proxy uses neither "org.freedesktop" nor - // "org.kde" and just gives us the items "unique name" - // - // We could use this to our advantage and fill out the "unique name" - // field with the given name if it is neither freedesktop or kde, but - // that's makes us rely on KDE hackyness which is bad practice - const char freedesktop_name[] = "org.freedesktop"; - if (strncmp(name, freedesktop_name, sizeof(freedesktop_name) - 1) != 0) { - item->kde_special_snowflake = true; - } else { - item->kde_special_snowflake = false; - } - - get_icon(item); - - get_unique_name(item); - - return item; -} -/* Return 0 if `item` has a name of `str` */ -int sni_str_cmp(const void *_item, const void *_str) { - const struct StatusNotifierItem *item = _item; - const char *str = _str; - - return strcmp(item->name, str); -} -/* Returns 0 if `item` has a unique name of `str` */ -int sni_uniq_cmp(const void *_item, const void *_str) { - const struct StatusNotifierItem *item = _item; - const char *str = _str; - - if (!item->unique_name) { - return false; - } - return strcmp(item->unique_name, str); -} -void sni_free(struct StatusNotifierItem *item) { - if (!item) { - return; - } - free(item->name); - if (item->unique_name) { - free(item->unique_name); - } - if (item->image) { - cairo_surface_destroy(item->image); - } - free(item); -} diff --git a/swaybar/tray/sni_watcher.c b/swaybar/tray/sni_watcher.c deleted file mode 100644 index 86453e70..00000000 --- a/swaybar/tray/sni_watcher.c +++ /dev/null @@ -1,497 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include "swaybar/tray/dbus.h" -#include "list.h" -#include "log.h" - -static list_t *items = NULL; -static list_t *hosts = NULL; - -/** - * Describes the function of the StatusNotifierWatcher - * See https://freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierWatcher/ - * - * We also implement KDE's special snowflake protocol, it's like this but with - * all occurrences 'freedesktop' replaced with 'kde'. There is no KDE introspect. - */ -static const char *interface_xml = - "" - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; - -static void host_registered_signal(DBusConnection *connection) { - // Send one signal for each protocol - DBusMessage *signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierHostRegistered"); - - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); - - - signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.kde.StatusNotifierWatcher", - "StatusNotifierHostRegistered"); - - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); -} -static void item_registered_signal(DBusConnection *connection, const char *name) { - DBusMessage *signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierItemRegistered"); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); - - signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.kde.StatusNotifierWatcher", - "StatusNotifierItemRegistered"); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); -} -static void item_unregistered_signal(DBusConnection *connection, const char *name) { - DBusMessage *signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierItemUnregistered"); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); - - signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.kde.StatusNotifierWatcher", - "StatusNotifierItemUnregistered"); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); -} - -static void respond_to_introspect(DBusConnection *connection, DBusMessage *request) { - DBusMessage *reply; - - reply = dbus_message_new_method_return(request); - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &interface_xml, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); -} - -static void register_item(DBusConnection *connection, DBusMessage *message) { - DBusError error; - char *name; - - dbus_error_init(&error); - if (!dbus_message_get_args(message, &error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error parsing method args: %s\n", error.message); - } - - sway_log(L_INFO, "RegisterStatusNotifierItem called with \"%s\"\n", name); - - // Don't add duplicate or not real item - if (!dbus_validate_bus_name(name, NULL)) { - sway_log(L_INFO, "This item is not valid, we cannot keep track of it."); - return; - } - - if (list_seq_find(items, (int (*)(const void *, const void *))strcmp, name) != -1) { - return; - } - if (!dbus_bus_name_has_owner(connection, name, &error)) { - return; - } - - list_add(items, strdup(name)); - item_registered_signal(connection, name); - - // It's silly, but xembedsniproxy wants a reply for this function - DBusMessage *reply = dbus_message_new_method_return(message); - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); -} - -static void register_host(DBusConnection *connection, DBusMessage *message) { - DBusError error; - char *name; - - dbus_error_init(&error); - if (!dbus_message_get_args(message, &error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error parsing method args: %s\n", error.message); - } - - sway_log(L_INFO, "RegisterStatusNotifierHost called with \"%s\"\n", name); - - // Don't add duplicate or not real host - if (!dbus_validate_bus_name(name, NULL)) { - sway_log(L_INFO, "This item is not valid, we cannot keep track of it."); - return; - } - - - if (list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name) != -1) { - return; - } - if (!dbus_bus_name_has_owner(connection, name, &error)) { - return; - } - - list_add(hosts, strdup(name)); - host_registered_signal(connection); -} - -static void get_property(DBusConnection *connection, DBusMessage *message) { - DBusError error; - char *interface; - char *property; - - dbus_error_init(&error); - if (!dbus_message_get_args(message, &error, - DBUS_TYPE_STRING, &interface, - DBUS_TYPE_STRING, &property, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error parsing prop args: %s\n", error.message); - return; - } - - if (strcmp(property, "RegisteredStatusNotifierItems") == 0) { - sway_log(L_INFO, "Replying with items\n"); - DBusMessage *reply; - reply = dbus_message_new_method_return(message); - DBusMessageIter iter; - DBusMessageIter sub; - DBusMessageIter subsub; - - dbus_message_iter_init_append(reply, &iter); - - dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, - "as", &sub); - dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, - "s", &subsub); - - for (int i = 0; i < items->length; ++i) { - dbus_message_iter_append_basic(&subsub, - DBUS_TYPE_STRING, &items->items[i]); - } - - dbus_message_iter_close_container(&sub, &subsub); - dbus_message_iter_close_container(&iter, &sub); - - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } else if (strcmp(property, "IsStatusNotifierHostRegistered") == 0) { - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter sub; - int registered = (hosts == NULL || hosts->length == 0) ? 0 : 1; - - reply = dbus_message_new_method_return(message); - - dbus_message_iter_init_append(reply, &iter); - - dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, - "b", &sub); - dbus_message_iter_append_basic(&sub, - DBUS_TYPE_BOOLEAN, ®istered); - - dbus_message_iter_close_container(&iter, &sub); - - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } else if (strcmp(property, "ProtocolVersion") == 0) { - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter sub; - const int version = 0; - - reply = dbus_message_new_method_return(message); - - dbus_message_iter_init_append(reply, &iter); - - dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, - "i", &sub); - dbus_message_iter_append_basic(&sub, - DBUS_TYPE_INT32, &version); - - dbus_message_iter_close_container(&iter, &sub); - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } -} - -static void set_property(DBusConnection *connection, DBusMessage *message) { - // All properties are read only and we don't allow new properties - return; -} - -static void get_all(DBusConnection *connection, DBusMessage *message) { - DBusMessage *reply; - reply = dbus_message_new_method_return(message); - DBusMessageIter iter; /* a{v} */ - DBusMessageIter arr; - DBusMessageIter dict; - DBusMessageIter sub; - DBusMessageIter subsub; - int registered = (hosts == NULL || hosts->length == 0) ? 0 : 1; - const int version = 0; - const char *prop; - - // Could clean this up with a function for each prop - dbus_message_iter_init_append(reply, &iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - "{sv}", &arr); - - prop = "RegisteredStatusNotifierItems"; - dbus_message_iter_open_container(&arr, DBUS_TYPE_DICT_ENTRY, - NULL, &dict); - dbus_message_iter_append_basic(&dict, - DBUS_TYPE_STRING, &prop); - dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, - "as", &sub); - dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, - "s", &subsub); - for (int i = 0; i < items->length; ++i) { - dbus_message_iter_append_basic(&subsub, - DBUS_TYPE_STRING, &items->items[i]); - } - dbus_message_iter_close_container(&sub, &subsub); - dbus_message_iter_close_container(&dict, &sub); - dbus_message_iter_close_container(&arr, &dict); - - prop = "IsStatusNotifierHostRegistered"; - dbus_message_iter_open_container(&arr, DBUS_TYPE_DICT_ENTRY, - NULL, &dict); - dbus_message_iter_append_basic(&dict, - DBUS_TYPE_STRING, &prop); - dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, - "b", &sub); - dbus_message_iter_append_basic(&sub, - DBUS_TYPE_BOOLEAN, ®istered); - dbus_message_iter_close_container(&dict, &sub); - dbus_message_iter_close_container(&arr, &dict); - - prop = "ProtocolVersion"; - dbus_message_iter_open_container(&arr, DBUS_TYPE_DICT_ENTRY, - NULL, &dict); - dbus_message_iter_append_basic(&dict, - DBUS_TYPE_STRING, &prop); - dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, - "i", &sub); - dbus_message_iter_append_basic(&sub, - DBUS_TYPE_INT32, &version); - dbus_message_iter_close_container(&dict, &sub); - dbus_message_iter_close_container(&arr, &dict); - - dbus_message_iter_close_container(&iter, &arr); - - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); -} - -static DBusHandlerResult message_handler(DBusConnection *connection, - DBusMessage *message, void *data) { - const char *interface_name = dbus_message_get_interface(message); - const char *member_name = dbus_message_get_member(message); - - // In order of the xml above - if (strcmp(interface_name, "org.freedesktop.DBus.Introspectable") == 0 && - strcmp(member_name, "Introspect") == 0) { - // We don't have an introspect for KDE - respond_to_introspect(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (strcmp(interface_name, "org.freedesktop.DBus.Properties") == 0) { - if (strcmp(member_name, "Get") == 0) { - get_property(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (strcmp(member_name, "Set") == 0) { - set_property(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (strcmp(member_name, "GetAll") == 0) { - get_all(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - } else if (strcmp(interface_name, "org.freedesktop.StatusNotifierWatcher") == 0 || - strcmp(interface_name, "org.kde.StatusNotifierWatcher") == 0) { - if (strcmp(member_name, "RegisterStatusNotifierItem") == 0) { - register_item(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (strcmp(member_name, "RegisterStatusNotifierHost") == 0) { - register_host(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult signal_handler(DBusConnection *connection, - DBusMessage *message, void *_data) { - if (dbus_message_is_signal(message, "org.freedesktop.DBus", "NameOwnerChanged")) { - // Only eat the message if it is name that we are watching - const char *name; - const char *old_owner; - const char *new_owner; - int index; - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &old_owner, - DBUS_TYPE_STRING, &new_owner, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error getting LostName args"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - if (strcmp(new_owner, "") != 0) { - // Name is not lost - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - if ((index = list_seq_find(items, (int (*)(const void *, const void *))strcmp, name)) != -1) { - sway_log(L_INFO, "Status Notifier Item lost %s", name); - free(items->items[index]); - list_del(items, index); - item_unregistered_signal(connection, name); - - return DBUS_HANDLER_RESULT_HANDLED; - } - if ((index = list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name)) != -1) { - sway_log(L_INFO, "Status Notifier Host lost %s", name); - free(hosts->items[index]); - list_del(hosts, index); - - return DBUS_HANDLER_RESULT_HANDLED; - } - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static const DBusObjectPathVTable vtable = { - .message_function = message_handler, - .unregister_function = NULL, -}; - -int init_sni_watcher() { - DBusError error; - dbus_error_init(&error); - if (!conn) { - sway_log(L_ERROR, "Connection is null, cannot initiate StatusNotifierWatcher"); - return -1; - } - - items = create_list(); - hosts = create_list(); - - int status = dbus_bus_request_name(conn, "org.freedesktop.StatusNotifierWatcher", - DBUS_NAME_FLAG_REPLACE_EXISTING, - &error); - if (status == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - sway_log(L_DEBUG, "Got watcher name"); - } else if (status == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) { - sway_log(L_INFO, "Could not get watcher name, it may start later"); - } - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus err getting watcher name: %s\n", error.message); - return -1; - } - - status = dbus_bus_request_name(conn, "org.kde.StatusNotifierWatcher", - DBUS_NAME_FLAG_REPLACE_EXISTING, - &error); - if (status == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - sway_log(L_DEBUG, "Got kde watcher name"); - } else if (status == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) { - sway_log(L_INFO, "Could not get kde watcher name, it may start later"); - } - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus err getting kde watcher name: %s\n", error.message); - return -1; - } - - dbus_connection_try_register_object_path(conn, - "/StatusNotifierWatcher", - &vtable, NULL, &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err: %s\n", error.message); - return -1; - } - - dbus_bus_add_match(conn, - "type='signal',\ - sender='org.freedesktop.DBus',\ - interface='org.freedesktop.DBus',\ - member='NameOwnerChanged'", - &error); - - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "DBus error getting match args: %s", error.message); - } - - dbus_connection_add_filter(conn, signal_handler, NULL, NULL); - return 0; -} diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c deleted file mode 100644 index 91c3af06..00000000 --- a/swaybar/tray/tray.c +++ /dev/null @@ -1,398 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include "swaybar/bar.h" -#include "swaybar/tray/tray.h" -#include "swaybar/tray/dbus.h" -#include "swaybar/tray/sni.h" -#include "swaybar/tray/sni_watcher.h" -#include "swaybar/bar.h" -#include "swaybar/config.h" -#include "list.h" -#include "log.h" - -struct tray *tray; - -static void register_host(char *name) { - DBusMessage *message; - - message = dbus_message_new_method_call( - "org.freedesktop.StatusNotifierWatcher", - "/StatusNotifierWatcher", - "org.freedesktop.StatusNotifierWatcher", - "RegisterStatusNotifierHost"); - if (!message) { - sway_log(L_ERROR, "Cannot allocate dbus method call"); - return; - } - - dbus_message_append_args(message, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, message, NULL); - - dbus_message_unref(message); -} - -static void get_items_reply(DBusPendingCall *pending, void *_data) { - DBusMessage *reply = dbus_pending_call_steal_reply(pending); - - if (!reply) { - sway_log(L_ERROR, "Got no items reply from sni watcher"); - goto bail; - } - - int message_type = dbus_message_get_type(reply); - - if (message_type == DBUS_MESSAGE_TYPE_ERROR) { - char *msg; - - dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &msg, - DBUS_TYPE_INVALID); - - sway_log(L_ERROR, "Message is error: %s", msg); - goto bail; - } - - DBusMessageIter iter; - DBusMessageIter variant; - DBusMessageIter array; - - dbus_message_iter_init(reply, &iter); - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { - sway_log(L_ERROR, "Replyed with wrong type, not v(as)"); - goto bail; - } - dbus_message_iter_recurse(&iter, &variant); - if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type(&variant) != DBUS_TYPE_STRING) { - sway_log(L_ERROR, "Replyed with wrong type, not v(as)"); - goto bail; - } - - // Clear list - list_foreach(tray->items, (void (*)(void *))sni_free); - list_free(tray->items); - tray->items = create_list(); - - // O(n) function, could be faster dynamically reading values - int len = dbus_message_iter_get_element_count(&variant); - - dbus_message_iter_recurse(&variant, &array); - for (int i = 0; i < len; i++) { - const char *name; - dbus_message_iter_get_basic(&array, &name); - - struct StatusNotifierItem *item = sni_create(name); - - if (item) { - sway_log(L_DEBUG, "Item registered with host: %s", name); - list_add(tray->items, item); - dirty = true; - } - } - -bail: - dbus_message_unref(reply); - dbus_pending_call_unref(pending); - return; -} -static void get_items() { - DBusPendingCall *pending; - DBusMessage *message = dbus_message_new_method_call( - "org.freedesktop.StatusNotifierWatcher", - "/StatusNotifierWatcher", - "org.freedesktop.DBus.Properties", - "Get"); - - const char *iface = "org.freedesktop.StatusNotifierWatcher"; - const char *prop = "RegisteredStatusNotifierItems"; - dbus_message_append_args(message, - DBUS_TYPE_STRING, &iface, - DBUS_TYPE_STRING, &prop, - DBUS_TYPE_INVALID); - - bool status = - dbus_connection_send_with_reply(conn, message, &pending, -1); - dbus_message_unref(message); - - if (!(pending || status)) { - sway_log(L_ERROR, "Could not get items"); - return; - } - - dbus_pending_call_set_notify(pending, get_items_reply, NULL, NULL); -} - -static DBusHandlerResult signal_handler(DBusConnection *connection, - DBusMessage *message, void *_data) { - if (dbus_message_is_signal(message, "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierItemRegistered")) { - const char *name; - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error getting StatusNotifierItemRegistered args"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - if (list_seq_find(tray->items, sni_str_cmp, name) == -1) { - struct StatusNotifierItem *item = sni_create(name); - - if (item) { - list_add(tray->items, item); - dirty = true; - } - } - - return DBUS_HANDLER_RESULT_HANDLED; - } else if (dbus_message_is_signal(message, "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierItemUnregistered")) { - const char *name; - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error getting StatusNotifierItemUnregistered args"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - int index; - if ((index = list_seq_find(tray->items, sni_str_cmp, name)) != -1) { - sni_free(tray->items->items[index]); - list_del(tray->items, index); - dirty = true; - } else { - // If it's not in our list, then our list is incorrect. - // Fetch all items again - sway_log(L_INFO, "Host item list incorrect, refreshing"); - get_items(); - } - - return DBUS_HANDLER_RESULT_HANDLED; - } else if (dbus_message_is_signal(message, "org.freedesktop.StatusNotifierItem", - "NewIcon") || dbus_message_is_signal(message, - "org.kde.StatusNotifierItem", "NewIcon")) { - const char *name; - int index; - struct StatusNotifierItem *item; - - name = dbus_message_get_sender(message); - if ((index = list_seq_find(tray->items, sni_uniq_cmp, name)) != -1) { - item = tray->items->items[index]; - sway_log(L_INFO, "NewIcon signal from item %s", item->name); - get_icon(item); - } - - return DBUS_HANDLER_RESULT_HANDLED; - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static int init_host() { - tray = (struct tray *)malloc(sizeof(tray)); - - tray->items = create_list(); - - DBusError error; - dbus_error_init(&error); - char *name = NULL; - if (!conn) { - sway_log(L_ERROR, "Connection is null, cannot init SNI host"); - goto err; - } - name = calloc(sizeof(char), 256); - - if (!name) { - sway_log(L_ERROR, "Cannot allocate name"); - goto err; - } - - pid_t pid = getpid(); - if (snprintf(name, 256, "org.freedesktop.StatusNotifierHost-%d", pid) - >= 256) { - sway_log(L_ERROR, "Cannot get host name because string is too short." - "This should not happen"); - goto err; - } - - // We want to be the sole owner of this name - if (dbus_bus_request_name(conn, name, DBUS_NAME_FLAG_DO_NOT_QUEUE, - &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - sway_log(L_ERROR, "Cannot get host name and start the tray"); - goto err; - } - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "Dbus err getting host name: %s\n", error.message); - goto err; - } - sway_log(L_DEBUG, "Got host name"); - - register_host(name); - - get_items(); - - // Perhaps use addmatch helper functions like wlc does? - dbus_bus_add_match(conn, - "type='signal',\ - sender='org.freedesktop.StatusNotifierWatcher',\ - member='StatusNotifierItemRegistered'", - &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err: %s", error.message); - goto err; - } - dbus_bus_add_match(conn, - "type='signal',\ - sender='org.freedesktop.StatusNotifierWatcher',\ - member='StatusNotifierItemUnregistered'", - &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err: %s", error.message); - return -1; - } - - // SNI matches - dbus_bus_add_match(conn, - "type='signal',\ - interface='org.freedesktop.StatusNotifierItem',\ - member='NewIcon'", - &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err %s", error.message); - goto err; - } - dbus_bus_add_match(conn, - "type='signal',\ - interface='org.kde.StatusNotifierItem',\ - member='NewIcon'", - &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err %s", error.message); - goto err; - } - - dbus_connection_add_filter(conn, signal_handler, NULL, NULL); - - free(name); - return 0; - -err: - // TODO better handle errors - free(name); - return -1; -} - -void tray_mouse_event(struct output *output, int x, int y, - uint32_t button, uint32_t state) { - - struct window *window = output->window; - uint32_t tray_padding = swaybar.config->tray_padding; - int tray_width = window->width * window->scale; - - for (int i = 0; i < output->items->length; ++i) { - struct sni_icon_ref *item = - output->items->items[i]; - int icon_width = cairo_image_surface_get_width(item->icon); - - tray_width -= tray_padding; - if (x <= tray_width && x >= tray_width - icon_width) { - if (button == swaybar.config->activate_button) { - sni_activate(item->ref, x, y); - } else if (button == swaybar.config->context_button) { - sni_context_menu(item->ref, x, y); - } else if (button == swaybar.config->secondary_button) { - sni_secondary(item->ref, x, y); - } - break; - } - tray_width -= icon_width; - } -} - -uint32_t tray_render(struct output *output, struct config *config) { - struct window *window = output->window; - cairo_t *cairo = window->cairo; - - // Tray icons - uint32_t tray_padding = config->tray_padding; - uint32_t tray_width = window->width * window->scale; - const int item_size = (window->height * window->scale) - (2 * tray_padding); - - if (item_size < 0) { - // Can't render items if the padding is too large - return tray_width; - } - - if (config->tray_output && strcmp(config->tray_output, output->name) != 0) { - return tray_width; - } - - for (int i = 0; i < tray->items->length; ++i) { - struct StatusNotifierItem *item = - tray->items->items[i]; - if (!item->image) { - continue; - } - - struct sni_icon_ref *render_item = NULL; - int j; - for (j = i; j < output->items->length; ++j) { - struct sni_icon_ref *ref = - output->items->items[j]; - if (ref->ref == item) { - render_item = ref; - break; - } else { - sni_icon_ref_free(ref); - list_del(output->items, j); - } - } - - if (!render_item) { - render_item = sni_icon_ref_create(item, item_size); - list_add(output->items, render_item); - } else if (item->dirty) { - // item needs re-render - sni_icon_ref_free(render_item); - output->items->items[j] = render_item = - sni_icon_ref_create(item, item_size); - } - - tray_width -= tray_padding; - tray_width -= item_size; - - cairo_operator_t op = cairo_get_operator(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding); - cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size); - cairo_fill(cairo); - cairo_set_operator(cairo, op); - - item->dirty = false; - } - - - if (tray_width != window->width * window->scale) { - tray_width -= tray_padding; - } - - return tray_width; -} - -void init_tray(struct bar *bar) { - if (!bar->config->tray_output || strcmp(bar->config->tray_output, "none") != 0) { - /* Connect to the D-Bus */ - dbus_init(); - - /* Start the SNI watcher */ - init_sni_watcher(); - - /* Start the SNI host */ - init_host(); - } -} -- cgit v1.2.3 From 6836074fed83255438960fdc9597532d8bcae4bd Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 16:51:36 -0400 Subject: Implement enough IPC for swaybar to work --- include/sway/config.h | 11 ---- include/sway/ipc-json.h | 1 + include/sway/ipc-server.h | 1 + sway/config.c | 6 -- sway/desktop/layer_shell.c | 10 +--- sway/input/seat.c | 26 +++++++-- sway/ipc-json.c | 134 +++++++++++++++++++++++++++++++++++++++++++++ sway/ipc-server.c | 93 ++++++++++++++++++++++++++++++- 8 files changed, 251 insertions(+), 31 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 8c9e04de..f9ab6778 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -158,17 +158,6 @@ struct bar_config { char *swaybar_command; char *font; int height; // -1 not defined - -#ifdef ENABLE_TRAY - // Tray - char *tray_output; - char *icon_theme; - uint32_t tray_padding; - uint32_t activate_button; - uint32_t context_button; - uint32_t secondary_button; -#endif - bool workspace_buttons; bool wrap_scroll; char *separator_symbol; diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index eef5a018..19c5b5bc 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -9,5 +9,6 @@ json_object *ipc_json_get_version(); json_object *ipc_json_describe_container(swayc_t *c); json_object *ipc_json_describe_container_recursive(swayc_t *c); json_object *ipc_json_describe_input(struct sway_input_device *device); +json_object *ipc_json_describe_bar_config(struct bar_config *bar); #endif diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index bcf1c433..6b7404e5 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -10,6 +10,7 @@ void ipc_init(struct sway_server *server); void ipc_terminate(void); struct sockaddr_un *ipc_user_sockaddr(void); +void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change); void ipc_event_window(swayc_t *window, const char *change); #endif diff --git a/sway/config.c b/sway/config.c index 213e7680..0422fdd9 100644 --- a/sway/config.c +++ b/sway/config.c @@ -403,12 +403,6 @@ bool load_main_config(const char *file, bool is_active) { free_config(old_config); } config->reading = false; - - if (success) { - // TODO: bar - //update_active_bar_modifiers(); - } - return success; } diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 31679fb2..187c8664 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -156,7 +156,6 @@ void arrange_layers(struct sway_output *output) { struct wlr_box usable_area = { 0 }; wlr_output_effective_resolution(output->wlr_output, &usable_area.width, &usable_area.height); - struct wlr_box usable_area_before = output->usable_area; // Arrange exclusive surfaces from top->bottom arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], @@ -169,11 +168,7 @@ void arrange_layers(struct sway_output *output) { &usable_area, true); memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); - if (memcmp(&usable_area_before, - &usable_area, sizeof(struct wlr_box)) != 0) { - wlr_log(L_DEBUG, "arrange"); - arrange_windows(output->swayc, -1, -1); - } + arrange_windows(output->swayc, -1, -1); // Arrange non-exlusive surfaces from top->bottom usable_area.x = usable_area.y = 0; @@ -221,6 +216,7 @@ static void unmap(struct wlr_layer_surface *layer_surface) { static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_layer_surface *sway_layer = wl_container_of( listener, sway_layer, destroy); + wlr_log(L_DEBUG, "layer surface removed"); if (sway_layer->layer_surface->mapped) { unmap(sway_layer->layer_surface); } @@ -233,8 +229,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&sway_layer->output_destroy.link); } struct sway_output *output = sway_layer->layer_surface->output->data; - arrange_layers(output); free(sway_layer); + arrange_layers(output); } static void handle_map(struct wl_listener *listener, void *data) { diff --git a/sway/input/seat.c b/sway/input/seat.c index 648e7914..81bef7bd 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -6,6 +6,7 @@ #include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" +#include "sway/ipc-server.h" #include "sway/output.h" #include "sway/view.h" #include "log.h" @@ -309,18 +310,31 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { if (container->type == C_VIEW) { struct sway_view *view = container->sway_view; view_set_activated(view, true); - struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); + struct wlr_keyboard *keyboard = + wlr_seat_get_keyboard(seat->wlr_seat); if (keyboard) { - wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, - keyboard->keycodes, keyboard->num_keycodes, - &keyboard->modifiers); + wlr_seat_keyboard_notify_enter(seat->wlr_seat, + view->surface, keyboard->keycodes, + keyboard->num_keycodes, &keyboard->modifiers); } else { - wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, - NULL, 0, NULL); + wlr_seat_keyboard_notify_enter( + seat->wlr_seat, view->surface, NULL, 0, NULL); } } } + if (last_focus) { + swayc_t *last_ws = last_focus; + if (last_ws && last_ws->type != C_WORKSPACE) { + last_ws = swayc_parent_by_type( + last_focus, C_WORKSPACE); + } + if (last_ws) { + wlr_log(L_DEBUG, "sending workspace event"); + ipc_event_workspace(last_ws, container, "focus"); + } + } + if (last_focus && last_focus->type == C_VIEW && !sway_input_manager_has_focus(seat->input, last_focus)) { struct sway_view *view = last_focus->sway_view; diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 977f1ecb..24e41581 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -9,6 +9,7 @@ #include "sway/input/seat.h" #include #include +#include "wlr-layer-shell-unstable-v1-protocol.h" json_object *ipc_json_get_version() { int major = 0, minor = 0, patch = 0; @@ -198,3 +199,136 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { return object; } + +json_object *ipc_json_describe_bar_config(struct bar_config *bar) { + if (!sway_assert(bar, "Bar must not be NULL")) { + return NULL; + } + + json_object *json = json_object_new_object(); + json_object_object_add(json, "id", json_object_new_string(bar->id)); + json_object_object_add(json, "mode", json_object_new_string(bar->mode)); + json_object_object_add(json, "hidden_state", + json_object_new_string(bar->hidden_state)); + json_object_object_add(json, "position", + json_object_new_string(bar->position)); + json_object_object_add(json, "status_command", + json_object_new_string(bar->status_command)); + json_object_object_add(json, "font", + json_object_new_string((bar->font) ? bar->font : config->font)); + if (bar->separator_symbol) { + json_object_object_add(json, "separator_symbol", + json_object_new_string(bar->separator_symbol)); + } + json_object_object_add(json, "bar_height", + json_object_new_int(bar->height)); + json_object_object_add(json, "wrap_scroll", + json_object_new_boolean(bar->wrap_scroll)); + json_object_object_add(json, "workspace_buttons", + json_object_new_boolean(bar->workspace_buttons)); + json_object_object_add(json, "strip_workspace_numbers", + json_object_new_boolean(bar->strip_workspace_numbers)); + json_object_object_add(json, "binding_mode_indicator", + json_object_new_boolean(bar->binding_mode_indicator)); + json_object_object_add(json, "verbose", + json_object_new_boolean(bar->verbose)); + json_object_object_add(json, "pango_markup", + json_object_new_boolean(bar->pango_markup)); + + json_object *colors = json_object_new_object(); + json_object_object_add(colors, "background", + json_object_new_string(bar->colors.background)); + json_object_object_add(colors, "statusline", + json_object_new_string(bar->colors.statusline)); + json_object_object_add(colors, "separator", + json_object_new_string(bar->colors.separator)); + + if (bar->colors.focused_background) { + json_object_object_add(colors, "focused_background", + json_object_new_string(bar->colors.focused_background)); + } else { + json_object_object_add(colors, "focused_background", + json_object_new_string(bar->colors.background)); + } + + if (bar->colors.focused_statusline) { + json_object_object_add(colors, "focused_statusline", + json_object_new_string(bar->colors.focused_statusline)); + } else { + json_object_object_add(colors, "focused_statusline", + json_object_new_string(bar->colors.statusline)); + } + + if (bar->colors.focused_separator) { + json_object_object_add(colors, "focused_separator", + json_object_new_string(bar->colors.focused_separator)); + } else { + json_object_object_add(colors, "focused_separator", + json_object_new_string(bar->colors.separator)); + } + + json_object_object_add(colors, "focused_workspace_border", + json_object_new_string(bar->colors.focused_workspace_border)); + json_object_object_add(colors, "focused_workspace_bg", + json_object_new_string(bar->colors.focused_workspace_bg)); + json_object_object_add(colors, "focused_workspace_text", + json_object_new_string(bar->colors.focused_workspace_text)); + + json_object_object_add(colors, "inactive_workspace_border", + json_object_new_string(bar->colors.inactive_workspace_border)); + json_object_object_add(colors, "inactive_workspace_bg", + json_object_new_string(bar->colors.inactive_workspace_bg)); + json_object_object_add(colors, "inactive_workspace_text", + json_object_new_string(bar->colors.inactive_workspace_text)); + + json_object_object_add(colors, "active_workspace_border", + json_object_new_string(bar->colors.active_workspace_border)); + json_object_object_add(colors, "active_workspace_bg", + json_object_new_string(bar->colors.active_workspace_bg)); + json_object_object_add(colors, "active_workspace_text", + json_object_new_string(bar->colors.active_workspace_text)); + + json_object_object_add(colors, "urgent_workspace_border", + json_object_new_string(bar->colors.urgent_workspace_border)); + json_object_object_add(colors, "urgent_workspace_bg", + json_object_new_string(bar->colors.urgent_workspace_bg)); + json_object_object_add(colors, "urgent_workspace_text", + json_object_new_string(bar->colors.urgent_workspace_text)); + + if (bar->colors.binding_mode_border) { + json_object_object_add(colors, "binding_mode_border", + json_object_new_string(bar->colors.binding_mode_border)); + } else { + json_object_object_add(colors, "binding_mode_border", + json_object_new_string(bar->colors.urgent_workspace_border)); + } + + if (bar->colors.binding_mode_bg) { + json_object_object_add(colors, "binding_mode_bg", + json_object_new_string(bar->colors.binding_mode_bg)); + } else { + json_object_object_add(colors, "binding_mode_bg", + json_object_new_string(bar->colors.urgent_workspace_bg)); + } + + if (bar->colors.binding_mode_text) { + json_object_object_add(colors, "binding_mode_text", + json_object_new_string(bar->colors.binding_mode_text)); + } else { + json_object_object_add(colors, "binding_mode_text", + json_object_new_string(bar->colors.urgent_workspace_text)); + } + + json_object_object_add(json, "colors", colors); + + // Add outputs if defined + if (bar->outputs && bar->outputs->length > 0) { + json_object *outputs = json_object_new_array(); + for (int i = 0; i < bar->outputs->length; ++i) { + const char *name = bar->outputs->items[i]; + json_object_array_add(outputs, json_object_new_string(name)); + } + json_object_object_add(json, "outputs", outputs); + } + return json; +} diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 156de380..408ed432 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -21,6 +21,7 @@ #include "sway/ipc-server.h" #include "sway/server.h" #include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "list.h" #include "log.h" @@ -279,6 +280,31 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) } } +void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { + wlr_log(L_DEBUG, "Sending workspace::%s event", change); + json_object *obj = json_object_new_object(); + json_object_object_add(obj, "change", json_object_new_string(change)); + if (strcmp("focus", change) == 0) { + if (old) { + json_object_object_add(obj, "old", + ipc_json_describe_container_recursive(old)); + } else { + json_object_object_add(obj, "old", NULL); + } + } + + if (new) { + json_object_object_add(obj, "current", + ipc_json_describe_container_recursive(new)); + } else { + json_object_object_add(obj, "current", NULL); + } + + const char *json_string = json_object_to_json_string(obj); + ipc_send_event(json_string, IPC_EVENT_WORKSPACE); + json_object_put(obj); +} + void ipc_event_window(swayc_t *window, const char *change) { wlr_log(L_DEBUG, "Sending window::%s event", change); json_object *obj = json_object_new_object(); @@ -357,6 +383,25 @@ void ipc_client_disconnect(struct ipc_client *client) { free(client); } +static void ipc_get_workspaces_callback(swayc_t *workspace, void *data) { + if (workspace->type == C_WORKSPACE) { + json_object *workspace_json = ipc_json_describe_container(workspace); + // override the default focused indicator because + // it's set differently for the get_workspaces reply + struct sway_seat *seat = + sway_input_manager_get_default_seat(input_manager); + swayc_t *focused_ws = sway_seat_get_focus(seat); + if (focused_ws->type != C_WORKSPACE) { + focused_ws = swayc_parent_by_type(focused_ws, C_WORKSPACE); + } + bool focused = workspace == focused_ws; + json_object_object_del(workspace_json, "focused"); + json_object_object_add(workspace_json, "focused", + json_object_new_boolean(focused)); + json_object_array_add((json_object *)data, workspace_json); + } +} + void ipc_client_handle_command(struct ipc_client *client) { if (!sway_assert(client != NULL, "client != NULL")) { return; @@ -412,6 +457,16 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_WORKSPACES: + { + json_object *workspaces = json_object_new_array(); + container_map(&root_container, ipc_get_workspaces_callback, workspaces); + const char *json_string = json_object_to_json_string(workspaces); + ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); + json_object_put(workspaces); // free + goto exit_cleanup; + } + case IPC_SUBSCRIBE: { // TODO: Check if they're permitted to use these events @@ -446,7 +501,6 @@ void ipc_client_handle_command(struct ipc_client *client) { } json_object_put(request); - ipc_send_reply(client, "{\"success\": true}", 17); goto exit_cleanup; } @@ -483,6 +537,43 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_BAR_CONFIG: + { + if (!buf[0]) { + // Send list of configured bar IDs + json_object *bars = json_object_new_array(); + int i; + for (i = 0; i < config->bars->length; ++i) { + struct bar_config *bar = config->bars->items[i]; + json_object_array_add(bars, json_object_new_string(bar->id)); + } + const char *json_string = json_object_to_json_string(bars); + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(bars); // free + } else { + // Send particular bar's details + struct bar_config *bar = NULL; + int i; + for (i = 0; i < config->bars->length; ++i) { + bar = config->bars->items[i]; + if (strcmp(buf, bar->id) == 0) { + break; + } + bar = NULL; + } + if (!bar) { + const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; + ipc_send_reply(client, error, (uint32_t)strlen(error)); + goto exit_cleanup; + } + json_object *json = ipc_json_describe_bar_config(bar); + const char *json_string = json_object_to_json_string(json); + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(json); // free + } + goto exit_cleanup; + } + default: wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command); goto exit_cleanup; -- cgit v1.2.3 From 569b2bfd5daae5b3be49772bdca4a3f224e20629 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 17:41:02 -0400 Subject: Move bar config into its own file --- include/sway/config.h | 26 +++------ sway/config.c | 127 -------------------------------------------- sway/config/bar.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ sway/config/output.c | 2 +- sway/meson.build | 1 + 5 files changed, 151 insertions(+), 148 deletions(-) create mode 100644 sway/config/bar.c (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index f9ab6778..dbcfc91e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -12,6 +12,8 @@ #include "container.h" #include "wlr-layer-shell-unstable-v1-protocol.h" +// TODO: Refactor this shit + /** * Describes a variable created via the `set` command. */ @@ -407,11 +409,6 @@ void merge_output_config(struct output_config *dst, struct output_config *src); void apply_output_config(struct output_config *oc, swayc_t *output); void free_output_config(struct output_config *oc); -/** - * Updates the list of active bar modifiers - */ -void update_active_bar_modifiers(void); - int workspace_output_cmp_workspace(const void *a, const void *b); int sway_binding_cmp(const void *a, const void *b); @@ -420,27 +417,16 @@ int sway_binding_cmp_keys(const void *a, const void *b); void free_sway_binding(struct sway_binding *sb); struct sway_binding *sway_binding_dup(struct sway_binding *sb); -int sway_mouse_binding_cmp(const void *a, const void *b); -int sway_mouse_binding_cmp_qsort(const void *a, const void *b); -int sway_mouse_binding_cmp_buttons(const void *a, const void *b); -void free_sway_mouse_binding(struct sway_mouse_binding *smb); - +/* Bar stuff */ void load_swaybars(); void terminate_swaybg(pid_t pid); - -/** - * Allocate and initialize default bar configuration. - */ struct bar_config *default_bar_config(void); +void free_bar_config(struct bar_config *bar); -/** - * Global config singleton. - */ +/* Global config singleton. */ extern struct sway_config *config; -/** - * Config file currently being read. - */ +/* Config file currently being read */ extern const char *current_config_path; #endif diff --git a/sway/config.c b/sway/config.c index a0e408de..0422fdd9 100644 --- a/sway/config.c +++ b/sway/config.c @@ -110,48 +110,6 @@ void free_config(struct sway_config *config) { free(config); } -static void free_bar(struct bar_config *bar) { - if (!bar) { - return; - } - free(bar->mode); - free(bar->position); - free(bar->hidden_state); - free(bar->status_command); - free(bar->font); - free(bar->separator_symbol); - // TODO: Free mouse bindings - list_free(bar->bindings); - if (bar->outputs) { - free_flat_list(bar->outputs); - } - if (bar->pid != 0) { - // TODO terminate_swaybar(bar->pid); - } - free(bar->colors.background); - free(bar->colors.statusline); - free(bar->colors.separator); - free(bar->colors.focused_background); - free(bar->colors.focused_statusline); - free(bar->colors.focused_separator); - free(bar->colors.focused_workspace_border); - free(bar->colors.focused_workspace_bg); - free(bar->colors.focused_workspace_text); - free(bar->colors.active_workspace_border); - free(bar->colors.active_workspace_bg); - free(bar->colors.active_workspace_text); - free(bar->colors.inactive_workspace_border); - free(bar->colors.inactive_workspace_bg); - free(bar->colors.inactive_workspace_text); - free(bar->colors.urgent_workspace_border); - free(bar->colors.urgent_workspace_bg); - free(bar->colors.urgent_workspace_text); - free(bar->colors.binding_mode_border); - free(bar->colors.binding_mode_bg); - free(bar->colors.binding_mode_text); - free(bar); -} - static void destroy_removed_seats(struct sway_config *old_config, struct sway_config *new_config) { struct seat_config *seat_config; @@ -281,91 +239,6 @@ cleanup: sway_abort("Unable to allocate config structures"); } -struct bar_config *default_bar_config(void) { - struct bar_config *bar = NULL; - bar = malloc(sizeof(struct bar_config)); - if (!bar) { - return NULL; - } - if (!(bar->mode = strdup("dock"))) goto cleanup; - if (!(bar->hidden_state = strdup("hide"))) goto cleanup; - bar->outputs = NULL; - bar->position = strdup("bottom"); - if (!(bar->bindings = create_list())) goto cleanup; - if (!(bar->status_command = strdup("while :; do date +'%Y-%m-%d %l:%M:%S %p'; sleep 1; done"))) goto cleanup; - bar->pango_markup = false; - bar->swaybar_command = NULL; - bar->font = NULL; - bar->height = -1; - bar->workspace_buttons = true; - bar->wrap_scroll = false; - bar->separator_symbol = NULL; - bar->strip_workspace_numbers = false; - bar->binding_mode_indicator = true; - bar->verbose = false; - bar->pid = 0; - // set default colors - if (!(bar->colors.background = strndup("#000000ff", 9))) { - goto cleanup; - } - if (!(bar->colors.statusline = strndup("#ffffffff", 9))) { - goto cleanup; - } - if (!(bar->colors.separator = strndup("#666666ff", 9))) { - goto cleanup; - } - if (!(bar->colors.focused_workspace_border = strndup("#4c7899ff", 9))) { - goto cleanup; - } - if (!(bar->colors.focused_workspace_bg = strndup("#285577ff", 9))) { - goto cleanup; - } - if (!(bar->colors.focused_workspace_text = strndup("#ffffffff", 9))) { - goto cleanup; - } - if (!(bar->colors.active_workspace_border = strndup("#333333ff", 9))) { - goto cleanup; - } - if (!(bar->colors.active_workspace_bg = strndup("#5f676aff", 9))) { - goto cleanup; - } - if (!(bar->colors.active_workspace_text = strndup("#ffffffff", 9))) { - goto cleanup; - } - if (!(bar->colors.inactive_workspace_border = strndup("#333333ff", 9))) { - goto cleanup; - } - if (!(bar->colors.inactive_workspace_bg = strndup("#222222ff", 9))) { - goto cleanup; - } - if (!(bar->colors.inactive_workspace_text = strndup("#888888ff", 9))) { - goto cleanup; - } - if (!(bar->colors.urgent_workspace_border = strndup("#2f343aff", 9))) { - goto cleanup; - } - if (!(bar->colors.urgent_workspace_bg = strndup("#900000ff", 9))) { - goto cleanup; - } - if (!(bar->colors.urgent_workspace_text = strndup("#ffffffff", 9))) { - goto cleanup; - } - // if the following colors stay undefined, they fall back to background, - // statusline, separator and urgent_workspace_*. - bar->colors.focused_background = NULL; - bar->colors.focused_statusline = NULL; - bar->colors.focused_separator = NULL; - bar->colors.binding_mode_border = NULL; - bar->colors.binding_mode_bg = NULL; - bar->colors.binding_mode_text = NULL; - - list_add(config->bars, bar); - return bar; -cleanup: - free_bar(bar); - return NULL; -} - static bool file_exists(const char *path) { return path && access(path, R_OK) != -1; } diff --git a/sway/config/bar.c b/sway/config/bar.c new file mode 100644 index 00000000..ecc357d0 --- /dev/null +++ b/sway/config/bar.c @@ -0,0 +1,143 @@ +#define _POSIX_C_SOURCE 200809L +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sway/config.h" +#include "stringop.h" +#include "list.h" +#include "log.h" + +void free_bar_config(struct bar_config *bar) { + if (!bar) { + return; + } + free(bar->mode); + free(bar->position); + free(bar->hidden_state); + free(bar->status_command); + free(bar->font); + free(bar->separator_symbol); + // TODO: Free mouse bindings + list_free(bar->bindings); + if (bar->outputs) { + free_flat_list(bar->outputs); + } + if (bar->pid != 0) { + // TODO terminate_swaybar(bar->pid); + } + free(bar->colors.background); + free(bar->colors.statusline); + free(bar->colors.separator); + free(bar->colors.focused_background); + free(bar->colors.focused_statusline); + free(bar->colors.focused_separator); + free(bar->colors.focused_workspace_border); + free(bar->colors.focused_workspace_bg); + free(bar->colors.focused_workspace_text); + free(bar->colors.active_workspace_border); + free(bar->colors.active_workspace_bg); + free(bar->colors.active_workspace_text); + free(bar->colors.inactive_workspace_border); + free(bar->colors.inactive_workspace_bg); + free(bar->colors.inactive_workspace_text); + free(bar->colors.urgent_workspace_border); + free(bar->colors.urgent_workspace_bg); + free(bar->colors.urgent_workspace_text); + free(bar->colors.binding_mode_border); + free(bar->colors.binding_mode_bg); + free(bar->colors.binding_mode_text); + free(bar); +} + +struct bar_config *default_bar_config(void) { + struct bar_config *bar = NULL; + bar = malloc(sizeof(struct bar_config)); + if (!bar) { + return NULL; + } + if (!(bar->mode = strdup("dock"))) goto cleanup; + if (!(bar->hidden_state = strdup("hide"))) goto cleanup; + bar->outputs = NULL; + bar->position = strdup("bottom"); + if (!(bar->bindings = create_list())) goto cleanup; + if (!(bar->status_command = strdup("while :; do date +'%Y-%m-%d %l:%M:%S %p'; sleep 1; done"))) goto cleanup; + bar->pango_markup = false; + bar->swaybar_command = NULL; + bar->font = NULL; + bar->height = -1; + bar->workspace_buttons = true; + bar->wrap_scroll = false; + bar->separator_symbol = NULL; + bar->strip_workspace_numbers = false; + bar->binding_mode_indicator = true; + bar->verbose = false; + bar->pid = 0; + // set default colors + if (!(bar->colors.background = strndup("#000000ff", 9))) { + goto cleanup; + } + if (!(bar->colors.statusline = strndup("#ffffffff", 9))) { + goto cleanup; + } + if (!(bar->colors.separator = strndup("#666666ff", 9))) { + goto cleanup; + } + if (!(bar->colors.focused_workspace_border = strndup("#4c7899ff", 9))) { + goto cleanup; + } + if (!(bar->colors.focused_workspace_bg = strndup("#285577ff", 9))) { + goto cleanup; + } + if (!(bar->colors.focused_workspace_text = strndup("#ffffffff", 9))) { + goto cleanup; + } + if (!(bar->colors.active_workspace_border = strndup("#333333ff", 9))) { + goto cleanup; + } + if (!(bar->colors.active_workspace_bg = strndup("#5f676aff", 9))) { + goto cleanup; + } + if (!(bar->colors.active_workspace_text = strndup("#ffffffff", 9))) { + goto cleanup; + } + if (!(bar->colors.inactive_workspace_border = strndup("#333333ff", 9))) { + goto cleanup; + } + if (!(bar->colors.inactive_workspace_bg = strndup("#222222ff", 9))) { + goto cleanup; + } + if (!(bar->colors.inactive_workspace_text = strndup("#888888ff", 9))) { + goto cleanup; + } + if (!(bar->colors.urgent_workspace_border = strndup("#2f343aff", 9))) { + goto cleanup; + } + if (!(bar->colors.urgent_workspace_bg = strndup("#900000ff", 9))) { + goto cleanup; + } + if (!(bar->colors.urgent_workspace_text = strndup("#ffffffff", 9))) { + goto cleanup; + } + // if the following colors stay undefined, they fall back to background, + // statusline, separator and urgent_workspace_*. + bar->colors.focused_background = NULL; + bar->colors.focused_statusline = NULL; + bar->colors.focused_separator = NULL; + bar->colors.binding_mode_border = NULL; + bar->colors.binding_mode_bg = NULL; + bar->colors.binding_mode_text = NULL; + + list_add(config->bars, bar); + return bar; +cleanup: + free_bar_config(bar); + return NULL; +} diff --git a/sway/config/output.c b/sway/config/output.c index 9e211861..24b4a18e 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -186,7 +186,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { output_id[bufsize-1] = 0; char *const cmd[] = { - "./swaybg/swaybg", + "swaybg", output_id, oc->background, oc->background_option, diff --git a/sway/meson.build b/sway/meson.build index 8fcb0dbf..ac65d05e 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -64,6 +64,7 @@ sway_sources = files( 'commands/reload.c', 'commands/workspace.c', 'config.c', + 'config/bar.c', 'config/output.c', 'config/seat.c', 'config/input.c', -- cgit v1.2.3 From 5c9cdbcdd2a07e2ced7b60d629a3e20bd7c8bf68 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 17:49:44 -0400 Subject: Add swaybg_command --- include/sway/commands.h | 1 + include/sway/config.h | 1 + sway/commands.c | 1 + sway/commands/swaybg_command.c | 20 ++++++++++++++++++++ sway/config/output.c | 25 +++++++++++++------------ sway/meson.build | 1 + sway/sway.5.txt | 3 +++ 7 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 sway/commands/swaybg_command.c (limited to 'include/sway/config.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index dda286a2..1291d5fb 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -141,6 +141,7 @@ sway_cmd cmd_splith; sway_cmd cmd_splitt; sway_cmd cmd_splitv; sway_cmd cmd_sticky; +sway_cmd cmd_swaybg_command; sway_cmd cmd_unmark; sway_cmd cmd_workspace; sway_cmd cmd_ws_auto_back_and_forth; diff --git a/include/sway/config.h b/include/sway/config.h index dbcfc91e..4a7fee0f 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -282,6 +282,7 @@ struct sway_config { list_t *active_bar_modifiers; struct sway_mode *current_mode; struct bar_config *current_bar; + char *swaybg_command; uint32_t floating_mod; uint32_t dragging_key; uint32_t resizing_key; diff --git a/sway/commands.c b/sway/commands.c index 8d8b643b..38e2f764 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -149,6 +149,7 @@ static struct cmd_handler bar_colors_handlers[] = { /* Config-time only commands. Keep alphabetized */ static struct cmd_handler config_handlers[] = { { "set", cmd_set }, + { "swaybg_command", cmd_swaybg_command }, }; /* Runtime-only commands. Keep alphabetized */ diff --git a/sway/commands/swaybg_command.c b/sway/commands/swaybg_command.c new file mode 100644 index 00000000..770d4821 --- /dev/null +++ b/sway/commands/swaybg_command.c @@ -0,0 +1,20 @@ +#include +#include "sway/commands.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *cmd_swaybg_command(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "swaybg_command", EXPECTED_AT_LEAST, 1))) { + return error; + } + + if (config->swaybg_command) { + free(config->swaybg_command); + } + config->swaybg_command = join_args(argv, argc); + wlr_log(L_DEBUG, "Using custom swaybg command: %s", + config->swaybg_command); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config/output.c b/sway/config/output.c index 24b4a18e..c3ec61b7 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -180,19 +180,20 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { wlr_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); - size_t bufsize = 12; - char output_id[bufsize]; - snprintf(output_id, bufsize, "%d", output_i); - output_id[bufsize-1] = 0; - - char *const cmd[] = { - "swaybg", - output_id, - oc->background, - oc->background_option, - NULL, - }; + size_t len = snprintf(NULL, 0, "%s %d %s %s", + config->swaybg_command ? config->swaybg_command : "swaybg", + output_i, oc->background, oc->background_option); + char *command = malloc(len + 1); + if (!command) { + wlr_log(L_DEBUG, "Unable to allocate swaybg command"); + return; + } + snprintf(command, len + 1, "%s %d %s %s", + config->swaybg_command ? config->swaybg_command : "swaybg", + output_i, oc->background, oc->background_option); + wlr_log(L_DEBUG, "-> %s", command); + char *const cmd[] = { "sh", "-c", command, NULL }; output->sway_output->bg_pid = fork(); if (output->sway_output->bg_pid == 0) { execvp(cmd[0], cmd); diff --git a/sway/meson.build b/sway/meson.build index ac65d05e..54c03061 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -20,6 +20,7 @@ sway_sources = files( 'commands/seat/attach.c', 'commands/seat/fallback.c', 'commands/set.c', + 'commands/swaybg_command.c', 'commands/bar/activate_button.c', 'commands/bar/binding_mode_indicator.c', 'commands/bar/bindsym.c', diff --git a/sway/sway.5.txt b/sway/sway.5.txt index 6c9bce7a..900e499a 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -43,6 +43,9 @@ The following commands may only be used in the configuration file. Sets variable $name to _value_. You can use the new variable in the arguments of future commands. +**swaybg_command** :: + Executes custom bg command, default is _swaybg_. + The following commands cannot be used directly in the configuration file. They are expected to be used with **bindsym** or at runtime through **swaymsg**(1). -- cgit v1.2.3 From 2719ddfe5e171881f3997f9f853bfca97fe01529 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 18:07:03 -0400 Subject: Spawn swaybars when outputs are added --- include/sway/config.h | 1 + sway/config/bar.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++ sway/server.c | 6 +++- sway/tree/container.c | 2 +- 4 files changed, 102 insertions(+), 2 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 4a7fee0f..b7820128 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -420,6 +420,7 @@ struct sway_binding *sway_binding_dup(struct sway_binding *sb); /* Bar stuff */ void load_swaybars(); +void invoke_swaybar(struct bar_config *bar); void terminate_swaybg(pid_t pid); struct bar_config *default_bar_config(void); void free_bar_config(struct bar_config *bar); diff --git a/sway/config/bar.c b/sway/config/bar.c index ecc357d0..5e02c01c 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -141,3 +141,98 @@ cleanup: free_bar_config(bar); return NULL; } + +void invoke_swaybar(struct bar_config *bar) { + // Pipe to communicate errors + int filedes[2]; + if (pipe(filedes) == -1) { + wlr_log(L_ERROR, "Pipe setup failed! Cannot fork into bar"); + return; + } + + bar->pid = fork(); + if (bar->pid == 0) { + close(filedes[0]); + + // run custom swaybar + size_t len = snprintf(NULL, 0, "%s -b %s", + bar->swaybar_command ? bar->swaybar_command : "swaybar", + bar->id); + char *command = malloc(len + 1); + if (!command) { + const char msg[] = "Unable to allocate swaybar command string"; + size_t len = sizeof(msg); + if (write(filedes[1], &len, sizeof(int))) {}; + if (write(filedes[1], msg, len)) {}; + close(filedes[1]); + exit(1); + } + snprintf(command, len + 1, "%s -b %s", + bar->swaybar_command ? bar->swaybar_command : "swaybar", + bar->id); + char *const cmd[] = { "sh", "-c", command, NULL, }; + close(filedes[1]); + execvp(cmd[0], cmd); + exit(1); + } + close(filedes[0]); + ssize_t len; + if (read(filedes[1], &len, sizeof(int)) == sizeof(int)) { + char *buf = malloc(len); + if(!buf) { + wlr_log(L_ERROR, "Cannot allocate error string"); + return; + } + if (read(filedes[1], buf, len)) { + wlr_log(L_ERROR, "%s", buf); + } + free(buf); + } + close(filedes[1]); +} + +static void terminate_swaybar(pid_t pid) { + int ret = kill(pid, SIGTERM); + if (ret != 0) { + wlr_log_errno(L_ERROR, "Unable to terminate swaybar %d", pid); + } else { + int status; + waitpid(pid, &status, 0); + } +} + +static bool active_output(const char *name) { + swayc_t *cont = NULL; + for (int i = 0; i < root_container.children->length; ++i) { + cont = root_container.children->items[i]; + if (cont->type == C_OUTPUT && strcasecmp(name, cont->name) == 0) { + return true; + } + } + return false; +} + +void load_swaybars() { + for (int i = 0; i < config->bars->length; ++i) { + struct bar_config *bar = config->bars->items[i]; + bool apply = false; + if (bar->outputs) { + for (int j = 0; j < bar->outputs->length; ++j) { + char *o = bar->outputs->items[j]; + if (!strcmp(o, "*") || active_output(o)) { + apply = true; + break; + } + } + } else { + apply = true; + } + if (apply) { + if (bar->pid != 0) { + terminate_swaybar(bar->pid); + } + wlr_log(L_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); + invoke_swaybar(bar); + } + } +} diff --git a/sway/server.c b/sway/server.c index 92f72f13..75202df2 100644 --- a/sway/server.c +++ b/sway/server.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include // TODO WLR: make Xwayland optional #include @@ -45,10 +47,12 @@ bool server_init(struct sway_server *server) { server->compositor = wlr_compositor_create( server->wl_display, server->renderer); - server->data_device_manager = wlr_data_device_manager_create(server->wl_display); + wlr_screenshooter_create(server->wl_display); + wlr_gamma_control_manager_create(server->wl_display); + server->new_output.notify = handle_new_output; wl_signal_add(&server->backend->events.new_output, &server->new_output); diff --git a/sway/tree/container.c b/sway/tree/container.c index bbafe9ec..64e2bdee 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -165,8 +165,8 @@ swayc_t *new_output(struct sway_output *sway_output) { } apply_output_config(oc, output); - add_child(&root_container, output); + load_swaybars(); // Create workspace char *ws_name = workspace_next_name(output->name); -- cgit v1.2.3 From d0c7f66e950689b70196a890b62b82ff3c66e103 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 23:29:29 -0400 Subject: Revert "Refactor tree" --- include/sway/config.h | 17 ++- include/sway/container.h | 169 ++++++++++++++++++++++++++++ include/sway/criteria.h | 6 +- include/sway/input/input-manager.h | 4 +- include/sway/input/seat.h | 13 +-- include/sway/ipc-json.h | 6 +- include/sway/ipc-server.h | 6 +- include/sway/layout.h | 43 ++++++++ include/sway/tree/container.h | 137 ----------------------- include/sway/tree/layout.h | 52 --------- include/sway/tree/view.h | 116 ------------------- include/sway/tree/workspace.h | 26 ----- include/sway/view.h | 120 ++++++++++++++++++++ include/sway/workspace.h | 20 ++++ sway/commands/exec_always.c | 4 +- sway/commands/focus.c | 9 +- sway/commands/kill.c | 4 +- sway/commands/layout.c | 20 ++-- sway/commands/output.c | 2 +- sway/commands/reload.c | 2 +- sway/commands/workspace.c | 14 +-- sway/config.c | 2 +- sway/config/output.c | 4 +- sway/criteria.c | 16 +-- sway/desktop/layer_shell.c | 2 +- sway/desktop/output.c | 20 ++-- sway/desktop/wl_shell.c | 12 +- sway/desktop/xdg_shell_v6.c | 12 +- sway/desktop/xwayland.c | 24 ++-- sway/input/cursor.c | 10 +- sway/input/input-manager.c | 4 +- sway/input/seat.c | 38 +++---- sway/ipc-json.c | 16 +-- sway/ipc-server.c | 4 +- sway/main.c | 4 +- sway/tree/container.c | 221 ++++++++++++++++++++----------------- sway/tree/layout.c | 133 +++++++++------------- sway/tree/view.c | 7 +- sway/tree/workspace.c | 92 +++++++-------- swaybar/ipc.c | 2 +- 40 files changed, 704 insertions(+), 709 deletions(-) create mode 100644 include/sway/container.h create mode 100644 include/sway/layout.h delete mode 100644 include/sway/tree/container.h delete mode 100644 include/sway/tree/layout.h delete mode 100644 include/sway/tree/view.h delete mode 100644 include/sway/tree/workspace.h create mode 100644 include/sway/view.h create mode 100644 include/sway/workspace.h (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 7fdd0be0..48a8b0ab 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -10,8 +10,8 @@ #include #include #include "list.h" -#include "tree/layout.h" -#include "tree/container.h" +#include "layout.h" +#include "container.h" /** * Describes a variable created via the `set` command. @@ -299,8 +299,8 @@ struct sway_config { char *floating_scroll_down_cmd; char *floating_scroll_left_cmd; char *floating_scroll_right_cmd; - enum sway_container_layout default_orientation; - enum sway_container_layout default_layout; + enum swayc_layouts default_orientation; + enum swayc_layouts default_layout; char *font; int font_height; @@ -324,8 +324,8 @@ struct sway_config { list_t *config_chain; const char *current_config; - enum sway_container_border border; - enum sway_container_border floating_border; + enum swayc_border_types border; + enum swayc_border_types floating_border; int border_thickness; int floating_border_thickness; enum edge_border_types hide_edge_borders; @@ -356,7 +356,7 @@ struct sway_config { struct input_config *input_config; struct seat_config *seat_config; struct sway_seat *seat; - struct sway_container *current_container; + swayc_t *current_container; } handler_context; }; @@ -416,8 +416,7 @@ void output_get_identifier(char *identifier, size_t len, struct sway_output *output); struct output_config *new_output_config(const char *name); void merge_output_config(struct output_config *dst, struct output_config *src); -void apply_output_config(struct output_config *oc, - struct sway_container *output); +void apply_output_config(struct output_config *oc, swayc_t *output); void free_output_config(struct output_config *oc); /** diff --git a/include/sway/container.h b/include/sway/container.h new file mode 100644 index 00000000..f200a1a2 --- /dev/null +++ b/include/sway/container.h @@ -0,0 +1,169 @@ +#ifndef _SWAY_CONTAINER_H +#define _SWAY_CONTAINER_H +#include +#include +#include +#include +#include "list.h" + +typedef struct sway_container swayc_t; + +extern swayc_t root_container; + +struct sway_view; +struct sway_seat; + +/** + * Different kinds of containers. + * + * This enum is in order. A container will never be inside of a container below + * it on this list. + */ +enum swayc_types { + C_ROOT, /**< The root container. Only one of these ever exists. */ + C_OUTPUT, /**< An output (aka monitor, head, etc). */ + C_WORKSPACE, /**< A workspace. */ + C_CONTAINER, /**< A manually created container. */ + C_VIEW, /**< A view (aka window). */ + + C_TYPES, +}; + +/** + * Different ways to arrange a container. + */ +enum swayc_layouts { + L_NONE, /**< Used for containers that have no layout (views, root) */ + L_HORIZ, + L_VERT, + L_STACKED, + L_TABBED, + L_FLOATING, /**< A psuedo-container, removed from the tree, to hold floating windows */ + + /* Awesome/Monad style auto layouts */ + L_AUTO_LEFT, + L_AUTO_RIGHT, + L_AUTO_TOP, + L_AUTO_BOTTOM, + + L_AUTO_FIRST = L_AUTO_LEFT, + L_AUTO_LAST = L_AUTO_BOTTOM, + + // Keep last + L_LAYOUTS, +}; + +enum swayc_border_types { + B_NONE, /**< No border */ + B_PIXEL, /**< 1px border */ + B_NORMAL, /**< Normal border with title bar */ +}; + +struct sway_root; +struct sway_output; +struct sway_view; + +/** + * Stores information about a container. + * + * The tree is made of these. Views are containers that cannot have children. + */ +struct sway_container { + union { + // TODO: Encapsulate state for other node types as well like C_CONTAINER + struct sway_root *sway_root; // C_ROOT + struct sway_output *sway_output; // C_OUTPUT + struct sway_view *sway_view; // C_VIEW + }; + + /** + * A unique ID to identify this container. Primarily used in the + * get_tree JSON output. + */ + size_t id; + + char *name; + + enum swayc_types type; + enum swayc_layouts layout; + enum swayc_layouts prev_layout; + enum swayc_layouts workspace_layout; + + /** + * The coordinates that this view appear at, relative to the output they + * are located on (output containers have absolute coordinates). + */ + double x, y; + + /** + * Width and height of this container, without borders or gaps. + */ + double width, height; + + list_t *children; + + /** + * The parent of this container. NULL for the root container. + */ + struct sway_container *parent; + + /** + * Number of master views in auto layouts. + */ + size_t nb_master; + + /** + * Number of slave groups (e.g. columns) in auto layouts. + */ + size_t nb_slave_groups; + + /** + * Marks applied to the container, list_t of char*. + */ + list_t *marks; + + struct { + struct wl_signal destroy; + } events; +}; + +void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, + void (*func)(swayc_t *item, void *data), void *data); + +swayc_t *new_output(struct sway_output *sway_output); +swayc_t *new_workspace(swayc_t *output, const char *name); +swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view); + +swayc_t *destroy_output(swayc_t *output); +swayc_t *destroy_view(swayc_t *view); + +swayc_t *next_view_sibling(struct sway_seat *seat); + +/** + * Finds a container based on test criteria. Returns the first container that + * passes the test. + */ +swayc_t *swayc_by_test(swayc_t *container, + bool (*test)(swayc_t *view, void *data), void *data); +/** + * Finds a parent container with the given swayc_type. + */ +swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); +/** + * Maps a container's children over a function. + */ +void container_map(swayc_t *container, + void (*f)(swayc_t *view, void *data), void *data); + +swayc_t *swayc_at(swayc_t *parent, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy); + +/** + * Apply the function for each child of the container breadth first. + */ +void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), + void *data); + +swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout); + +#endif diff --git a/include/sway/criteria.h b/include/sway/criteria.h index ec256ddb..9b4b4bef 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -1,7 +1,7 @@ #ifndef _SWAY_CRITERIA_H #define _SWAY_CRITERIA_H -#include "tree/container.h" +#include "container.h" #include "list.h" /** @@ -31,12 +31,12 @@ char *extract_crit_tokens(list_t *tokens, const char *criteria); // Returns list of criteria that match given container. These criteria have // been set with `for_window` commands and have an associated cmdlist. -list_t *criteria_for(struct sway_container *cont); +list_t *criteria_for(swayc_t *cont); // Returns a list of all containers that match the given list of tokens. list_t *container_for_crit_tokens(list_t *tokens); // Returns true if any criteria in the given list matches this container -bool criteria_any(struct sway_container *cont, list_t *criteria); +bool criteria_any(swayc_t *cont, list_t *criteria); #endif diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index c6c73dba..eab7dc90 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -31,10 +31,10 @@ struct sway_input_manager *sway_input_manager_create( struct sway_server *server); bool sway_input_manager_has_focus(struct sway_input_manager *input, - struct sway_container *container); + swayc_t *container); void sway_input_manager_set_focus(struct sway_input_manager *input, - struct sway_container *container); + swayc_t *container); void sway_input_manager_configure_xcursor(struct sway_input_manager *input); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 496bfd5d..1d55bec7 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -14,7 +14,7 @@ struct sway_seat_device { struct sway_seat_container { struct sway_seat *seat; - struct sway_container *container; + swayc_t *container; struct wl_list link; // sway_seat::focus_stack @@ -54,9 +54,9 @@ void sway_seat_remove_device(struct sway_seat *seat, void sway_seat_configure_xcursor(struct sway_seat *seat); -void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); +void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); -struct sway_container *sway_seat_get_focus(struct sway_seat *seat); +swayc_t *sway_seat_get_focus(struct sway_seat *seat); /** * Return the last container to be focused for the seat (or the most recently @@ -67,11 +67,10 @@ struct sway_container *sway_seat_get_focus(struct sway_seat *seat); * is destroyed, or focus moves to a container with children and we need to * descend into the next leaf in focus order. */ -struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, - struct sway_container *container); +swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container); -struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, - enum sway_container_type type); +swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, + enum swayc_types type); void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index 3d2fdc4f..eef5a018 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -1,13 +1,13 @@ #ifndef _SWAY_IPC_JSON_H #define _SWAY_IPC_JSON_H #include -#include "sway/tree/container.h" +#include "sway/container.h" #include "sway/input/input-manager.h" json_object *ipc_json_get_version(); -json_object *ipc_json_describe_container(struct sway_container *c); -json_object *ipc_json_describe_container_recursive(struct sway_container *c); +json_object *ipc_json_describe_container(swayc_t *c); +json_object *ipc_json_describe_container_recursive(swayc_t *c); json_object *ipc_json_describe_input(struct sway_input_device *device); #endif diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index d73006dc..bcf1c433 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -1,17 +1,15 @@ #ifndef _SWAY_IPC_SERVER_H #define _SWAY_IPC_SERVER_H #include -#include "sway/tree/container.h" +#include "sway/container.h" #include "ipc.h" struct sway_server; void ipc_init(struct sway_server *server); - void ipc_terminate(void); - struct sockaddr_un *ipc_user_sockaddr(void); -void ipc_event_window(struct sway_container *window, const char *change); +void ipc_event_window(swayc_t *window, const char *change); #endif diff --git a/include/sway/layout.h b/include/sway/layout.h new file mode 100644 index 00000000..e82c4442 --- /dev/null +++ b/include/sway/layout.h @@ -0,0 +1,43 @@ +#ifndef _SWAY_LAYOUT_H +#define _SWAY_LAYOUT_H + +#include +#include "sway/container.h" + +enum movement_direction { + MOVE_LEFT, + MOVE_RIGHT, + MOVE_UP, + MOVE_DOWN, + MOVE_PARENT, + MOVE_CHILD, + MOVE_NEXT, + MOVE_PREV, + MOVE_FIRST +}; + +struct sway_container; + +struct sway_root { + struct wlr_output_layout *output_layout; + + struct wl_listener output_layout_change; + + struct wl_list unmanaged_views; // sway_view::unmanaged_view_link + + struct { + struct wl_signal new_container; + } events; +}; + +void init_layout(void); +void add_child(struct sway_container *parent, struct sway_container *child); +swayc_t *add_sibling(swayc_t *parent, swayc_t *child); +struct sway_container *remove_child(struct sway_container *child); +enum swayc_layouts default_layout(struct sway_container *output); +void sort_workspaces(struct sway_container *output); +void arrange_windows(struct sway_container *container, double width, double height); +swayc_t *get_swayc_in_direction(swayc_t *container, + struct sway_seat *seat, enum movement_direction dir); + +#endif diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h deleted file mode 100644 index 16df3ee7..00000000 --- a/include/sway/tree/container.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef _SWAY_CONTAINER_H -#define _SWAY_CONTAINER_H -#include -#include -#include -#include -#include "list.h" - -extern struct sway_container root_container; - -struct sway_view; -struct sway_seat; - -/** - * Different kinds of containers. - * - * This enum is in order. A container will never be inside of a container below - * it on this list. - */ -enum sway_container_type { - C_ROOT, - C_OUTPUT, - C_WORKSPACE, - C_CONTAINER, - C_VIEW, - - C_TYPES, -}; - -enum sway_container_layout { - L_NONE, - L_HORIZ, - L_VERT, - L_STACKED, - L_TABBED, - L_FLOATING, - - // Keep last - L_LAYOUTS, -}; - -enum sway_container_border { - B_NONE, - B_PIXEL, - B_NORMAL, -}; - -struct sway_root; -struct sway_output; -struct sway_view; - -struct sway_container { - union { - // TODO: Encapsulate state for other node types as well like C_CONTAINER - struct sway_root *sway_root; - struct sway_output *sway_output; - struct sway_view *sway_view; - }; - - /** - * A unique ID to identify this container. Primarily used in the - * get_tree JSON output. - */ - size_t id; - - char *name; - - enum sway_container_type type; - enum sway_container_layout layout; - enum sway_container_layout prev_layout; - enum sway_container_layout workspace_layout; - - // TODO convert to layout coordinates - double x, y; - - // does not include borders or gaps. - double width, height; - - list_t *children; - - struct sway_container *parent; - - list_t *marks; // list of char* - - struct { - struct wl_signal destroy; - } events; -}; - -// TODO only one container create function and pass the type? -struct sway_container *container_output_create( - struct sway_output *sway_output); - -struct sway_container *container_workspace_create( - struct sway_container *output, const char *name); - -struct sway_container *container_view_create( - struct sway_container *sibling, struct sway_view *sway_view); - -struct sway_container *container_output_destroy(struct sway_container *output); - -struct sway_container *container_view_destroy(struct sway_container *view); - -struct sway_container *container_set_layout(struct sway_container *container, - enum sway_container_layout layout); - -void container_descendents(struct sway_container *root, - enum sway_container_type type, - void (*func)(struct sway_container *item, void *data), void *data); - -/** - * Finds a container based on test criteria. Returns the first container that - * passes the test. - */ -struct sway_container *container_find(struct sway_container *container, - bool (*test)(struct sway_container *view, void *data), void *data); - -/** - * Finds a parent container with the given struct sway_containerype. - */ -struct sway_container *container_parent(struct sway_container *container, - enum sway_container_type type); - -/** - * Find a container at the given coordinates. - */ -struct sway_container *container_at(struct sway_container *parent, - double lx, double ly, struct wlr_surface **surface, - double *sx, double *sy); - -/** - * Apply the function for each child of the container breadth first. - */ -void container_for_each_descendent(struct sway_container *container, - void (*f)(struct sway_container *container, void *data), void *data); - -#endif diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h deleted file mode 100644 index ad52bdb0..00000000 --- a/include/sway/tree/layout.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _SWAY_LAYOUT_H -#define _SWAY_LAYOUT_H - -#include -#include "sway/tree/container.h" - -enum movement_direction { - MOVE_LEFT, - MOVE_RIGHT, - MOVE_UP, - MOVE_DOWN, - MOVE_PARENT, - MOVE_CHILD, - MOVE_NEXT, - MOVE_PREV, - MOVE_FIRST -}; - -struct sway_container; - -struct sway_root { - struct wlr_output_layout *output_layout; - - struct wl_listener output_layout_change; - - struct wl_list unmanaged_views; // sway_view::unmanaged_view_link - - struct { - struct wl_signal new_container; - } events; -}; - -void layout_init(void); - -void container_add_child(struct sway_container *parent, struct sway_container *child); - -struct sway_container *container_add_sibling(struct sway_container *parent, - struct sway_container *child); - -struct sway_container *container_remove_child(struct sway_container *child); - -enum sway_container_layout container_get_default_layout(struct sway_container *output); - -void container_sort_workspaces(struct sway_container *output); - -void arrange_windows(struct sway_container *container, - double width, double height); - -struct sway_container *container_get_in_direction(struct sway_container - *container, struct sway_seat *seat, enum movement_direction dir); - -#endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h deleted file mode 100644 index e5f53f4e..00000000 --- a/include/sway/tree/view.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef _SWAY_VIEW_H -#define _SWAY_VIEW_H -#include -#include -#include -#include - -struct sway_container; -struct sway_view; - -struct sway_xdg_surface_v6 { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -struct sway_xwayland_surface { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener request_configure; - struct wl_listener unmap_notify; - struct wl_listener map_notify; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -struct sway_wl_shell_surface { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -enum sway_view_type { - SWAY_WL_SHELL_VIEW, - SWAY_XDG_SHELL_V6_VIEW, - SWAY_XWAYLAND_VIEW, - // Keep last - SWAY_VIEW_TYPES, -}; - -enum sway_view_prop { - VIEW_PROP_TITLE, - VIEW_PROP_APP_ID, - VIEW_PROP_CLASS, - VIEW_PROP_INSTANCE, -}; - -struct sway_view { - enum sway_view_type type; - struct sway_container *swayc; - struct wlr_surface *surface; - int width, height; - - union { - struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; - struct wlr_xwayland_surface *wlr_xwayland_surface; - struct wlr_wl_shell_surface *wlr_wl_shell_surface; - }; - - union { - struct sway_xdg_surface_v6 *sway_xdg_surface_v6; - struct sway_xwayland_surface *sway_xwayland_surface; - struct sway_wl_shell_surface *sway_wl_shell_surface; - }; - - struct { - const char *(*get_prop)(struct sway_view *view, - enum sway_view_prop prop); - void (*set_size)(struct sway_view *view, - int width, int height); - void (*set_position)(struct sway_view *view, - double ox, double oy); - void (*set_activated)(struct sway_view *view, bool activated); - void (*close)(struct sway_view *view); - } iface; - - // only used for unmanaged views (shell specific) - struct wl_list unmanaged_view_link; // sway_root::unmanaged views -}; - -const char *view_get_title(struct sway_view *view); - -const char *view_get_app_id(struct sway_view *view); - -const char *view_get_class(struct sway_view *view); - -const char *view_get_instance(struct sway_view *view); - -void view_set_size(struct sway_view *view, int width, int height); - -void view_set_position(struct sway_view *view, double ox, double oy); - -void view_set_activated(struct sway_view *view, bool activated); - -void view_close(struct sway_view *view); - -void view_update_outputs(struct sway_view *view, const struct wlr_box *before); - -#endif diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h deleted file mode 100644 index d73b29c1..00000000 --- a/include/sway/tree/workspace.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _SWAY_WORKSPACE_H -#define _SWAY_WORKSPACE_H - -#include "sway/tree/container.h" - -extern char *prev_workspace_name; - -char *workspace_next_name(const char *output_name); - -struct sway_container *workspace_create(const char *name); - -bool workspace_switch(struct sway_container *workspace); - -struct sway_container *workspace_by_number(const char* name); - -struct sway_container *workspace_by_name(const char*); - -struct sway_container *workspace_output_next(struct sway_container *current); - -struct sway_container *workspace_next(struct sway_container *current); - -struct sway_container *workspace_output_prev(struct sway_container *current); - -struct sway_container *workspace_prev(struct sway_container *current); - -#endif diff --git a/include/sway/view.h b/include/sway/view.h new file mode 100644 index 00000000..b2886211 --- /dev/null +++ b/include/sway/view.h @@ -0,0 +1,120 @@ +#ifndef _SWAY_VIEW_H +#define _SWAY_VIEW_H +#include +#include +#include +#include + +struct sway_container; +struct sway_view; + +struct sway_xdg_surface_v6 { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +struct sway_xwayland_surface { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener request_configure; + struct wl_listener unmap_notify; + struct wl_listener map_notify; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +struct sway_wl_shell_surface { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +enum sway_view_type { + SWAY_WL_SHELL_VIEW, + SWAY_XDG_SHELL_V6_VIEW, + SWAY_XWAYLAND_VIEW, + // Keep last + SWAY_VIEW_TYPES, +}; + +enum sway_view_prop { + VIEW_PROP_TITLE, + VIEW_PROP_APP_ID, + VIEW_PROP_CLASS, + VIEW_PROP_INSTANCE, +}; + +/** + * sway_view is a state container for surfaces that are arranged in the sway + * tree (shell surfaces). + */ +struct sway_view { + enum sway_view_type type; + struct sway_container *swayc; + struct wlr_surface *surface; + int width, height; + + union { + struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; + struct wlr_xwayland_surface *wlr_xwayland_surface; + struct wlr_wl_shell_surface *wlr_wl_shell_surface; + }; + + union { + struct sway_xdg_surface_v6 *sway_xdg_surface_v6; + struct sway_xwayland_surface *sway_xwayland_surface; + struct sway_wl_shell_surface *sway_wl_shell_surface; + }; + + struct { + const char *(*get_prop)(struct sway_view *view, + enum sway_view_prop prop); + void (*set_size)(struct sway_view *view, + int width, int height); + void (*set_position)(struct sway_view *view, + double ox, double oy); + void (*set_activated)(struct sway_view *view, bool activated); + void (*close)(struct sway_view *view); + } iface; + + // only used for unmanaged views (shell specific) + struct wl_list unmanaged_view_link; // sway_root::unmanaged views +}; + +const char *view_get_title(struct sway_view *view); + +const char *view_get_app_id(struct sway_view *view); + +const char *view_get_class(struct sway_view *view); + +const char *view_get_instance(struct sway_view *view); + +void view_set_size(struct sway_view *view, int width, int height); + +void view_set_position(struct sway_view *view, double ox, double oy); + +void view_set_activated(struct sway_view *view, bool activated); + +void view_close(struct sway_view *view); + +void view_update_outputs(struct sway_view *view, const struct wlr_box *before); + +#endif diff --git a/include/sway/workspace.h b/include/sway/workspace.h new file mode 100644 index 00000000..fee54255 --- /dev/null +++ b/include/sway/workspace.h @@ -0,0 +1,20 @@ +#ifndef _SWAY_WORKSPACE_H +#define _SWAY_WORKSPACE_H + +#include "sway/container.h" + +extern char *prev_workspace_name; + +char *workspace_next_name(const char *output_name); +swayc_t *workspace_create(const char *name); +bool workspace_switch(swayc_t *workspace); + +struct sway_container *workspace_by_number(const char* name); +swayc_t *workspace_by_name(const char*); + +struct sway_container *workspace_output_next(swayc_t *current); +struct sway_container *workspace_next(swayc_t *current); +struct sway_container *workspace_output_prev(swayc_t *current); +struct sway_container *workspace_prev(swayc_t *current); + +#endif diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 954950e7..61870c51 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -6,8 +6,8 @@ #include #include "sway/commands.h" #include "sway/config.h" -#include "sway/tree/container.h" -#include "sway/tree/workspace.h" +#include "sway/container.h" +#include "sway/workspace.h" #include "log.h" #include "stringop.h" diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 64f079f4..f1a8078f 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -3,11 +3,10 @@ #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "sway/commands.h" -static bool parse_movement_direction(const char *name, - enum movement_direction *out) { +static bool parse_movement_direction(const char *name, enum movement_direction *out) { if (strcasecmp(name, "left") == 0) { *out = MOVE_LEFT; } else if (strcasecmp(name, "right") == 0) { @@ -32,7 +31,7 @@ static bool parse_movement_direction(const char *name, } struct cmd_results *cmd_focus(int argc, char **argv) { - struct sway_container *con = config->handler_context.current_container; + swayc_t *con = config->handler_context.current_container; struct sway_seat *seat = config->handler_context.seat; if (con->type < C_WORKSPACE) { return cmd_results_new(CMD_FAILURE, "focus", @@ -51,7 +50,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) { "Expected 'focus ' or 'focus output '"); } - struct sway_container *next_focus = container_get_in_direction(con, seat, direction); + swayc_t *next_focus = get_swayc_in_direction(con, seat, direction); if (next_focus) { sway_seat_set_focus(seat, next_focus); } diff --git a/sway/commands/kill.c b/sway/commands/kill.c index f6774767..f408ce2a 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -2,11 +2,11 @@ #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "sway/commands.h" struct cmd_results *cmd_kill(int argc, char **argv) { - enum sway_container_type type = config->handler_context.current_container->type; + enum swayc_types type = config->handler_context.current_container->type; if (type != C_VIEW && type != C_CONTAINER) { return cmd_results_new(CMD_INVALID, NULL, "Can only kill views and containers with this command"); diff --git a/sway/commands/layout.c b/sway/commands/layout.c index ebab2a48..b0fc5d66 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -1,8 +1,8 @@ #include #include #include "sway/commands.h" -#include "sway/tree/container.h" -#include "sway/tree/layout.h" +#include "sway/container.h" +#include "sway/layout.h" #include "log.h" struct cmd_results *cmd_layout(int argc, char **argv) { @@ -10,7 +10,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { return error; } - struct sway_container *parent = config->handler_context.current_container; + swayc_t *parent = config->handler_context.current_container; // TODO: floating /* @@ -26,10 +26,10 @@ struct cmd_results *cmd_layout(int argc, char **argv) { // TODO: stacks and tabs if (strcasecmp(argv[0], "default") == 0) { - container_set_layout(parent, parent->prev_layout); + swayc_change_layout(parent, parent->prev_layout); if (parent->layout == L_NONE) { - struct sway_container *output = container_parent(parent, C_OUTPUT); - container_set_layout(parent, container_get_default_layout(output)); + swayc_t *output = swayc_parent_by_type(parent, C_OUTPUT); + swayc_change_layout(parent, default_layout(output)); } } else { if (parent->layout != L_TABBED && parent->layout != L_STACKED) { @@ -37,15 +37,15 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } if (strcasecmp(argv[0], "splith") == 0) { - container_set_layout(parent, L_HORIZ); + swayc_change_layout(parent, L_HORIZ); } else if (strcasecmp(argv[0], "splitv") == 0) { - container_set_layout(parent, L_VERT); + swayc_change_layout(parent, L_VERT); } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE || parent->workspace_layout == L_HORIZ)) { - container_set_layout(parent, L_VERT); + swayc_change_layout(parent, L_VERT); } else { - container_set_layout(parent, L_HORIZ); + swayc_change_layout(parent, L_HORIZ); } } } diff --git a/sway/commands/output.c b/sway/commands/output.c index f7e3372c..35bc8099 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -296,7 +296,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { char identifier[128]; bool all = strcmp(output->name, "*") == 0; for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *cont = root_container.children->items[i]; + swayc_t *cont = root_container.children->items[i]; if (cont->type != C_OUTPUT) { continue; } diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 8cef789b..d54d40db 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -1,6 +1,6 @@ #include "sway/commands.h" #include "sway/config.h" -#include "sway/tree/layout.h" +#include "sway/layout.h" struct cmd_results *cmd_reload(int argc, char **argv) { struct cmd_results *error = NULL; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 8f39e5fc..fa891398 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -4,7 +4,7 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/input/seat.h" -#include "sway/tree/workspace.h" +#include "sway/workspace.h" #include "list.h" #include "log.h" #include "stringop.h" @@ -17,15 +17,15 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { int output_location = -1; - struct sway_container *current_container = config->handler_context.current_container; - struct sway_container *old_workspace = NULL, *old_output = NULL; + swayc_t *current_container = config->handler_context.current_container; + swayc_t *old_workspace = NULL, *old_output = NULL; if (current_container) { if (current_container->type == C_WORKSPACE) { old_workspace = current_container; } else { - old_workspace = container_parent(current_container, C_WORKSPACE); + old_workspace = swayc_parent_by_type(current_container, C_WORKSPACE); } - old_output = container_parent(current_container, C_OUTPUT); + old_output = swayc_parent_by_type(current_container, C_OUTPUT); } for (int i = 0; i < argc; ++i) { @@ -57,7 +57,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (config->reading || !config->active) { return cmd_results_new(CMD_DEFER, "workspace", NULL); } - struct sway_container *ws = NULL; + swayc_t *ws = NULL; if (strcasecmp(argv[0], "number") == 0) { if (!(ws = workspace_by_number(argv[1]))) { char *name = join_args(argv + 1, argc - 1); @@ -92,7 +92,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { workspace_switch(ws); current_container = sway_seat_get_focus(config->handler_context.seat); - struct sway_container *new_output = container_parent(current_container, C_OUTPUT); + swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); if (config->mouse_warping && old_output != new_output) { // TODO: Warp mouse diff --git a/sway/config.c b/sway/config.c index 0b29735a..213e7680 100644 --- a/sway/config.c +++ b/sway/config.c @@ -24,7 +24,7 @@ #include "sway/input/seat.h" #include "sway/commands.h" #include "sway/config.h" -#include "sway/tree/layout.h" +#include "sway/layout.h" #include "readline.h" #include "stringop.h" #include "list.h" diff --git a/sway/config/output.c b/sway/config/output.c index 7fc79739..9e211861 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -120,14 +120,14 @@ void terminate_swaybg(pid_t pid) { } } -void apply_output_config(struct output_config *oc, struct sway_container *output) { +void apply_output_config(struct output_config *oc, swayc_t *output) { assert(output->type == C_OUTPUT); struct wlr_output *wlr_output = output->sway_output->wlr_output; if (oc && oc->enabled == 0) { wlr_output_layout_remove(root_container.sway_root->output_layout, wlr_output); - container_output_destroy(output); + destroy_output(output); return; } diff --git a/sway/criteria.c b/sway/criteria.c index 247f6b75..2eee331c 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -4,9 +4,9 @@ #include #include #include "sway/criteria.h" -#include "sway/tree/container.h" +#include "sway/container.h" #include "sway/config.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "stringop.h" #include "list.h" #include "log.h" @@ -272,7 +272,7 @@ static int regex_cmp(const char *item, const pcre *regex) { } // test a single view if it matches list of criteria tokens (all of them). -static bool criteria_test(struct sway_container *cont, list_t *tokens) { +static bool criteria_test(swayc_t *cont, list_t *tokens) { if (cont->type != C_VIEW) { return false; } @@ -398,7 +398,7 @@ void free_criteria(struct criteria *crit) { free(crit); } -bool criteria_any(struct sway_container *cont, list_t *criteria) { +bool criteria_any(swayc_t *cont, list_t *criteria) { for (int i = 0; i < criteria->length; i++) { struct criteria *bc = criteria->items[i]; if (criteria_test(cont, bc->tokens)) { @@ -408,7 +408,7 @@ bool criteria_any(struct sway_container *cont, list_t *criteria) { return false; } -list_t *criteria_for(struct sway_container *cont) { +list_t *criteria_for(swayc_t *cont) { list_t *criteria = config->criteria, *matches = create_list(); for (int i = 0; i < criteria->length; i++) { struct criteria *bc = criteria->items[i]; @@ -424,7 +424,7 @@ struct list_tokens { list_t *tokens; }; -static void container_match_add(struct sway_container *container, +static void container_match_add(swayc_t *container, struct list_tokens *list_tokens) { if (criteria_test(container, list_tokens->tokens)) { list_add(list_tokens->list, container); @@ -435,8 +435,8 @@ list_t *container_for_crit_tokens(list_t *tokens) { struct list_tokens list_tokens = (struct list_tokens){create_list(), tokens}; - container_for_each_descendent(&root_container, - (void (*)(struct sway_container *, void *))container_match_add, + container_map(&root_container, + (void (*)(swayc_t *, void *))container_match_add, &list_tokens); // TODO look in the scratchpad diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 137b3260..bd62f84a 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -7,7 +7,7 @@ #include #include #include "sway/layers.h" -#include "sway/tree/layout.h" +#include "sway/layout.h" #include "sway/output.h" #include "sway/server.h" diff --git a/sway/desktop/output.c b/sway/desktop/output.c index ba778f4c..b8253ace 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -11,14 +11,14 @@ #include #include #include "log.h" -#include "sway/tree/container.h" +#include "sway/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/layers.h" -#include "sway/tree/layout.h" +#include "sway/layout.h" #include "sway/output.h" #include "sway/server.h" -#include "sway/tree/view.h" +#include "sway/view.h" /** * Rotate a child's position relative to a parent. The parent size is (pw, ph), @@ -145,7 +145,7 @@ struct render_data { struct timespec *now; }; -static void output_frame_view(struct sway_container *view, void *data) { +static void output_frame_view(swayc_t *view, void *data) { struct render_data *rdata = data; struct sway_output *output = rdata->output; struct timespec *now = rdata->now; @@ -219,16 +219,16 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); - struct sway_container *workspace = (focus->type == C_WORKSPACE ? + swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); + swayc_t *workspace = (focus->type == C_WORKSPACE ? focus : - container_parent(focus, C_WORKSPACE)); + swayc_parent_by_type(focus, C_WORKSPACE)); struct render_data rdata = { .output = soutput, .now = &now, }; - container_descendents(workspace, C_VIEW, output_frame_view, &rdata); + swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, &rdata); // render unmanaged views on top struct sway_view *view; @@ -259,7 +259,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); - container_output_destroy(output->swayc); + destroy_output(output->swayc); } static void handle_output_mode(struct wl_listener *listener, void *data) { @@ -287,7 +287,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { wlr_output_set_mode(wlr_output, mode); } - output->swayc = container_output_create(output); + output->swayc = new_output(output); if (!output->swayc) { free(output); return; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 4d4d1ed7..0356aa81 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/tree/container.h" -#include "sway/tree/layout.h" +#include "sway/container.h" +#include "sway/layout.h" #include "sway/server.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" #include "log.h" @@ -74,7 +74,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_surface, destroy); wl_list_remove(&sway_surface->commit.link); wl_list_remove(&sway_surface->destroy.link); - struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); + swayc_t *parent = destroy_view(sway_surface->view->swayc); free(sway_surface->view); free(sway_surface); arrange_windows(parent, -1, -1); @@ -132,8 +132,8 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); - struct sway_container *cont = container_view_create(focus, sway_view); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + swayc_t *cont = new_view(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 25c0cbca..18e7d399 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/tree/container.h" -#include "sway/tree/layout.h" +#include "sway/container.h" +#include "sway/layout.h" #include "sway/server.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" #include "log.h" @@ -83,7 +83,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_xdg_surface, destroy); wl_list_remove(&sway_xdg_surface->commit.link); wl_list_remove(&sway_xdg_surface->destroy.link); - struct sway_container *parent = container_view_destroy(sway_xdg_surface->view->swayc); + swayc_t *parent = destroy_view(sway_xdg_surface->view->swayc); free(sway_xdg_surface->view); free(sway_xdg_surface); arrange_windows(parent, -1, -1); @@ -137,8 +137,8 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); - struct sway_container *cont = container_view_create(focus, sway_view); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + swayc_t *cont = new_view(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index fd0bcaca..f9b5242b 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -5,10 +5,10 @@ #include #include #include -#include "sway/tree/container.h" -#include "sway/tree/layout.h" +#include "sway/container.h" +#include "sway/layout.h" #include "sway/server.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "sway/output.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" @@ -49,11 +49,11 @@ static void set_position(struct sway_view *view, double ox, double oy) { if (!assert_xwayland(view)) { return; } - struct sway_container *output = container_parent(view->swayc, C_OUTPUT); + swayc_t *output = swayc_parent_by_type(view->swayc, C_OUTPUT); if (!sway_assert(output, "view must be within tree to set position")) { return; } - struct sway_container *root = container_parent(output, C_ROOT); + swayc_t *root = swayc_parent_by_type(output, C_ROOT); if (!sway_assert(root, "output must be within tree to set position")) { return; } @@ -114,7 +114,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } } - struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); + swayc_t *parent = destroy_view(sway_surface->view->swayc); if (parent) { arrange_windows(parent, -1, -1); } @@ -132,7 +132,7 @@ static void handle_unmap_notify(struct wl_listener *listener, void *data) { } // take it out of the tree - struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); + swayc_t *parent = destroy_view(sway_surface->view->swayc); if (parent) { arrange_windows(parent, -1, -1); } @@ -155,12 +155,12 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { &sway_surface->view->unmanaged_view_link); } else { struct sway_view *view = sway_surface->view; - container_view_destroy(view->swayc); + destroy_view(view->swayc); - struct sway_container *parent = root_container.children->items[0]; + swayc_t *parent = root_container.children->items[0]; parent = parent->children->items[0]; // workspace - struct sway_container *cont = container_view_create(parent, view); + swayc_t *cont = new_view(parent, view); view->swayc = cont; arrange_windows(cont->parent, -1, -1); @@ -238,8 +238,8 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { } struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); - struct sway_container *cont = container_view_create(focus, sway_view); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + swayc_t *cont = new_view(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d57ac3e3..8a0d1df5 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -7,7 +7,7 @@ #include #include #include "sway/input/cursor.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "list.h" #include "log.h" @@ -49,8 +49,8 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, } } - struct sway_container *swayc = - container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + swayc_t *swayc = + swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); if (swayc) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); @@ -87,8 +87,8 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { if (event->button == BTN_LEFT) { struct wlr_surface *surface = NULL; double sx, sy; - struct sway_container *swayc = - container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + swayc_t *swayc = + swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); sway_seat_set_focus(cursor->seat, swayc); } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index d421a03f..27c2c72e 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -278,7 +278,7 @@ struct sway_input_manager *sway_input_manager_create( } bool sway_input_manager_has_focus(struct sway_input_manager *input, - struct sway_container *container) { + swayc_t *container) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { if (sway_seat_get_focus(seat) == container) { @@ -290,7 +290,7 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, } void sway_input_manager_set_focus(struct sway_input_manager *input, - struct sway_container *container) { + swayc_t *container) { struct sway_seat *seat ; wl_list_for_each(seat, &input->seats, link) { sway_seat_set_focus(seat, container); diff --git a/sway/input/seat.c b/sway/input/seat.c index 76d29b52..648e7914 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,13 +1,13 @@ #define _XOPEN_SOURCE 700 #include #include -#include "sway/tree/container.h" +#include "sway/container.h" #include "sway/input/seat.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" #include "sway/output.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "log.h" static void seat_device_destroy(struct sway_seat_device *seat_device) { @@ -37,7 +37,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, struct sway_seat_container *seat_con = wl_container_of(listener, seat_con, destroy); struct sway_seat *seat = seat_con->seat; - struct sway_container *con = seat_con->container; + swayc_t *con = seat_con->container; bool is_focus = (sway_seat_get_focus(seat) == con); @@ -46,7 +46,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, if (is_focus) { // pick next focus sway_seat_set_focus(seat, NULL); - struct sway_container *next = sway_seat_get_focus_inactive(seat, con->parent); + swayc_t *next = sway_seat_get_focus_inactive(seat, con->parent); if (next == NULL) { next = con->parent; } @@ -59,7 +59,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, } static struct sway_seat_container *seat_container_from_container( - struct sway_seat *seat, struct sway_container *con) { + struct sway_seat *seat, swayc_t *con) { if (con->type < C_WORKSPACE) { // these don't get seat containers ever return NULL; @@ -89,11 +89,11 @@ static struct sway_seat_container *seat_container_from_container( static void handle_new_container(struct wl_listener *listener, void *data) { struct sway_seat *seat = wl_container_of(listener, seat, new_container); - struct sway_container *con = data; + swayc_t *con = data; seat_container_from_container(seat, con); } -static void collect_focus_iter(struct sway_container *con, void *data) { +static void collect_focus_iter(swayc_t *con, void *data) { struct sway_seat *seat = data; if (con->type > C_WORKSPACE) { return; @@ -130,7 +130,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, // init the focus stack wl_list_init(&seat->focus_stack); - container_for_each_descendent(&root_container, collect_focus_iter, seat); + container_for_each_bfs(&root_container, collect_focus_iter, seat); wl_signal_add(&root_container.sway_root->events.new_container, &seat->new_container); @@ -166,7 +166,7 @@ static void seat_configure_keyboard(struct sway_seat *seat, sway_keyboard_configure(seat_device->keyboard); wlr_seat_set_keyboard(seat->wlr_seat, seat_device->input_device->wlr_device); - struct sway_container *focus = sway_seat_get_focus(seat); + swayc_t *focus = sway_seat_get_focus(seat); if (focus && focus->type == C_VIEW) { // force notify reenter to pick up the new configuration wlr_seat_keyboard_clear_focus(seat->wlr_seat); @@ -270,7 +270,7 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { } for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *output_container = root_container.children->items[i]; + swayc_t *output_container = root_container.children->items[i]; struct wlr_output *output = output_container->sway_output->wlr_output; bool result = @@ -289,8 +289,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container) { - struct sway_container *last_focus = sway_seat_get_focus(seat); +void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { + swayc_t *last_focus = sway_seat_get_focus(seat); if (container && last_focus == container) { return; @@ -330,9 +330,9 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe seat->has_focus = (container != NULL); } -struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { +swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container) { struct sway_seat_container *current = NULL; - struct sway_container *parent = NULL; + swayc_t *parent = NULL; wl_list_for_each(current, &seat->focus_stack, link) { parent = current->container->parent; @@ -351,21 +351,21 @@ struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, stru return NULL; } -struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { +swayc_t *sway_seat_get_focus(struct sway_seat *seat) { if (!seat->has_focus) { return NULL; } return sway_seat_get_focus_inactive(seat, &root_container); } -struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, - enum sway_container_type type) { - struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); +swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, + enum swayc_types type) { + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); if (focus->type == type) { return focus; } - return container_parent(focus, type); + return swayc_parent_by_type(focus, type); } void sway_seat_set_config(struct sway_seat *seat, diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 7caa2457..977f1ecb 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -3,7 +3,7 @@ #include #include "log.h" #include "sway/ipc-json.h" -#include "sway/tree/container.h" +#include "sway/container.h" #include "sway/output.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -25,7 +25,7 @@ json_object *ipc_json_get_version() { return version; } -static json_object *ipc_json_create_rect(struct sway_container *c) { +static json_object *ipc_json_create_rect(swayc_t *c) { json_object *rect = json_object_new_object(); json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); @@ -36,7 +36,7 @@ static json_object *ipc_json_create_rect(struct sway_container *c) { return rect; } -static void ipc_json_describe_root(struct sway_container *root, json_object *object) { +static void ipc_json_describe_root(swayc_t *root, json_object *object) { json_object_object_add(object, "type", json_object_new_string("root")); json_object_object_add(object, "layout", json_object_new_string("splith")); } @@ -63,7 +63,7 @@ static const char *ipc_json_get_output_transform(enum wl_output_transform transf return NULL; } -static void ipc_json_describe_output(struct sway_container *container, json_object *object) { +static void ipc_json_describe_output(swayc_t *container, json_object *object) { struct wlr_output *wlr_output = container->sway_output->wlr_output; json_object_object_add(object, "type", json_object_new_string("output")); json_object_object_add(object, "active", json_object_new_boolean(true)); @@ -94,7 +94,7 @@ static void ipc_json_describe_output(struct sway_container *container, json_obje json_object_object_add(object, "modes", modes_array); } -static void ipc_json_describe_workspace(struct sway_container *workspace, json_object *object) { +static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; json_object_object_add(object, "num", json_object_new_int(num)); @@ -102,11 +102,11 @@ static void ipc_json_describe_workspace(struct sway_container *workspace, json_o json_object_object_add(object, "type", json_object_new_string("workspace")); } -static void ipc_json_describe_view(struct sway_container *c, json_object *object) { +static void ipc_json_describe_view(swayc_t *c, json_object *object) { json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); } -json_object *ipc_json_describe_container(struct sway_container *c) { +json_object *ipc_json_describe_container(swayc_t *c) { if (!(sway_assert(c, "Container must not be null."))) { return NULL; } @@ -147,7 +147,7 @@ json_object *ipc_json_describe_container(struct sway_container *c) { return object; } -json_object *ipc_json_describe_container_recursive(struct sway_container *c) { +json_object *ipc_json_describe_container_recursive(swayc_t *c) { json_object *object = ipc_json_describe_container(c); int i; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 50d0bcf3..156de380 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -279,7 +279,7 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) } } -void ipc_event_window(struct sway_container *window, const char *change) { +void ipc_event_window(swayc_t *window, const char *change) { wlr_log(L_DEBUG, "Sending window::%s event", change); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(change)); @@ -400,7 +400,7 @@ void ipc_client_handle_command(struct ipc_client *client) { { json_object *outputs = json_object_new_array(); for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *container = root_container.children->items[i]; + swayc_t *container = root_container.children->items[i]; if (container->type == C_OUTPUT) { json_object_array_add(outputs, ipc_json_describe_container(container)); diff --git a/sway/main.c b/sway/main.c index ded922ee..f2f24be3 100644 --- a/sway/main.c +++ b/sway/main.c @@ -18,7 +18,7 @@ #include #include "sway/config.h" #include "sway/server.h" -#include "sway/tree/layout.h" +#include "sway/layout.h" #include "sway/ipc-server.h" #include "ipc-client.h" #include "readline.h" @@ -382,7 +382,7 @@ int main(int argc, char **argv) { wlr_log(L_INFO, "Starting sway version " SWAY_VERSION); - layout_init(); + init_layout(); if (!server_init(&server)) { return 1; diff --git a/sway/tree/container.c b/sway/tree/container.c index 40047dcf..bbafe9ec 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -7,14 +7,14 @@ #include #include #include "sway/config.h" -#include "sway/tree/container.h" +#include "sway/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/tree/layout.h" +#include "sway/layout.h" #include "sway/output.h" #include "sway/server.h" -#include "sway/tree/view.h" -#include "sway/tree/workspace.h" +#include "sway/view.h" +#include "sway/workspace.h" #include "sway/ipc-server.h" #include "log.h" @@ -33,15 +33,48 @@ static list_t *get_bfs_queue() { return bfs_queue; } -static void notify_new_container(struct sway_container *container) { +static void notify_new_container(swayc_t *container) { wl_signal_emit(&root_container.sway_root->events.new_container, container); ipc_event_window(container, "new"); } -static struct sway_container *container_create(enum sway_container_type type) { +swayc_t *swayc_by_test(swayc_t *container, + bool (*test)(swayc_t *view, void *data), void *data) { + if (!container->children) { + return NULL; + } + // TODO: floating windows + for (int i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; + if (test(child, data)) { + return child; + } else { + swayc_t *res = swayc_by_test(child, test, data); + if (res) { + return res; + } + } + } + return NULL; +} + +void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, + void (*func)(swayc_t *item, void *data), void *data) { + for (int i = 0; i < root->children->length; ++i) { + swayc_t *item = root->children->items[i]; + if (item->type == type) { + func(item, data); + } + if (item->children && item->children->length) { + swayc_descendants_of_type(item, type, func, data); + } + } +} + +static swayc_t *new_swayc(enum swayc_types type) { // next id starts at 1 because 0 is assigned to root_container in layout.c static size_t next_id = 1; - struct sway_container *c = calloc(1, sizeof(struct sway_container)); + swayc_t *c = calloc(1, sizeof(swayc_t)); if (!c) { return NULL; } @@ -49,6 +82,8 @@ static struct sway_container *container_create(enum sway_container_type type) { c->layout = L_NONE; c->workspace_layout = L_NONE; c->type = type; + c->nb_master = 1; + c->nb_slave_groups = 1; if (type != C_VIEW) { c->children = create_list(); } @@ -58,18 +93,18 @@ static struct sway_container *container_create(enum sway_container_type type) { return c; } -static void container_destroy(struct sway_container *cont) { - if (cont == NULL) { +static void free_swayc(swayc_t *cont) { + if (!sway_assert(cont, "free_swayc passed NULL")) { return; } wl_signal_emit(&cont->events.destroy, cont); if (cont->children) { - // remove children until there are no more, container_destroy calls - // container_remove_child, which removes child from this container + // remove children until there are no more, free_swayc calls + // remove_child, which removes child from this container while (cont->children->length) { - container_destroy(cont->children->items[0]); + free_swayc(cont->children->items[0]); } list_free(cont->children); } @@ -78,7 +113,7 @@ static void container_destroy(struct sway_container *cont) { list_free(cont->marks); } if (cont->parent) { - container_remove_child(cont); + remove_child(cont); } if (cont->name) { free(cont->name); @@ -86,8 +121,7 @@ static void container_destroy(struct sway_container *cont) { free(cont); } -struct sway_container *container_output_create( - struct sway_output *sway_output) { +swayc_t *new_output(struct sway_output *sway_output) { struct wlr_box size; wlr_output_effective_resolution(sway_output->wlr_output, &size.width, &size.height); @@ -122,22 +156,22 @@ struct sway_container *container_output_create( return NULL; } - struct sway_container *output = container_create(C_OUTPUT); + swayc_t *output = new_swayc(C_OUTPUT); output->sway_output = sway_output; output->name = strdup(name); if (output->name == NULL) { - container_destroy(output); + free_swayc(output); return NULL; } apply_output_config(oc, output); - container_add_child(&root_container, output); + add_child(&root_container, output); // Create workspace char *ws_name = workspace_next_name(output->name); wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); - struct sway_container *ws = container_workspace_create(output, ws_name); + swayc_t *ws = new_workspace(output, ws_name); // Set each seat's focus if not already set struct sway_seat *seat = NULL; wl_list_for_each(seat, &input_manager->seats, link) { @@ -151,14 +185,12 @@ struct sway_container *container_output_create( return output; } -struct sway_container *container_workspace_create( - struct sway_container *output, const char *name) { - if (!sway_assert(output, - "container_workspace_create called with null output")) { +swayc_t *new_workspace(swayc_t *output, const char *name) { + if (!sway_assert(output, "new_workspace called with null output")) { return NULL; } wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); - struct sway_container *workspace = container_create(C_WORKSPACE); + swayc_t *workspace = new_swayc(C_WORKSPACE); workspace->x = output->x; workspace->y = output->y; @@ -166,23 +198,21 @@ struct sway_container *container_workspace_create( workspace->height = output->height; workspace->name = !name ? NULL : strdup(name); workspace->prev_layout = L_NONE; - workspace->layout = container_get_default_layout(output); - workspace->workspace_layout = container_get_default_layout(output); + workspace->layout = default_layout(output); + workspace->workspace_layout = default_layout(output); - container_add_child(output, workspace); - container_sort_workspaces(output); + add_child(output, workspace); + sort_workspaces(output); notify_new_container(workspace); return workspace; } -struct sway_container *container_view_create(struct sway_container *sibling, - struct sway_view *sway_view) { - if (!sway_assert(sibling, - "container_view_create called with NULL sibling/parent")) { +swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { + if (!sway_assert(sibling, "new_view called with NULL sibling/parent")) { return NULL; } const char *title = view_get_title(sway_view); - struct sway_container *swayc = container_create(C_VIEW); + swayc_t *swayc = new_swayc(C_VIEW); wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d %s", swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); // Setup values @@ -193,18 +223,17 @@ struct sway_container *container_view_create(struct sway_container *sibling, if (sibling->type == C_WORKSPACE) { // Case of focused workspace, just create as child of it - container_add_child(sibling, swayc); + add_child(sibling, swayc); } else { // Regular case, create as sibling of current container - container_add_sibling(sibling, swayc); + add_sibling(sibling, swayc); } notify_new_container(swayc); return swayc; } -struct sway_container *container_output_destroy(struct sway_container *output) { - if (!sway_assert(output, - "null output passed to container_output_destroy")) { +swayc_t *destroy_output(swayc_t *output) { + if (!sway_assert(output, "null output passed to destroy_output")) { return NULL; } @@ -216,13 +245,12 @@ struct sway_container *container_output_destroy(struct sway_container *output) { int p = root_container.children->items[0] == output; // Move workspace from this output to another output while (output->children->length) { - struct sway_container *child = output->children->items[0]; - container_remove_child(child); - container_add_child(root_container.children->items[p], child); + swayc_t *child = output->children->items[0]; + remove_child(child); + add_child(root_container.children->items[p], child); } - container_sort_workspaces(root_container.children->items[p]); - arrange_windows(root_container.children->items[p], - -1, -1); + sort_workspaces(root_container.children->items[p]); + arrange_windows(root_container.children->items[p], -1, -1); } } @@ -231,18 +259,18 @@ struct sway_container *container_output_destroy(struct sway_container *output) { wl_list_remove(&output->sway_output->mode.link); wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); - container_destroy(output); + free_swayc(output); return &root_container; } -struct sway_container *container_view_destroy(struct sway_container *view) { +swayc_t *destroy_view(swayc_t *view) { if (!view) { return NULL; } wlr_log(L_DEBUG, "Destroying view '%s'", view->name); - struct sway_container *parent = view->parent; - container_destroy(view); + swayc_t *parent = view->parent; + free_swayc(view); // TODO WLR: Destroy empty containers /* @@ -253,55 +281,7 @@ struct sway_container *container_view_destroy(struct sway_container *view) { return parent; } -struct sway_container *container_set_layout(struct sway_container *container, - enum sway_container_layout layout) { - if (container->type == C_WORKSPACE) { - container->workspace_layout = layout; - if (layout == L_HORIZ || layout == L_VERT) { - container->layout = layout; - } - } else { - container->layout = layout; - } - return container; -} - -void container_descendents(struct sway_container *root, - enum sway_container_type type, - void (*func)(struct sway_container *item, void *data), void *data) { - for (int i = 0; i < root->children->length; ++i) { - struct sway_container *item = root->children->items[i]; - if (item->type == type) { - func(item, data); - } - if (item->children && item->children->length) { - container_descendents(item, type, func, data); - } - } -} - -struct sway_container *container_find(struct sway_container *container, - bool (*test)(struct sway_container *view, void *data), void *data) { - if (!container->children) { - return NULL; - } - // TODO: floating windows - for (int i = 0; i < container->children->length; ++i) { - struct sway_container *child = container->children->items[i]; - if (test(child, data)) { - return child; - } else { - struct sway_container *res = container_find(child, test, data); - if (res) { - return res; - } - } - } - return NULL; -} - -struct sway_container *container_parent(struct sway_container *container, - enum sway_container_type type) { +swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { if (!sway_assert(container, "container is NULL")) { return NULL; } @@ -314,8 +294,7 @@ struct sway_container *container_parent(struct sway_container *container, return container; } -struct sway_container *container_at(struct sway_container *parent, - double lx, double ly, +swayc_t *swayc_at(swayc_t *parent, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { list_t *queue = get_bfs_queue(); if (!queue) { @@ -324,13 +303,13 @@ struct sway_container *container_at(struct sway_container *parent, list_add(queue, parent); - struct sway_container *swayc = NULL; + swayc_t *swayc = NULL; while (queue->length) { swayc = queue->items[0]; list_del(queue, 0); if (swayc->type == C_VIEW) { struct sway_view *sview = swayc->sway_view; - struct sway_container *soutput = container_parent(swayc, C_OUTPUT); + swayc_t *soutput = swayc_parent_by_type(swayc, C_OUTPUT); struct wlr_box *output_box = wlr_output_layout_get_box( root_container.sway_root->output_layout, @@ -400,8 +379,30 @@ struct sway_container *container_at(struct sway_container *parent, return NULL; } -void container_for_each_descendent(struct sway_container *con, - void (*f)(struct sway_container *con, void *data), void *data) { +void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { + if (container) { + int i; + if (container->children) { + for (i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; + container_map(child, f, data); + } + } + // TODO + /* + if (container->floating) { + for (i = 0; i < container->floating->length; ++i) { + swayc_t *child = container->floating->items[i]; + container_map(child, f, data); + } + } + */ + f(container, data); + } +} + +void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), + void *data) { list_t *queue = get_bfs_queue(); if (!queue) { return; @@ -414,7 +415,7 @@ void container_for_each_descendent(struct sway_container *con, list_add(queue, con); - struct sway_container *current = NULL; + swayc_t *current = NULL; while (queue->length) { current = queue->items[0]; list_del(queue, 0); @@ -423,3 +424,15 @@ void container_for_each_descendent(struct sway_container *con, list_cat(queue, current->children); } } + +swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) { + if (container->type == C_WORKSPACE) { + container->workspace_layout = layout; + if (layout == L_HORIZ || layout == L_VERT) { + container->layout = layout; + } + } else { + container->layout = layout; + } + return container; +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index dc0ee5b4..de9e7b58 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -6,26 +6,24 @@ #include #include #include -#include "sway/tree/container.h" -#include "sway/tree/layout.h" +#include "sway/container.h" +#include "sway/layout.h" #include "sway/output.h" -#include "sway/tree/view.h" +#include "sway/view.h" #include "sway/input/seat.h" #include "list.h" #include "log.h" -struct sway_container root_container; +swayc_t root_container; -static void output_layout_change_notify(struct wl_listener *listener, - void *data) { +static void output_layout_change_notify(struct wl_listener *listener, void *data) { struct wlr_box *layout_box = wlr_output_layout_get_box( root_container.sway_root->output_layout, NULL); root_container.width = layout_box->width; root_container.height = layout_box->height; for (int i = 0 ; i < root_container.children->length; ++i) { - struct sway_container *output_container = - root_container.children->items[i]; + swayc_t *output_container = root_container.children->items[i]; if (output_container->type != C_OUTPUT) { continue; } @@ -45,7 +43,7 @@ static void output_layout_change_notify(struct wl_listener *listener, arrange_windows(&root_container, -1, -1); } -void layout_init(void) { +void init_layout(void) { root_container.id = 0; // normally assigned in new_swayc() root_container.type = C_ROOT; root_container.layout = L_NONE; @@ -64,9 +62,9 @@ void layout_init(void) { &root_container.sway_root->output_layout_change); } -static int index_child(const struct sway_container *child) { +static int index_child(const swayc_t *child) { // TODO handle floating - struct sway_container *parent = child->parent; + swayc_t *parent = child->parent; int i, len; len = parent->children->length; for (i = 0; i < len; ++i) { @@ -81,18 +79,16 @@ static int index_child(const struct sway_container *child) { return i; } -struct sway_container *container_add_sibling(struct sway_container *fixed, - struct sway_container *active) { +swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { // TODO handle floating - struct sway_container *parent = fixed->parent; + swayc_t *parent = fixed->parent; int i = index_child(fixed); list_insert(parent->children, i + 1, active); active->parent = parent; return active->parent; } -void container_add_child(struct sway_container *parent, - struct sway_container *child) { +void add_child(swayc_t *parent, swayc_t *child) { wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", child, child->type, child->width, child->height, parent, parent->type, parent->width, parent->height); @@ -100,17 +96,15 @@ void container_add_child(struct sway_container *parent, child->parent = parent; // set focus for this container /* TODO WLR - if (parent->type == C_WORKSPACE && child->type == C_VIEW && - (parent->workspace_layout == L_TABBED || parent->workspace_layout == - L_STACKED)) { + if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) { child = new_container(child, parent->workspace_layout); } */ } -struct sway_container *container_remove_child(struct sway_container *child) { +swayc_t *remove_child(swayc_t *child) { int i; - struct sway_container *parent = child->parent; + swayc_t *parent = child->parent; for (i = 0; i < parent->children->length; ++i) { if (parent->children->items[i] == child) { list_del(parent->children, i); @@ -121,8 +115,7 @@ struct sway_container *container_remove_child(struct sway_container *child) { return parent; } -enum sway_container_layout container_get_default_layout( - struct sway_container *output) { +enum swayc_layouts default_layout(swayc_t *output) { /* TODO WLR if (config->default_layout != L_NONE) { //return config->default_layout; @@ -136,8 +129,8 @@ enum sway_container_layout container_get_default_layout( } static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { - struct sway_container *a = *(void **)_a; - struct sway_container *b = *(void **)_b; + swayc_t *a = *(void **)_a; + swayc_t *b = *(void **)_b; int retval = 0; if (isdigit(a->name[0]) && isdigit(b->name[0])) { @@ -153,22 +146,21 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { return retval; } -void container_sort_workspaces(struct sway_container *output) { +void sort_workspaces(swayc_t *output) { list_stable_sort(output->children, sort_workspace_cmp_qsort); } -static void apply_horiz_layout(struct sway_container *container, const double x, +static void apply_horiz_layout(swayc_t *container, const double x, const double y, const double width, const double height, const int start, const int end); -static void apply_vert_layout(struct sway_container *container, const double x, +static void apply_vert_layout(swayc_t *container, const double x, const double y, const double width, const double height, const int start, const int end); -void arrange_windows(struct sway_container *container, - double width, double height) { +void arrange_windows(swayc_t *container, double width, double height) { int i; if (width == -1 || height == -1) { width = container->width; @@ -189,7 +181,7 @@ void arrange_windows(struct sway_container *container, case C_ROOT: // TODO: wlr_output_layout probably for (i = 0; i < container->children->length; ++i) { - struct sway_container *output = container->children->items[i]; + swayc_t *output = container->children->items[i]; wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); arrange_windows(output, -1, -1); @@ -205,14 +197,13 @@ void arrange_windows(struct sway_container *container, } // arrange all workspaces: for (i = 0; i < container->children->length; ++i) { - struct sway_container *child = container->children->items[i]; + swayc_t *child = container->children->items[i]; arrange_windows(child, -1, -1); } return; case C_WORKSPACE: { - struct sway_container *output = - container_parent(container, C_OUTPUT); + swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); struct wlr_box *area = &output->sway_output->usable_area; wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", area->width, area->height, area->x, area->y); @@ -261,15 +252,14 @@ void arrange_windows(struct sway_container *container, } } -static void apply_horiz_layout(struct sway_container *container, +static void apply_horiz_layout(swayc_t *container, const double x, const double y, const double width, const double height, const int start, const int end) { double scale = 0; // Calculate total width for (int i = start; i < end; ++i) { - double *old_width = - &((struct sway_container *)container->children->items[i])->width; + double *old_width = &((swayc_t *)container->children->items[i])->width; if (*old_width <= 0) { if (end - start > 1) { *old_width = width / (end - start - 1); @@ -286,7 +276,7 @@ static void apply_horiz_layout(struct sway_container *container, if (scale > 0.1) { wlr_log(L_DEBUG, "Arranging %p horizontally", container); for (int i = start; i < end; ++i) { - struct sway_container *child = container->children->items[i]; + swayc_t *child = container->children->items[i]; wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); @@ -311,7 +301,7 @@ static void apply_horiz_layout(struct sway_container *container, } } -void apply_vert_layout(struct sway_container *container, +void apply_vert_layout(swayc_t *container, const double x, const double y, const double width, const double height, const int start, const int end) { @@ -319,8 +309,7 @@ void apply_vert_layout(struct sway_container *container, double scale = 0; // Calculate total height for (i = start; i < end; ++i) { - double *old_height = - &((struct sway_container *)container->children->items[i])->height; + double *old_height = &((swayc_t *)container->children->items[i])->height; if (*old_height <= 0) { if (end - start > 1) { *old_height = height / (end - start - 1); @@ -337,7 +326,7 @@ void apply_vert_layout(struct sway_container *container, if (scale > 0.1) { wlr_log(L_DEBUG, "Arranging %p vertically", container); for (i = start; i < end; ++i) { - struct sway_container *child = container->children->items[i]; + swayc_t *child = container->children->items[i]; wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); @@ -365,16 +354,15 @@ void apply_vert_layout(struct sway_container *container, /** * Get swayc in the direction of newly entered output. */ -static struct sway_container *get_swayc_in_output_direction( - struct sway_container *output, enum movement_direction dir, - struct sway_seat *seat) { +static swayc_t *get_swayc_in_output_direction(swayc_t *output, + enum movement_direction dir, struct sway_seat *seat) { if (!output) { return NULL; } - struct sway_container *ws = sway_seat_get_focus_inactive(seat, output); + swayc_t *ws = sway_seat_get_focus_inactive(seat, output); if (ws->type != C_WORKSPACE) { - ws = container_parent(ws, C_WORKSPACE); + ws = swayc_parent_by_type(ws, C_WORKSPACE); } if (ws == NULL) { @@ -392,15 +380,13 @@ static struct sway_container *get_swayc_in_output_direction( return ws->children->items[0]; case MOVE_UP: case MOVE_DOWN: { - struct sway_container *focused = - sway_seat_get_focus_inactive(seat, ws); + swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); if (focused && focused->parent) { - struct sway_container *parent = focused->parent; + swayc_t *parent = focused->parent; if (parent->layout == L_VERT) { if (dir == MOVE_UP) { // get child furthest down on new output - int idx = parent->children->length - 1; - return parent->children->items[idx]; + return parent->children->items[parent->children->length-1]; } else if (dir == MOVE_DOWN) { // get child furthest up on new output return parent->children->items[0]; @@ -418,14 +404,13 @@ static struct sway_container *get_swayc_in_output_direction( return ws; } -static void get_layout_center_position(struct sway_container *container, - int *x, int *y) { +static void get_layout_center_position(swayc_t *container, int *x, int *y) { // FIXME view coords are inconsistently referred to in layout/output systems if (container->type == C_OUTPUT) { *x = container->x + container->width/2; *y = container->y + container->height/2; } else { - struct sway_container *output = container_parent(container, C_OUTPUT); + swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); if (container->type == C_WORKSPACE) { // Workspace coordinates are actually wrong/arbitrary, but should // be same as output. @@ -438,8 +423,7 @@ static void get_layout_center_position(struct sway_container *container, } } -static bool sway_dir_to_wlr(enum movement_direction dir, - enum wlr_direction *out) { +static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) { switch (dir) { case MOVE_UP: *out = WLR_DIRECTION_UP; @@ -460,12 +444,12 @@ static bool sway_dir_to_wlr(enum movement_direction dir, return true; } -static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { +static swayc_t *sway_output_from_wlr(struct wlr_output *output) { if (output == NULL) { return NULL; } for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *o = root_container.children->items[i]; + swayc_t *o = root_container.children->items[i]; if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) { return o; } @@ -473,14 +457,13 @@ static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { return NULL; } -static struct sway_container *get_swayc_in_direction_under( - struct sway_container *container, enum movement_direction dir, - struct sway_seat *seat, struct sway_container *limit) { +static swayc_t *get_swayc_in_direction_under(swayc_t *container, + enum movement_direction dir, struct sway_seat *seat, swayc_t *limit) { if (dir == MOVE_CHILD) { return sway_seat_get_focus_inactive(seat, container); } - struct sway_container *parent = container->parent; + swayc_t *parent = container->parent; if (dir == MOVE_PARENT) { if (parent->type == C_OUTPUT) { return NULL; @@ -513,10 +496,9 @@ static struct sway_container *get_swayc_in_direction_under( /* if (container->type == C_VIEW && swayc_is_fullscreen(container)) { wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); - container = container_parent(container, C_OUTPUT); + container = swayc_parent_by_type(container, C_OUTPUT); get_layout_center_position(container, &abs_pos); - struct sway_container *output = - swayc_adjacent_output(container, dir, &abs_pos, true); + swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); return get_swayc_in_output_direction(output, dir); } if (container->type == C_WORKSPACE && container->fullscreen) { @@ -525,7 +507,7 @@ static struct sway_container *get_swayc_in_direction_under( } */ - struct sway_container *wrap_candidate = NULL; + swayc_t *wrap_candidate = NULL; while (true) { // Test if we can even make a difference here bool can_move = false; @@ -539,19 +521,16 @@ static struct sway_container *get_swayc_in_direction_under( } int lx, ly; get_layout_center_position(container, &lx, &ly); - struct wlr_output_layout *layout = - root_container.sway_root->output_layout; + struct wlr_output_layout *layout = root_container.sway_root->output_layout; struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output(layout, wlr_dir, container->sway_output->wlr_output, lx, ly); - struct sway_container *adjacent = - sway_output_from_wlr(wlr_adjacent); + swayc_t *adjacent = sway_output_from_wlr(wlr_adjacent); if (!adjacent || adjacent == container) { return wrap_candidate; } - struct sway_container *next = - get_swayc_in_output_direction(adjacent, dir, seat); + swayc_t *next = get_swayc_in_output_direction(adjacent, dir, seat); if (next == NULL) { return NULL; } @@ -591,9 +570,8 @@ static struct sway_container *get_swayc_in_direction_under( } } } else { - wlr_log(L_DEBUG, - "cont %d-%p dir %i sibling %d: %p", idx, - container, dir, desired, parent->children->items[desired]); + wlr_log(L_DEBUG, "%s cont %d-%p dir %i sibling %d: %p", __func__, + idx, container, dir, desired, parent->children->items[desired]); return parent->children->items[desired]; } } @@ -609,8 +587,7 @@ static struct sway_container *get_swayc_in_direction_under( } } -struct sway_container *container_get_in_direction( - struct sway_container *container, struct sway_seat *seat, +swayc_t *get_swayc_in_direction(swayc_t *container, struct sway_seat *seat, enum movement_direction dir) { return get_swayc_in_direction_under(container, dir, seat, NULL); } diff --git a/sway/tree/view.c b/sway/tree/view.c index d5325c31..9499adca 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,8 +1,8 @@ #include #include -#include "sway/tree/container.h" -#include "sway/tree/layout.h" -#include "sway/tree/view.h" +#include "sway/container.h" +#include "sway/layout.h" +#include "sway/view.h" const char *view_get_title(struct sway_view *view) { if (view->iface.get_prop) { @@ -45,7 +45,6 @@ void view_set_size(struct sway_view *view, int width, int height) { } } -// TODO make view coordinates in layout coordinates void view_set_position(struct sway_view *view, double ox, double oy) { if (view->iface.set_position) { struct wlr_box box = { diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index ba04c55c..861fda4d 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/tree/container.h" +#include "sway/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/tree/workspace.h" +#include "sway/workspace.h" #include "log.h" #include "util.h" @@ -17,7 +17,7 @@ struct workspace_by_number_data { const char *name; }; -void next_name_map(struct sway_container *ws, void *data) { +void next_name_map(swayc_t *ws, void *data) { int *count = data; ++count; } @@ -37,7 +37,7 @@ char *workspace_next_name(const char *output_name) { return name; } -static bool _workspace_by_number(struct sway_container *view, void *data) { +static bool _workspace_by_number(swayc_t *view, void *data) { if (view->type != C_WORKSPACE) { return false; } @@ -46,28 +46,27 @@ static bool _workspace_by_number(struct sway_container *view, void *data) { return a == wbnd->len && strncmp(view->name, wbnd->name, a) == 0; } -struct sway_container *workspace_by_number(const char* name) { +swayc_t *workspace_by_number(const char* name) { struct workspace_by_number_data wbnd = {0, "1234567890", name}; wbnd.len = strspn(name, wbnd.cset); if (wbnd.len <= 0) { return NULL; } - return container_find(&root_container, - _workspace_by_number, (void *) &wbnd); + return swayc_by_test(&root_container, _workspace_by_number, (void *) &wbnd); } -static bool _workspace_by_name(struct sway_container *view, void *data) { +static bool _workspace_by_name(swayc_t *view, void *data) { return (view->type == C_WORKSPACE) && (strcasecmp(view->name, (char *) data) == 0); } -struct sway_container *workspace_by_name(const char *name) { +swayc_t *workspace_by_name(const char *name) { struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *current_workspace = NULL, *current_output = NULL; - struct sway_container *focus = sway_seat_get_focus(seat); + swayc_t *current_workspace = NULL, *current_output = NULL; + swayc_t *focus = sway_seat_get_focus(seat); if (focus) { - current_workspace = container_parent(focus, C_WORKSPACE); - current_output = container_parent(focus, C_OUTPUT); + current_workspace = swayc_parent_by_type(focus, C_WORKSPACE); + current_output = swayc_parent_by_type(focus, C_OUTPUT); } if (strcmp(name, "prev") == 0) { return workspace_prev(current_workspace); @@ -80,13 +79,12 @@ struct sway_container *workspace_by_name(const char *name) { } else if (strcmp(name, "current") == 0) { return current_workspace; } else { - return container_find(&root_container, _workspace_by_name, - (void *)name); + return swayc_by_test(&root_container, _workspace_by_name, (void *) name); } } -struct sway_container *workspace_create(const char *name) { - struct sway_container *parent; +swayc_t *workspace_create(const char *name) { + swayc_t *parent; // Search for workspace<->output pair int i, e = config->workspace_outputs->length; for (i = 0; i < e; ++i) { @@ -97,7 +95,7 @@ struct sway_container *workspace_create(const char *name) { for (i = 0; i < e; ++i) { parent = root_container.children->items[i]; if (strcmp(parent->name, wso->output) == 0) { - return container_workspace_create(parent, name); + return new_workspace(parent, name); } } break; @@ -105,11 +103,10 @@ struct sway_container *workspace_create(const char *name) { } // Otherwise create a new one struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = - sway_seat_get_focus_inactive(seat, &root_container); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); parent = focus; - parent = container_parent(parent, C_OUTPUT); - return container_workspace_create(parent, name); + parent = swayc_parent_by_type(parent, C_OUTPUT); + return new_workspace(parent, name); } /** @@ -117,18 +114,17 @@ struct sway_container *workspace_create(const char *name) { * the end and beginning. If next is false, the previous workspace is returned, * otherwise the next one is returned. */ -struct sway_container *workspace_output_prev_next_impl( - struct sway_container *output, bool next) { +swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { if (!sway_assert(output->type == C_OUTPUT, "Argument must be an output, is %d", output->type)) { return NULL; } struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); - struct sway_container *workspace = (focus->type == C_WORKSPACE ? + swayc_t *focus = sway_seat_get_focus_inactive(seat, output); + swayc_t *workspace = (focus->type == C_WORKSPACE ? focus : - container_parent(focus, C_WORKSPACE)); + swayc_parent_by_type(focus, C_WORKSPACE)); int i; for (i = 0; i < output->children->length; i++) { @@ -138,8 +134,7 @@ struct sway_container *workspace_output_prev_next_impl( } } - // Doesn't happen, at worst the for loop returns the previously active - // workspace + // Doesn't happen, at worst the for loop returns the previously active workspace return NULL; } @@ -149,14 +144,13 @@ struct sway_container *workspace_output_prev_next_impl( * next is false, the previous workspace is returned, otherwise the next one is * returned. */ -struct sway_container *workspace_prev_next_impl( - struct sway_container *workspace, bool next) { +swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) { if (!sway_assert(workspace->type == C_WORKSPACE, "Argument must be a workspace, is %d", workspace->type)) { return NULL; } - struct sway_container *current_output = workspace->parent; + swayc_t *current_output = workspace->parent; int offset = next ? 1 : -1; int start = next ? 0 : 1; int end; @@ -172,57 +166,54 @@ struct sway_container *workspace_prev_next_impl( } } - // Given workspace is the first/last on the output, jump to the - // previous/next output + // Given workspace is the first/last on the output, jump to the previous/next output int num_outputs = root_container.children->length; for (i = 0; i < num_outputs; i++) { if (root_container.children->items[i] == current_output) { - struct sway_container *next_output = root_container.children->items[ + swayc_t *next_output = root_container.children->items[ wrap(i + offset, num_outputs)]; return workspace_output_prev_next_impl(next_output, next); } } - // Doesn't happen, at worst the for loop returns the previously active - // workspace on the active output + // Doesn't happen, at worst the for loop returns the previously active workspace on the active output return NULL; } -struct sway_container *workspace_output_next(struct sway_container *current) { +swayc_t *workspace_output_next(swayc_t *current) { return workspace_output_prev_next_impl(current, true); } -struct sway_container *workspace_next(struct sway_container *current) { +swayc_t *workspace_next(swayc_t *current) { return workspace_prev_next_impl(current, true); } -struct sway_container *workspace_output_prev(struct sway_container *current) { +swayc_t *workspace_output_prev(swayc_t *current) { return workspace_output_prev_next_impl(current, false); } -struct sway_container *workspace_prev(struct sway_container *current) { +swayc_t *workspace_prev(swayc_t *current) { return workspace_prev_next_impl(current, false); } -bool workspace_switch(struct sway_container *workspace) { +bool workspace_switch(swayc_t *workspace) { if (!workspace) { return false; } struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = - sway_seat_get_focus_inactive(seat, &root_container); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); if (!seat || !focus) { return false; } - struct sway_container *active_ws = focus; + swayc_t *active_ws = focus; if (active_ws->type != C_WORKSPACE) { - container_parent(focus, C_WORKSPACE); + swayc_parent_by_type(focus, C_WORKSPACE); } if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { - struct sway_container *new_ws = workspace_by_name(prev_workspace_name); + swayc_t *new_ws = workspace_by_name(prev_workspace_name); workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); } @@ -239,14 +230,13 @@ bool workspace_switch(struct sway_container *workspace) { // TODO: Deal with sticky containers - wlr_log(L_DEBUG, "Switching to workspace %p:%s", - workspace, workspace->name); - struct sway_container *next = sway_seat_get_focus_inactive(seat, workspace); + wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); + swayc_t *next = sway_seat_get_focus_inactive(seat, workspace); if (next == NULL) { next = workspace; } sway_seat_set_focus(seat, next); - struct sway_container *output = container_parent(workspace, C_OUTPUT); + swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); arrange_windows(output, -1, -1); return true; } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 2d2b3b69..93d1219c 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -352,7 +352,7 @@ void ipc_bar_init(struct bar *bar, const char *bar_id) { } // add bar to the output - struct output *bar_output = container_output_create(name); + struct output *bar_output = new_output(name); bar_output->idx = i; list_add(bar->outputs, bar_output); } -- cgit v1.2.3 From dc8c9fbeb664518c76066cc28ee29452c6c30128 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 23:41:33 -0400 Subject: Revert "Merge pull request #1653 from swaywm/revert-1647-refactor-tree" This reverts commit 472e81f35d689d67cda241acafda91c688d61046, reversing changes made to 6b7841b11ff4cd35f54d69dc92029855893e5ce0. --- include/sway/config.h | 17 +-- include/sway/container.h | 169 ---------------------------- include/sway/criteria.h | 6 +- include/sway/input/input-manager.h | 4 +- include/sway/input/seat.h | 13 ++- include/sway/ipc-json.h | 6 +- include/sway/ipc-server.h | 6 +- include/sway/layout.h | 43 -------- include/sway/tree/container.h | 137 +++++++++++++++++++++++ include/sway/tree/layout.h | 52 +++++++++ include/sway/tree/view.h | 116 +++++++++++++++++++ include/sway/tree/workspace.h | 26 +++++ include/sway/view.h | 120 -------------------- include/sway/workspace.h | 20 ---- sway/commands/exec_always.c | 4 +- sway/commands/focus.c | 9 +- sway/commands/kill.c | 4 +- sway/commands/layout.c | 20 ++-- sway/commands/output.c | 2 +- sway/commands/reload.c | 2 +- sway/commands/workspace.c | 14 +-- sway/config.c | 2 +- sway/config/output.c | 4 +- sway/criteria.c | 16 +-- sway/desktop/layer_shell.c | 2 +- sway/desktop/output.c | 20 ++-- sway/desktop/wl_shell.c | 12 +- sway/desktop/xdg_shell_v6.c | 12 +- sway/desktop/xwayland.c | 24 ++-- sway/input/cursor.c | 10 +- sway/input/input-manager.c | 4 +- sway/input/seat.c | 38 +++---- sway/ipc-json.c | 16 +-- sway/ipc-server.c | 4 +- sway/main.c | 4 +- sway/tree/container.c | 221 +++++++++++++++++-------------------- sway/tree/layout.c | 133 +++++++++++++--------- sway/tree/view.c | 7 +- sway/tree/workspace.c | 92 ++++++++------- swaybar/ipc.c | 2 +- 40 files changed, 709 insertions(+), 704 deletions(-) delete mode 100644 include/sway/container.h delete mode 100644 include/sway/layout.h create mode 100644 include/sway/tree/container.h create mode 100644 include/sway/tree/layout.h create mode 100644 include/sway/tree/view.h create mode 100644 include/sway/tree/workspace.h delete mode 100644 include/sway/view.h delete mode 100644 include/sway/workspace.h (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 48a8b0ab..7fdd0be0 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -10,8 +10,8 @@ #include #include #include "list.h" -#include "layout.h" -#include "container.h" +#include "tree/layout.h" +#include "tree/container.h" /** * Describes a variable created via the `set` command. @@ -299,8 +299,8 @@ struct sway_config { char *floating_scroll_down_cmd; char *floating_scroll_left_cmd; char *floating_scroll_right_cmd; - enum swayc_layouts default_orientation; - enum swayc_layouts default_layout; + enum sway_container_layout default_orientation; + enum sway_container_layout default_layout; char *font; int font_height; @@ -324,8 +324,8 @@ struct sway_config { list_t *config_chain; const char *current_config; - enum swayc_border_types border; - enum swayc_border_types floating_border; + enum sway_container_border border; + enum sway_container_border floating_border; int border_thickness; int floating_border_thickness; enum edge_border_types hide_edge_borders; @@ -356,7 +356,7 @@ struct sway_config { struct input_config *input_config; struct seat_config *seat_config; struct sway_seat *seat; - swayc_t *current_container; + struct sway_container *current_container; } handler_context; }; @@ -416,7 +416,8 @@ void output_get_identifier(char *identifier, size_t len, struct sway_output *output); struct output_config *new_output_config(const char *name); void merge_output_config(struct output_config *dst, struct output_config *src); -void apply_output_config(struct output_config *oc, swayc_t *output); +void apply_output_config(struct output_config *oc, + struct sway_container *output); void free_output_config(struct output_config *oc); /** diff --git a/include/sway/container.h b/include/sway/container.h deleted file mode 100644 index f200a1a2..00000000 --- a/include/sway/container.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef _SWAY_CONTAINER_H -#define _SWAY_CONTAINER_H -#include -#include -#include -#include -#include "list.h" - -typedef struct sway_container swayc_t; - -extern swayc_t root_container; - -struct sway_view; -struct sway_seat; - -/** - * Different kinds of containers. - * - * This enum is in order. A container will never be inside of a container below - * it on this list. - */ -enum swayc_types { - C_ROOT, /**< The root container. Only one of these ever exists. */ - C_OUTPUT, /**< An output (aka monitor, head, etc). */ - C_WORKSPACE, /**< A workspace. */ - C_CONTAINER, /**< A manually created container. */ - C_VIEW, /**< A view (aka window). */ - - C_TYPES, -}; - -/** - * Different ways to arrange a container. - */ -enum swayc_layouts { - L_NONE, /**< Used for containers that have no layout (views, root) */ - L_HORIZ, - L_VERT, - L_STACKED, - L_TABBED, - L_FLOATING, /**< A psuedo-container, removed from the tree, to hold floating windows */ - - /* Awesome/Monad style auto layouts */ - L_AUTO_LEFT, - L_AUTO_RIGHT, - L_AUTO_TOP, - L_AUTO_BOTTOM, - - L_AUTO_FIRST = L_AUTO_LEFT, - L_AUTO_LAST = L_AUTO_BOTTOM, - - // Keep last - L_LAYOUTS, -}; - -enum swayc_border_types { - B_NONE, /**< No border */ - B_PIXEL, /**< 1px border */ - B_NORMAL, /**< Normal border with title bar */ -}; - -struct sway_root; -struct sway_output; -struct sway_view; - -/** - * Stores information about a container. - * - * The tree is made of these. Views are containers that cannot have children. - */ -struct sway_container { - union { - // TODO: Encapsulate state for other node types as well like C_CONTAINER - struct sway_root *sway_root; // C_ROOT - struct sway_output *sway_output; // C_OUTPUT - struct sway_view *sway_view; // C_VIEW - }; - - /** - * A unique ID to identify this container. Primarily used in the - * get_tree JSON output. - */ - size_t id; - - char *name; - - enum swayc_types type; - enum swayc_layouts layout; - enum swayc_layouts prev_layout; - enum swayc_layouts workspace_layout; - - /** - * The coordinates that this view appear at, relative to the output they - * are located on (output containers have absolute coordinates). - */ - double x, y; - - /** - * Width and height of this container, without borders or gaps. - */ - double width, height; - - list_t *children; - - /** - * The parent of this container. NULL for the root container. - */ - struct sway_container *parent; - - /** - * Number of master views in auto layouts. - */ - size_t nb_master; - - /** - * Number of slave groups (e.g. columns) in auto layouts. - */ - size_t nb_slave_groups; - - /** - * Marks applied to the container, list_t of char*. - */ - list_t *marks; - - struct { - struct wl_signal destroy; - } events; -}; - -void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, - void (*func)(swayc_t *item, void *data), void *data); - -swayc_t *new_output(struct sway_output *sway_output); -swayc_t *new_workspace(swayc_t *output, const char *name); -swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view); - -swayc_t *destroy_output(swayc_t *output); -swayc_t *destroy_view(swayc_t *view); - -swayc_t *next_view_sibling(struct sway_seat *seat); - -/** - * Finds a container based on test criteria. Returns the first container that - * passes the test. - */ -swayc_t *swayc_by_test(swayc_t *container, - bool (*test)(swayc_t *view, void *data), void *data); -/** - * Finds a parent container with the given swayc_type. - */ -swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); -/** - * Maps a container's children over a function. - */ -void container_map(swayc_t *container, - void (*f)(swayc_t *view, void *data), void *data); - -swayc_t *swayc_at(swayc_t *parent, double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy); - -/** - * Apply the function for each child of the container breadth first. - */ -void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), - void *data); - -swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout); - -#endif diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 9b4b4bef..ec256ddb 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -1,7 +1,7 @@ #ifndef _SWAY_CRITERIA_H #define _SWAY_CRITERIA_H -#include "container.h" +#include "tree/container.h" #include "list.h" /** @@ -31,12 +31,12 @@ char *extract_crit_tokens(list_t *tokens, const char *criteria); // Returns list of criteria that match given container. These criteria have // been set with `for_window` commands and have an associated cmdlist. -list_t *criteria_for(swayc_t *cont); +list_t *criteria_for(struct sway_container *cont); // Returns a list of all containers that match the given list of tokens. list_t *container_for_crit_tokens(list_t *tokens); // Returns true if any criteria in the given list matches this container -bool criteria_any(swayc_t *cont, list_t *criteria); +bool criteria_any(struct sway_container *cont, list_t *criteria); #endif diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index eab7dc90..c6c73dba 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -31,10 +31,10 @@ struct sway_input_manager *sway_input_manager_create( struct sway_server *server); bool sway_input_manager_has_focus(struct sway_input_manager *input, - swayc_t *container); + struct sway_container *container); void sway_input_manager_set_focus(struct sway_input_manager *input, - swayc_t *container); + struct sway_container *container); void sway_input_manager_configure_xcursor(struct sway_input_manager *input); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 1d55bec7..496bfd5d 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -14,7 +14,7 @@ struct sway_seat_device { struct sway_seat_container { struct sway_seat *seat; - swayc_t *container; + struct sway_container *container; struct wl_list link; // sway_seat::focus_stack @@ -54,9 +54,9 @@ void sway_seat_remove_device(struct sway_seat *seat, void sway_seat_configure_xcursor(struct sway_seat *seat); -void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); +void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); -swayc_t *sway_seat_get_focus(struct sway_seat *seat); +struct sway_container *sway_seat_get_focus(struct sway_seat *seat); /** * Return the last container to be focused for the seat (or the most recently @@ -67,10 +67,11 @@ swayc_t *sway_seat_get_focus(struct sway_seat *seat); * is destroyed, or focus moves to a container with children and we need to * descend into the next leaf in focus order. */ -swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container); +struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, + struct sway_container *container); -swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, - enum swayc_types type); +struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, + enum sway_container_type type); void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index eef5a018..3d2fdc4f 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -1,13 +1,13 @@ #ifndef _SWAY_IPC_JSON_H #define _SWAY_IPC_JSON_H #include -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/input-manager.h" json_object *ipc_json_get_version(); -json_object *ipc_json_describe_container(swayc_t *c); -json_object *ipc_json_describe_container_recursive(swayc_t *c); +json_object *ipc_json_describe_container(struct sway_container *c); +json_object *ipc_json_describe_container_recursive(struct sway_container *c); json_object *ipc_json_describe_input(struct sway_input_device *device); #endif diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index bcf1c433..d73006dc 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -1,15 +1,17 @@ #ifndef _SWAY_IPC_SERVER_H #define _SWAY_IPC_SERVER_H #include -#include "sway/container.h" +#include "sway/tree/container.h" #include "ipc.h" struct sway_server; void ipc_init(struct sway_server *server); + void ipc_terminate(void); + struct sockaddr_un *ipc_user_sockaddr(void); -void ipc_event_window(swayc_t *window, const char *change); +void ipc_event_window(struct sway_container *window, const char *change); #endif diff --git a/include/sway/layout.h b/include/sway/layout.h deleted file mode 100644 index e82c4442..00000000 --- a/include/sway/layout.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _SWAY_LAYOUT_H -#define _SWAY_LAYOUT_H - -#include -#include "sway/container.h" - -enum movement_direction { - MOVE_LEFT, - MOVE_RIGHT, - MOVE_UP, - MOVE_DOWN, - MOVE_PARENT, - MOVE_CHILD, - MOVE_NEXT, - MOVE_PREV, - MOVE_FIRST -}; - -struct sway_container; - -struct sway_root { - struct wlr_output_layout *output_layout; - - struct wl_listener output_layout_change; - - struct wl_list unmanaged_views; // sway_view::unmanaged_view_link - - struct { - struct wl_signal new_container; - } events; -}; - -void init_layout(void); -void add_child(struct sway_container *parent, struct sway_container *child); -swayc_t *add_sibling(swayc_t *parent, swayc_t *child); -struct sway_container *remove_child(struct sway_container *child); -enum swayc_layouts default_layout(struct sway_container *output); -void sort_workspaces(struct sway_container *output); -void arrange_windows(struct sway_container *container, double width, double height); -swayc_t *get_swayc_in_direction(swayc_t *container, - struct sway_seat *seat, enum movement_direction dir); - -#endif diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h new file mode 100644 index 00000000..16df3ee7 --- /dev/null +++ b/include/sway/tree/container.h @@ -0,0 +1,137 @@ +#ifndef _SWAY_CONTAINER_H +#define _SWAY_CONTAINER_H +#include +#include +#include +#include +#include "list.h" + +extern struct sway_container root_container; + +struct sway_view; +struct sway_seat; + +/** + * Different kinds of containers. + * + * This enum is in order. A container will never be inside of a container below + * it on this list. + */ +enum sway_container_type { + C_ROOT, + C_OUTPUT, + C_WORKSPACE, + C_CONTAINER, + C_VIEW, + + C_TYPES, +}; + +enum sway_container_layout { + L_NONE, + L_HORIZ, + L_VERT, + L_STACKED, + L_TABBED, + L_FLOATING, + + // Keep last + L_LAYOUTS, +}; + +enum sway_container_border { + B_NONE, + B_PIXEL, + B_NORMAL, +}; + +struct sway_root; +struct sway_output; +struct sway_view; + +struct sway_container { + union { + // TODO: Encapsulate state for other node types as well like C_CONTAINER + struct sway_root *sway_root; + struct sway_output *sway_output; + struct sway_view *sway_view; + }; + + /** + * A unique ID to identify this container. Primarily used in the + * get_tree JSON output. + */ + size_t id; + + char *name; + + enum sway_container_type type; + enum sway_container_layout layout; + enum sway_container_layout prev_layout; + enum sway_container_layout workspace_layout; + + // TODO convert to layout coordinates + double x, y; + + // does not include borders or gaps. + double width, height; + + list_t *children; + + struct sway_container *parent; + + list_t *marks; // list of char* + + struct { + struct wl_signal destroy; + } events; +}; + +// TODO only one container create function and pass the type? +struct sway_container *container_output_create( + struct sway_output *sway_output); + +struct sway_container *container_workspace_create( + struct sway_container *output, const char *name); + +struct sway_container *container_view_create( + struct sway_container *sibling, struct sway_view *sway_view); + +struct sway_container *container_output_destroy(struct sway_container *output); + +struct sway_container *container_view_destroy(struct sway_container *view); + +struct sway_container *container_set_layout(struct sway_container *container, + enum sway_container_layout layout); + +void container_descendents(struct sway_container *root, + enum sway_container_type type, + void (*func)(struct sway_container *item, void *data), void *data); + +/** + * Finds a container based on test criteria. Returns the first container that + * passes the test. + */ +struct sway_container *container_find(struct sway_container *container, + bool (*test)(struct sway_container *view, void *data), void *data); + +/** + * Finds a parent container with the given struct sway_containerype. + */ +struct sway_container *container_parent(struct sway_container *container, + enum sway_container_type type); + +/** + * Find a container at the given coordinates. + */ +struct sway_container *container_at(struct sway_container *parent, + double lx, double ly, struct wlr_surface **surface, + double *sx, double *sy); + +/** + * Apply the function for each child of the container breadth first. + */ +void container_for_each_descendent(struct sway_container *container, + void (*f)(struct sway_container *container, void *data), void *data); + +#endif diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h new file mode 100644 index 00000000..ad52bdb0 --- /dev/null +++ b/include/sway/tree/layout.h @@ -0,0 +1,52 @@ +#ifndef _SWAY_LAYOUT_H +#define _SWAY_LAYOUT_H + +#include +#include "sway/tree/container.h" + +enum movement_direction { + MOVE_LEFT, + MOVE_RIGHT, + MOVE_UP, + MOVE_DOWN, + MOVE_PARENT, + MOVE_CHILD, + MOVE_NEXT, + MOVE_PREV, + MOVE_FIRST +}; + +struct sway_container; + +struct sway_root { + struct wlr_output_layout *output_layout; + + struct wl_listener output_layout_change; + + struct wl_list unmanaged_views; // sway_view::unmanaged_view_link + + struct { + struct wl_signal new_container; + } events; +}; + +void layout_init(void); + +void container_add_child(struct sway_container *parent, struct sway_container *child); + +struct sway_container *container_add_sibling(struct sway_container *parent, + struct sway_container *child); + +struct sway_container *container_remove_child(struct sway_container *child); + +enum sway_container_layout container_get_default_layout(struct sway_container *output); + +void container_sort_workspaces(struct sway_container *output); + +void arrange_windows(struct sway_container *container, + double width, double height); + +struct sway_container *container_get_in_direction(struct sway_container + *container, struct sway_seat *seat, enum movement_direction dir); + +#endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h new file mode 100644 index 00000000..e5f53f4e --- /dev/null +++ b/include/sway/tree/view.h @@ -0,0 +1,116 @@ +#ifndef _SWAY_VIEW_H +#define _SWAY_VIEW_H +#include +#include +#include +#include + +struct sway_container; +struct sway_view; + +struct sway_xdg_surface_v6 { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +struct sway_xwayland_surface { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener request_configure; + struct wl_listener unmap_notify; + struct wl_listener map_notify; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +struct sway_wl_shell_surface { + struct sway_view *view; + + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +enum sway_view_type { + SWAY_WL_SHELL_VIEW, + SWAY_XDG_SHELL_V6_VIEW, + SWAY_XWAYLAND_VIEW, + // Keep last + SWAY_VIEW_TYPES, +}; + +enum sway_view_prop { + VIEW_PROP_TITLE, + VIEW_PROP_APP_ID, + VIEW_PROP_CLASS, + VIEW_PROP_INSTANCE, +}; + +struct sway_view { + enum sway_view_type type; + struct sway_container *swayc; + struct wlr_surface *surface; + int width, height; + + union { + struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; + struct wlr_xwayland_surface *wlr_xwayland_surface; + struct wlr_wl_shell_surface *wlr_wl_shell_surface; + }; + + union { + struct sway_xdg_surface_v6 *sway_xdg_surface_v6; + struct sway_xwayland_surface *sway_xwayland_surface; + struct sway_wl_shell_surface *sway_wl_shell_surface; + }; + + struct { + const char *(*get_prop)(struct sway_view *view, + enum sway_view_prop prop); + void (*set_size)(struct sway_view *view, + int width, int height); + void (*set_position)(struct sway_view *view, + double ox, double oy); + void (*set_activated)(struct sway_view *view, bool activated); + void (*close)(struct sway_view *view); + } iface; + + // only used for unmanaged views (shell specific) + struct wl_list unmanaged_view_link; // sway_root::unmanaged views +}; + +const char *view_get_title(struct sway_view *view); + +const char *view_get_app_id(struct sway_view *view); + +const char *view_get_class(struct sway_view *view); + +const char *view_get_instance(struct sway_view *view); + +void view_set_size(struct sway_view *view, int width, int height); + +void view_set_position(struct sway_view *view, double ox, double oy); + +void view_set_activated(struct sway_view *view, bool activated); + +void view_close(struct sway_view *view); + +void view_update_outputs(struct sway_view *view, const struct wlr_box *before); + +#endif diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h new file mode 100644 index 00000000..d73b29c1 --- /dev/null +++ b/include/sway/tree/workspace.h @@ -0,0 +1,26 @@ +#ifndef _SWAY_WORKSPACE_H +#define _SWAY_WORKSPACE_H + +#include "sway/tree/container.h" + +extern char *prev_workspace_name; + +char *workspace_next_name(const char *output_name); + +struct sway_container *workspace_create(const char *name); + +bool workspace_switch(struct sway_container *workspace); + +struct sway_container *workspace_by_number(const char* name); + +struct sway_container *workspace_by_name(const char*); + +struct sway_container *workspace_output_next(struct sway_container *current); + +struct sway_container *workspace_next(struct sway_container *current); + +struct sway_container *workspace_output_prev(struct sway_container *current); + +struct sway_container *workspace_prev(struct sway_container *current); + +#endif diff --git a/include/sway/view.h b/include/sway/view.h deleted file mode 100644 index b2886211..00000000 --- a/include/sway/view.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef _SWAY_VIEW_H -#define _SWAY_VIEW_H -#include -#include -#include -#include - -struct sway_container; -struct sway_view; - -struct sway_xdg_surface_v6 { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -struct sway_xwayland_surface { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener request_configure; - struct wl_listener unmap_notify; - struct wl_listener map_notify; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -struct sway_wl_shell_surface { - struct sway_view *view; - - struct wl_listener commit; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -enum sway_view_type { - SWAY_WL_SHELL_VIEW, - SWAY_XDG_SHELL_V6_VIEW, - SWAY_XWAYLAND_VIEW, - // Keep last - SWAY_VIEW_TYPES, -}; - -enum sway_view_prop { - VIEW_PROP_TITLE, - VIEW_PROP_APP_ID, - VIEW_PROP_CLASS, - VIEW_PROP_INSTANCE, -}; - -/** - * sway_view is a state container for surfaces that are arranged in the sway - * tree (shell surfaces). - */ -struct sway_view { - enum sway_view_type type; - struct sway_container *swayc; - struct wlr_surface *surface; - int width, height; - - union { - struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; - struct wlr_xwayland_surface *wlr_xwayland_surface; - struct wlr_wl_shell_surface *wlr_wl_shell_surface; - }; - - union { - struct sway_xdg_surface_v6 *sway_xdg_surface_v6; - struct sway_xwayland_surface *sway_xwayland_surface; - struct sway_wl_shell_surface *sway_wl_shell_surface; - }; - - struct { - const char *(*get_prop)(struct sway_view *view, - enum sway_view_prop prop); - void (*set_size)(struct sway_view *view, - int width, int height); - void (*set_position)(struct sway_view *view, - double ox, double oy); - void (*set_activated)(struct sway_view *view, bool activated); - void (*close)(struct sway_view *view); - } iface; - - // only used for unmanaged views (shell specific) - struct wl_list unmanaged_view_link; // sway_root::unmanaged views -}; - -const char *view_get_title(struct sway_view *view); - -const char *view_get_app_id(struct sway_view *view); - -const char *view_get_class(struct sway_view *view); - -const char *view_get_instance(struct sway_view *view); - -void view_set_size(struct sway_view *view, int width, int height); - -void view_set_position(struct sway_view *view, double ox, double oy); - -void view_set_activated(struct sway_view *view, bool activated); - -void view_close(struct sway_view *view); - -void view_update_outputs(struct sway_view *view, const struct wlr_box *before); - -#endif diff --git a/include/sway/workspace.h b/include/sway/workspace.h deleted file mode 100644 index fee54255..00000000 --- a/include/sway/workspace.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _SWAY_WORKSPACE_H -#define _SWAY_WORKSPACE_H - -#include "sway/container.h" - -extern char *prev_workspace_name; - -char *workspace_next_name(const char *output_name); -swayc_t *workspace_create(const char *name); -bool workspace_switch(swayc_t *workspace); - -struct sway_container *workspace_by_number(const char* name); -swayc_t *workspace_by_name(const char*); - -struct sway_container *workspace_output_next(swayc_t *current); -struct sway_container *workspace_next(swayc_t *current); -struct sway_container *workspace_output_prev(swayc_t *current); -struct sway_container *workspace_prev(swayc_t *current); - -#endif diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 61870c51..954950e7 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -6,8 +6,8 @@ #include #include "sway/commands.h" #include "sway/config.h" -#include "sway/container.h" -#include "sway/workspace.h" +#include "sway/tree/container.h" +#include "sway/tree/workspace.h" #include "log.h" #include "stringop.h" diff --git a/sway/commands/focus.c b/sway/commands/focus.c index f1a8078f..64f079f4 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -3,10 +3,11 @@ #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/commands.h" -static bool parse_movement_direction(const char *name, enum movement_direction *out) { +static bool parse_movement_direction(const char *name, + enum movement_direction *out) { if (strcasecmp(name, "left") == 0) { *out = MOVE_LEFT; } else if (strcasecmp(name, "right") == 0) { @@ -31,7 +32,7 @@ static bool parse_movement_direction(const char *name, enum movement_direction * } struct cmd_results *cmd_focus(int argc, char **argv) { - swayc_t *con = config->handler_context.current_container; + struct sway_container *con = config->handler_context.current_container; struct sway_seat *seat = config->handler_context.seat; if (con->type < C_WORKSPACE) { return cmd_results_new(CMD_FAILURE, "focus", @@ -50,7 +51,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) { "Expected 'focus ' or 'focus output '"); } - swayc_t *next_focus = get_swayc_in_direction(con, seat, direction); + struct sway_container *next_focus = container_get_in_direction(con, seat, direction); if (next_focus) { sway_seat_set_focus(seat, next_focus); } diff --git a/sway/commands/kill.c b/sway/commands/kill.c index f408ce2a..f6774767 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -2,11 +2,11 @@ #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/commands.h" struct cmd_results *cmd_kill(int argc, char **argv) { - enum swayc_types type = config->handler_context.current_container->type; + enum sway_container_type type = config->handler_context.current_container->type; if (type != C_VIEW && type != C_CONTAINER) { return cmd_results_new(CMD_INVALID, NULL, "Can only kill views and containers with this command"); diff --git a/sway/commands/layout.c b/sway/commands/layout.c index b0fc5d66..ebab2a48 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -1,8 +1,8 @@ #include #include #include "sway/commands.h" -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "log.h" struct cmd_results *cmd_layout(int argc, char **argv) { @@ -10,7 +10,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { return error; } - swayc_t *parent = config->handler_context.current_container; + struct sway_container *parent = config->handler_context.current_container; // TODO: floating /* @@ -26,10 +26,10 @@ struct cmd_results *cmd_layout(int argc, char **argv) { // TODO: stacks and tabs if (strcasecmp(argv[0], "default") == 0) { - swayc_change_layout(parent, parent->prev_layout); + container_set_layout(parent, parent->prev_layout); if (parent->layout == L_NONE) { - swayc_t *output = swayc_parent_by_type(parent, C_OUTPUT); - swayc_change_layout(parent, default_layout(output)); + struct sway_container *output = container_parent(parent, C_OUTPUT); + container_set_layout(parent, container_get_default_layout(output)); } } else { if (parent->layout != L_TABBED && parent->layout != L_STACKED) { @@ -37,15 +37,15 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } if (strcasecmp(argv[0], "splith") == 0) { - swayc_change_layout(parent, L_HORIZ); + container_set_layout(parent, L_HORIZ); } else if (strcasecmp(argv[0], "splitv") == 0) { - swayc_change_layout(parent, L_VERT); + container_set_layout(parent, L_VERT); } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE || parent->workspace_layout == L_HORIZ)) { - swayc_change_layout(parent, L_VERT); + container_set_layout(parent, L_VERT); } else { - swayc_change_layout(parent, L_HORIZ); + container_set_layout(parent, L_HORIZ); } } } diff --git a/sway/commands/output.c b/sway/commands/output.c index 35bc8099..f7e3372c 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -296,7 +296,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { char identifier[128]; bool all = strcmp(output->name, "*") == 0; for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *cont = root_container.children->items[i]; + struct sway_container *cont = root_container.children->items[i]; if (cont->type != C_OUTPUT) { continue; } diff --git a/sway/commands/reload.c b/sway/commands/reload.c index d54d40db..8cef789b 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -1,6 +1,6 @@ #include "sway/commands.h" #include "sway/config.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" struct cmd_results *cmd_reload(int argc, char **argv) { struct cmd_results *error = NULL; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index fa891398..8f39e5fc 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -4,7 +4,7 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/input/seat.h" -#include "sway/workspace.h" +#include "sway/tree/workspace.h" #include "list.h" #include "log.h" #include "stringop.h" @@ -17,15 +17,15 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { int output_location = -1; - swayc_t *current_container = config->handler_context.current_container; - swayc_t *old_workspace = NULL, *old_output = NULL; + struct sway_container *current_container = config->handler_context.current_container; + struct sway_container *old_workspace = NULL, *old_output = NULL; if (current_container) { if (current_container->type == C_WORKSPACE) { old_workspace = current_container; } else { - old_workspace = swayc_parent_by_type(current_container, C_WORKSPACE); + old_workspace = container_parent(current_container, C_WORKSPACE); } - old_output = swayc_parent_by_type(current_container, C_OUTPUT); + old_output = container_parent(current_container, C_OUTPUT); } for (int i = 0; i < argc; ++i) { @@ -57,7 +57,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (config->reading || !config->active) { return cmd_results_new(CMD_DEFER, "workspace", NULL); } - swayc_t *ws = NULL; + struct sway_container *ws = NULL; if (strcasecmp(argv[0], "number") == 0) { if (!(ws = workspace_by_number(argv[1]))) { char *name = join_args(argv + 1, argc - 1); @@ -92,7 +92,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { workspace_switch(ws); current_container = sway_seat_get_focus(config->handler_context.seat); - swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); + struct sway_container *new_output = container_parent(current_container, C_OUTPUT); if (config->mouse_warping && old_output != new_output) { // TODO: Warp mouse diff --git a/sway/config.c b/sway/config.c index 213e7680..0b29735a 100644 --- a/sway/config.c +++ b/sway/config.c @@ -24,7 +24,7 @@ #include "sway/input/seat.h" #include "sway/commands.h" #include "sway/config.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "readline.h" #include "stringop.h" #include "list.h" diff --git a/sway/config/output.c b/sway/config/output.c index 9e211861..7fc79739 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -120,14 +120,14 @@ void terminate_swaybg(pid_t pid) { } } -void apply_output_config(struct output_config *oc, swayc_t *output) { +void apply_output_config(struct output_config *oc, struct sway_container *output) { assert(output->type == C_OUTPUT); struct wlr_output *wlr_output = output->sway_output->wlr_output; if (oc && oc->enabled == 0) { wlr_output_layout_remove(root_container.sway_root->output_layout, wlr_output); - destroy_output(output); + container_output_destroy(output); return; } diff --git a/sway/criteria.c b/sway/criteria.c index 2eee331c..247f6b75 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -4,9 +4,9 @@ #include #include #include "sway/criteria.h" -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/config.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "stringop.h" #include "list.h" #include "log.h" @@ -272,7 +272,7 @@ static int regex_cmp(const char *item, const pcre *regex) { } // test a single view if it matches list of criteria tokens (all of them). -static bool criteria_test(swayc_t *cont, list_t *tokens) { +static bool criteria_test(struct sway_container *cont, list_t *tokens) { if (cont->type != C_VIEW) { return false; } @@ -398,7 +398,7 @@ void free_criteria(struct criteria *crit) { free(crit); } -bool criteria_any(swayc_t *cont, list_t *criteria) { +bool criteria_any(struct sway_container *cont, list_t *criteria) { for (int i = 0; i < criteria->length; i++) { struct criteria *bc = criteria->items[i]; if (criteria_test(cont, bc->tokens)) { @@ -408,7 +408,7 @@ bool criteria_any(swayc_t *cont, list_t *criteria) { return false; } -list_t *criteria_for(swayc_t *cont) { +list_t *criteria_for(struct sway_container *cont) { list_t *criteria = config->criteria, *matches = create_list(); for (int i = 0; i < criteria->length; i++) { struct criteria *bc = criteria->items[i]; @@ -424,7 +424,7 @@ struct list_tokens { list_t *tokens; }; -static void container_match_add(swayc_t *container, +static void container_match_add(struct sway_container *container, struct list_tokens *list_tokens) { if (criteria_test(container, list_tokens->tokens)) { list_add(list_tokens->list, container); @@ -435,8 +435,8 @@ list_t *container_for_crit_tokens(list_t *tokens) { struct list_tokens list_tokens = (struct list_tokens){create_list(), tokens}; - container_map(&root_container, - (void (*)(swayc_t *, void *))container_match_add, + container_for_each_descendent(&root_container, + (void (*)(struct sway_container *, void *))container_match_add, &list_tokens); // TODO look in the scratchpad diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index bd62f84a..137b3260 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -7,7 +7,7 @@ #include #include #include "sway/layers.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "sway/output.h" #include "sway/server.h" diff --git a/sway/desktop/output.c b/sway/desktop/output.c index b8253ace..ba778f4c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -11,14 +11,14 @@ #include #include #include "log.h" -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/layers.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "sway/output.h" #include "sway/server.h" -#include "sway/view.h" +#include "sway/tree/view.h" /** * Rotate a child's position relative to a parent. The parent size is (pw, ph), @@ -145,7 +145,7 @@ struct render_data { struct timespec *now; }; -static void output_frame_view(swayc_t *view, void *data) { +static void output_frame_view(struct sway_container *view, void *data) { struct render_data *rdata = data; struct sway_output *output = rdata->output; struct timespec *now = rdata->now; @@ -219,16 +219,16 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); - swayc_t *workspace = (focus->type == C_WORKSPACE ? + struct sway_container *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); + struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : - swayc_parent_by_type(focus, C_WORKSPACE)); + container_parent(focus, C_WORKSPACE)); struct render_data rdata = { .output = soutput, .now = &now, }; - swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, &rdata); + container_descendents(workspace, C_VIEW, output_frame_view, &rdata); // render unmanaged views on top struct sway_view *view; @@ -259,7 +259,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); - destroy_output(output->swayc); + container_output_destroy(output->swayc); } static void handle_output_mode(struct wl_listener *listener, void *data) { @@ -287,7 +287,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { wlr_output_set_mode(wlr_output, mode); } - output->swayc = new_output(output); + output->swayc = container_output_create(output); if (!output->swayc) { free(output); return; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 0356aa81..4d4d1ed7 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/server.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" #include "log.h" @@ -74,7 +74,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_surface, destroy); wl_list_remove(&sway_surface->commit.link); wl_list_remove(&sway_surface->destroy.link); - swayc_t *parent = destroy_view(sway_surface->view->swayc); + struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); free(sway_surface->view); free(sway_surface); arrange_windows(parent, -1, -1); @@ -132,8 +132,8 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); - swayc_t *cont = new_view(focus, sway_view); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 18e7d399..25c0cbca 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/server.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" #include "log.h" @@ -83,7 +83,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_xdg_surface, destroy); wl_list_remove(&sway_xdg_surface->commit.link); wl_list_remove(&sway_xdg_surface->destroy.link); - swayc_t *parent = destroy_view(sway_xdg_surface->view->swayc); + struct sway_container *parent = container_view_destroy(sway_xdg_surface->view->swayc); free(sway_xdg_surface->view); free(sway_xdg_surface); arrange_windows(parent, -1, -1); @@ -137,8 +137,8 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); - swayc_t *cont = new_view(focus, sway_view); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index f9b5242b..fd0bcaca 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -5,10 +5,10 @@ #include #include #include -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/server.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/output.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" @@ -49,11 +49,11 @@ static void set_position(struct sway_view *view, double ox, double oy) { if (!assert_xwayland(view)) { return; } - swayc_t *output = swayc_parent_by_type(view->swayc, C_OUTPUT); + struct sway_container *output = container_parent(view->swayc, C_OUTPUT); if (!sway_assert(output, "view must be within tree to set position")) { return; } - swayc_t *root = swayc_parent_by_type(output, C_ROOT); + struct sway_container *root = container_parent(output, C_ROOT); if (!sway_assert(root, "output must be within tree to set position")) { return; } @@ -114,7 +114,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } } - swayc_t *parent = destroy_view(sway_surface->view->swayc); + struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); if (parent) { arrange_windows(parent, -1, -1); } @@ -132,7 +132,7 @@ static void handle_unmap_notify(struct wl_listener *listener, void *data) { } // take it out of the tree - swayc_t *parent = destroy_view(sway_surface->view->swayc); + struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); if (parent) { arrange_windows(parent, -1, -1); } @@ -155,12 +155,12 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { &sway_surface->view->unmanaged_view_link); } else { struct sway_view *view = sway_surface->view; - destroy_view(view->swayc); + container_view_destroy(view->swayc); - swayc_t *parent = root_container.children->items[0]; + struct sway_container *parent = root_container.children->items[0]; parent = parent->children->items[0]; // workspace - swayc_t *cont = new_view(parent, view); + struct sway_container *cont = container_view_create(parent, view); view->swayc = cont; arrange_windows(cont->parent, -1, -1); @@ -238,8 +238,8 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { } struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); - swayc_t *cont = new_view(focus, sway_view); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 8a0d1df5..d57ac3e3 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -7,7 +7,7 @@ #include #include #include "sway/input/cursor.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "list.h" #include "log.h" @@ -49,8 +49,8 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, } } - swayc_t *swayc = - swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + struct sway_container *swayc = + container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); if (swayc) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); @@ -87,8 +87,8 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { if (event->button == BTN_LEFT) { struct wlr_surface *surface = NULL; double sx, sy; - swayc_t *swayc = - swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + struct sway_container *swayc = + container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); sway_seat_set_focus(cursor->seat, swayc); } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 27c2c72e..d421a03f 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -278,7 +278,7 @@ struct sway_input_manager *sway_input_manager_create( } bool sway_input_manager_has_focus(struct sway_input_manager *input, - swayc_t *container) { + struct sway_container *container) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { if (sway_seat_get_focus(seat) == container) { @@ -290,7 +290,7 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, } void sway_input_manager_set_focus(struct sway_input_manager *input, - swayc_t *container) { + struct sway_container *container) { struct sway_seat *seat ; wl_list_for_each(seat, &input->seats, link) { sway_seat_set_focus(seat, container); diff --git a/sway/input/seat.c b/sway/input/seat.c index 648e7914..76d29b52 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,13 +1,13 @@ #define _XOPEN_SOURCE 700 #include #include -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/seat.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" #include "sway/output.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "log.h" static void seat_device_destroy(struct sway_seat_device *seat_device) { @@ -37,7 +37,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, struct sway_seat_container *seat_con = wl_container_of(listener, seat_con, destroy); struct sway_seat *seat = seat_con->seat; - swayc_t *con = seat_con->container; + struct sway_container *con = seat_con->container; bool is_focus = (sway_seat_get_focus(seat) == con); @@ -46,7 +46,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, if (is_focus) { // pick next focus sway_seat_set_focus(seat, NULL); - swayc_t *next = sway_seat_get_focus_inactive(seat, con->parent); + struct sway_container *next = sway_seat_get_focus_inactive(seat, con->parent); if (next == NULL) { next = con->parent; } @@ -59,7 +59,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, } static struct sway_seat_container *seat_container_from_container( - struct sway_seat *seat, swayc_t *con) { + struct sway_seat *seat, struct sway_container *con) { if (con->type < C_WORKSPACE) { // these don't get seat containers ever return NULL; @@ -89,11 +89,11 @@ static struct sway_seat_container *seat_container_from_container( static void handle_new_container(struct wl_listener *listener, void *data) { struct sway_seat *seat = wl_container_of(listener, seat, new_container); - swayc_t *con = data; + struct sway_container *con = data; seat_container_from_container(seat, con); } -static void collect_focus_iter(swayc_t *con, void *data) { +static void collect_focus_iter(struct sway_container *con, void *data) { struct sway_seat *seat = data; if (con->type > C_WORKSPACE) { return; @@ -130,7 +130,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, // init the focus stack wl_list_init(&seat->focus_stack); - container_for_each_bfs(&root_container, collect_focus_iter, seat); + container_for_each_descendent(&root_container, collect_focus_iter, seat); wl_signal_add(&root_container.sway_root->events.new_container, &seat->new_container); @@ -166,7 +166,7 @@ static void seat_configure_keyboard(struct sway_seat *seat, sway_keyboard_configure(seat_device->keyboard); wlr_seat_set_keyboard(seat->wlr_seat, seat_device->input_device->wlr_device); - swayc_t *focus = sway_seat_get_focus(seat); + struct sway_container *focus = sway_seat_get_focus(seat); if (focus && focus->type == C_VIEW) { // force notify reenter to pick up the new configuration wlr_seat_keyboard_clear_focus(seat->wlr_seat); @@ -270,7 +270,7 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { } for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *output_container = root_container.children->items[i]; + struct sway_container *output_container = root_container.children->items[i]; struct wlr_output *output = output_container->sway_output->wlr_output; bool result = @@ -289,8 +289,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { - swayc_t *last_focus = sway_seat_get_focus(seat); +void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container) { + struct sway_container *last_focus = sway_seat_get_focus(seat); if (container && last_focus == container) { return; @@ -330,9 +330,9 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { seat->has_focus = (container != NULL); } -swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container) { +struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { struct sway_seat_container *current = NULL; - swayc_t *parent = NULL; + struct sway_container *parent = NULL; wl_list_for_each(current, &seat->focus_stack, link) { parent = current->container->parent; @@ -351,21 +351,21 @@ swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container return NULL; } -swayc_t *sway_seat_get_focus(struct sway_seat *seat) { +struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { if (!seat->has_focus) { return NULL; } return sway_seat_get_focus_inactive(seat, &root_container); } -swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, - enum swayc_types type) { - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); +struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, + enum sway_container_type type) { + struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); if (focus->type == type) { return focus; } - return swayc_parent_by_type(focus, type); + return container_parent(focus, type); } void sway_seat_set_config(struct sway_seat *seat, diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 977f1ecb..7caa2457 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -3,7 +3,7 @@ #include #include "log.h" #include "sway/ipc-json.h" -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/output.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -25,7 +25,7 @@ json_object *ipc_json_get_version() { return version; } -static json_object *ipc_json_create_rect(swayc_t *c) { +static json_object *ipc_json_create_rect(struct sway_container *c) { json_object *rect = json_object_new_object(); json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); @@ -36,7 +36,7 @@ static json_object *ipc_json_create_rect(swayc_t *c) { return rect; } -static void ipc_json_describe_root(swayc_t *root, json_object *object) { +static void ipc_json_describe_root(struct sway_container *root, json_object *object) { json_object_object_add(object, "type", json_object_new_string("root")); json_object_object_add(object, "layout", json_object_new_string("splith")); } @@ -63,7 +63,7 @@ static const char *ipc_json_get_output_transform(enum wl_output_transform transf return NULL; } -static void ipc_json_describe_output(swayc_t *container, json_object *object) { +static void ipc_json_describe_output(struct sway_container *container, json_object *object) { struct wlr_output *wlr_output = container->sway_output->wlr_output; json_object_object_add(object, "type", json_object_new_string("output")); json_object_object_add(object, "active", json_object_new_boolean(true)); @@ -94,7 +94,7 @@ static void ipc_json_describe_output(swayc_t *container, json_object *object) { json_object_object_add(object, "modes", modes_array); } -static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { +static void ipc_json_describe_workspace(struct sway_container *workspace, json_object *object) { int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; json_object_object_add(object, "num", json_object_new_int(num)); @@ -102,11 +102,11 @@ static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) json_object_object_add(object, "type", json_object_new_string("workspace")); } -static void ipc_json_describe_view(swayc_t *c, json_object *object) { +static void ipc_json_describe_view(struct sway_container *c, json_object *object) { json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); } -json_object *ipc_json_describe_container(swayc_t *c) { +json_object *ipc_json_describe_container(struct sway_container *c) { if (!(sway_assert(c, "Container must not be null."))) { return NULL; } @@ -147,7 +147,7 @@ json_object *ipc_json_describe_container(swayc_t *c) { return object; } -json_object *ipc_json_describe_container_recursive(swayc_t *c) { +json_object *ipc_json_describe_container_recursive(struct sway_container *c) { json_object *object = ipc_json_describe_container(c); int i; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 156de380..50d0bcf3 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -279,7 +279,7 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) } } -void ipc_event_window(swayc_t *window, const char *change) { +void ipc_event_window(struct sway_container *window, const char *change) { wlr_log(L_DEBUG, "Sending window::%s event", change); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(change)); @@ -400,7 +400,7 @@ void ipc_client_handle_command(struct ipc_client *client) { { json_object *outputs = json_object_new_array(); for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *container = root_container.children->items[i]; + struct sway_container *container = root_container.children->items[i]; if (container->type == C_OUTPUT) { json_object_array_add(outputs, ipc_json_describe_container(container)); diff --git a/sway/main.c b/sway/main.c index f2f24be3..ded922ee 100644 --- a/sway/main.c +++ b/sway/main.c @@ -18,7 +18,7 @@ #include #include "sway/config.h" #include "sway/server.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "sway/ipc-server.h" #include "ipc-client.h" #include "readline.h" @@ -382,7 +382,7 @@ int main(int argc, char **argv) { wlr_log(L_INFO, "Starting sway version " SWAY_VERSION); - init_layout(); + layout_init(); if (!server_init(&server)) { return 1; diff --git a/sway/tree/container.c b/sway/tree/container.c index bbafe9ec..40047dcf 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -7,14 +7,14 @@ #include #include #include "sway/config.h" -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/layout.h" +#include "sway/tree/layout.h" #include "sway/output.h" #include "sway/server.h" -#include "sway/view.h" -#include "sway/workspace.h" +#include "sway/tree/view.h" +#include "sway/tree/workspace.h" #include "sway/ipc-server.h" #include "log.h" @@ -33,48 +33,15 @@ static list_t *get_bfs_queue() { return bfs_queue; } -static void notify_new_container(swayc_t *container) { +static void notify_new_container(struct sway_container *container) { wl_signal_emit(&root_container.sway_root->events.new_container, container); ipc_event_window(container, "new"); } -swayc_t *swayc_by_test(swayc_t *container, - bool (*test)(swayc_t *view, void *data), void *data) { - if (!container->children) { - return NULL; - } - // TODO: floating windows - for (int i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - if (test(child, data)) { - return child; - } else { - swayc_t *res = swayc_by_test(child, test, data); - if (res) { - return res; - } - } - } - return NULL; -} - -void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, - void (*func)(swayc_t *item, void *data), void *data) { - for (int i = 0; i < root->children->length; ++i) { - swayc_t *item = root->children->items[i]; - if (item->type == type) { - func(item, data); - } - if (item->children && item->children->length) { - swayc_descendants_of_type(item, type, func, data); - } - } -} - -static swayc_t *new_swayc(enum swayc_types type) { +static struct sway_container *container_create(enum sway_container_type type) { // next id starts at 1 because 0 is assigned to root_container in layout.c static size_t next_id = 1; - swayc_t *c = calloc(1, sizeof(swayc_t)); + struct sway_container *c = calloc(1, sizeof(struct sway_container)); if (!c) { return NULL; } @@ -82,8 +49,6 @@ static swayc_t *new_swayc(enum swayc_types type) { c->layout = L_NONE; c->workspace_layout = L_NONE; c->type = type; - c->nb_master = 1; - c->nb_slave_groups = 1; if (type != C_VIEW) { c->children = create_list(); } @@ -93,18 +58,18 @@ static swayc_t *new_swayc(enum swayc_types type) { return c; } -static void free_swayc(swayc_t *cont) { - if (!sway_assert(cont, "free_swayc passed NULL")) { +static void container_destroy(struct sway_container *cont) { + if (cont == NULL) { return; } wl_signal_emit(&cont->events.destroy, cont); if (cont->children) { - // remove children until there are no more, free_swayc calls - // remove_child, which removes child from this container + // remove children until there are no more, container_destroy calls + // container_remove_child, which removes child from this container while (cont->children->length) { - free_swayc(cont->children->items[0]); + container_destroy(cont->children->items[0]); } list_free(cont->children); } @@ -113,7 +78,7 @@ static void free_swayc(swayc_t *cont) { list_free(cont->marks); } if (cont->parent) { - remove_child(cont); + container_remove_child(cont); } if (cont->name) { free(cont->name); @@ -121,7 +86,8 @@ static void free_swayc(swayc_t *cont) { free(cont); } -swayc_t *new_output(struct sway_output *sway_output) { +struct sway_container *container_output_create( + struct sway_output *sway_output) { struct wlr_box size; wlr_output_effective_resolution(sway_output->wlr_output, &size.width, &size.height); @@ -156,22 +122,22 @@ swayc_t *new_output(struct sway_output *sway_output) { return NULL; } - swayc_t *output = new_swayc(C_OUTPUT); + struct sway_container *output = container_create(C_OUTPUT); output->sway_output = sway_output; output->name = strdup(name); if (output->name == NULL) { - free_swayc(output); + container_destroy(output); return NULL; } apply_output_config(oc, output); - add_child(&root_container, output); + container_add_child(&root_container, output); // Create workspace char *ws_name = workspace_next_name(output->name); wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); - swayc_t *ws = new_workspace(output, ws_name); + struct sway_container *ws = container_workspace_create(output, ws_name); // Set each seat's focus if not already set struct sway_seat *seat = NULL; wl_list_for_each(seat, &input_manager->seats, link) { @@ -185,12 +151,14 @@ swayc_t *new_output(struct sway_output *sway_output) { return output; } -swayc_t *new_workspace(swayc_t *output, const char *name) { - if (!sway_assert(output, "new_workspace called with null output")) { +struct sway_container *container_workspace_create( + struct sway_container *output, const char *name) { + if (!sway_assert(output, + "container_workspace_create called with null output")) { return NULL; } wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); - swayc_t *workspace = new_swayc(C_WORKSPACE); + struct sway_container *workspace = container_create(C_WORKSPACE); workspace->x = output->x; workspace->y = output->y; @@ -198,21 +166,23 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { workspace->height = output->height; workspace->name = !name ? NULL : strdup(name); workspace->prev_layout = L_NONE; - workspace->layout = default_layout(output); - workspace->workspace_layout = default_layout(output); + workspace->layout = container_get_default_layout(output); + workspace->workspace_layout = container_get_default_layout(output); - add_child(output, workspace); - sort_workspaces(output); + container_add_child(output, workspace); + container_sort_workspaces(output); notify_new_container(workspace); return workspace; } -swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { - if (!sway_assert(sibling, "new_view called with NULL sibling/parent")) { +struct sway_container *container_view_create(struct sway_container *sibling, + struct sway_view *sway_view) { + if (!sway_assert(sibling, + "container_view_create called with NULL sibling/parent")) { return NULL; } const char *title = view_get_title(sway_view); - swayc_t *swayc = new_swayc(C_VIEW); + struct sway_container *swayc = container_create(C_VIEW); wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d %s", swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); // Setup values @@ -223,17 +193,18 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { if (sibling->type == C_WORKSPACE) { // Case of focused workspace, just create as child of it - add_child(sibling, swayc); + container_add_child(sibling, swayc); } else { // Regular case, create as sibling of current container - add_sibling(sibling, swayc); + container_add_sibling(sibling, swayc); } notify_new_container(swayc); return swayc; } -swayc_t *destroy_output(swayc_t *output) { - if (!sway_assert(output, "null output passed to destroy_output")) { +struct sway_container *container_output_destroy(struct sway_container *output) { + if (!sway_assert(output, + "null output passed to container_output_destroy")) { return NULL; } @@ -245,12 +216,13 @@ swayc_t *destroy_output(swayc_t *output) { int p = root_container.children->items[0] == output; // Move workspace from this output to another output while (output->children->length) { - swayc_t *child = output->children->items[0]; - remove_child(child); - add_child(root_container.children->items[p], child); + struct sway_container *child = output->children->items[0]; + container_remove_child(child); + container_add_child(root_container.children->items[p], child); } - sort_workspaces(root_container.children->items[p]); - arrange_windows(root_container.children->items[p], -1, -1); + container_sort_workspaces(root_container.children->items[p]); + arrange_windows(root_container.children->items[p], + -1, -1); } } @@ -259,18 +231,18 @@ swayc_t *destroy_output(swayc_t *output) { wl_list_remove(&output->sway_output->mode.link); wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); - free_swayc(output); + container_destroy(output); return &root_container; } -swayc_t *destroy_view(swayc_t *view) { +struct sway_container *container_view_destroy(struct sway_container *view) { if (!view) { return NULL; } wlr_log(L_DEBUG, "Destroying view '%s'", view->name); - swayc_t *parent = view->parent; - free_swayc(view); + struct sway_container *parent = view->parent; + container_destroy(view); // TODO WLR: Destroy empty containers /* @@ -281,7 +253,55 @@ swayc_t *destroy_view(swayc_t *view) { return parent; } -swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { +struct sway_container *container_set_layout(struct sway_container *container, + enum sway_container_layout layout) { + if (container->type == C_WORKSPACE) { + container->workspace_layout = layout; + if (layout == L_HORIZ || layout == L_VERT) { + container->layout = layout; + } + } else { + container->layout = layout; + } + return container; +} + +void container_descendents(struct sway_container *root, + enum sway_container_type type, + void (*func)(struct sway_container *item, void *data), void *data) { + for (int i = 0; i < root->children->length; ++i) { + struct sway_container *item = root->children->items[i]; + if (item->type == type) { + func(item, data); + } + if (item->children && item->children->length) { + container_descendents(item, type, func, data); + } + } +} + +struct sway_container *container_find(struct sway_container *container, + bool (*test)(struct sway_container *view, void *data), void *data) { + if (!container->children) { + return NULL; + } + // TODO: floating windows + for (int i = 0; i < container->children->length; ++i) { + struct sway_container *child = container->children->items[i]; + if (test(child, data)) { + return child; + } else { + struct sway_container *res = container_find(child, test, data); + if (res) { + return res; + } + } + } + return NULL; +} + +struct sway_container *container_parent(struct sway_container *container, + enum sway_container_type type) { if (!sway_assert(container, "container is NULL")) { return NULL; } @@ -294,7 +314,8 @@ swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { return container; } -swayc_t *swayc_at(swayc_t *parent, double lx, double ly, +struct sway_container *container_at(struct sway_container *parent, + double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { list_t *queue = get_bfs_queue(); if (!queue) { @@ -303,13 +324,13 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, list_add(queue, parent); - swayc_t *swayc = NULL; + struct sway_container *swayc = NULL; while (queue->length) { swayc = queue->items[0]; list_del(queue, 0); if (swayc->type == C_VIEW) { struct sway_view *sview = swayc->sway_view; - swayc_t *soutput = swayc_parent_by_type(swayc, C_OUTPUT); + struct sway_container *soutput = container_parent(swayc, C_OUTPUT); struct wlr_box *output_box = wlr_output_layout_get_box( root_container.sway_root->output_layout, @@ -379,30 +400,8 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, return NULL; } -void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { - if (container) { - int i; - if (container->children) { - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - container_map(child, f, data); - } - } - // TODO - /* - if (container->floating) { - for (i = 0; i < container->floating->length; ++i) { - swayc_t *child = container->floating->items[i]; - container_map(child, f, data); - } - } - */ - f(container, data); - } -} - -void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), - void *data) { +void container_for_each_descendent(struct sway_container *con, + void (*f)(struct sway_container *con, void *data), void *data) { list_t *queue = get_bfs_queue(); if (!queue) { return; @@ -415,7 +414,7 @@ void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), list_add(queue, con); - swayc_t *current = NULL; + struct sway_container *current = NULL; while (queue->length) { current = queue->items[0]; list_del(queue, 0); @@ -424,15 +423,3 @@ void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), list_cat(queue, current->children); } } - -swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) { - if (container->type == C_WORKSPACE) { - container->workspace_layout = layout; - if (layout == L_HORIZ || layout == L_VERT) { - container->layout = layout; - } - } else { - container->layout = layout; - } - return container; -} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index de9e7b58..dc0ee5b4 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -6,24 +6,26 @@ #include #include #include -#include "sway/container.h" -#include "sway/layout.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/output.h" -#include "sway/view.h" +#include "sway/tree/view.h" #include "sway/input/seat.h" #include "list.h" #include "log.h" -swayc_t root_container; +struct sway_container root_container; -static void output_layout_change_notify(struct wl_listener *listener, void *data) { +static void output_layout_change_notify(struct wl_listener *listener, + void *data) { struct wlr_box *layout_box = wlr_output_layout_get_box( root_container.sway_root->output_layout, NULL); root_container.width = layout_box->width; root_container.height = layout_box->height; for (int i = 0 ; i < root_container.children->length; ++i) { - swayc_t *output_container = root_container.children->items[i]; + struct sway_container *output_container = + root_container.children->items[i]; if (output_container->type != C_OUTPUT) { continue; } @@ -43,7 +45,7 @@ static void output_layout_change_notify(struct wl_listener *listener, void *data arrange_windows(&root_container, -1, -1); } -void init_layout(void) { +void layout_init(void) { root_container.id = 0; // normally assigned in new_swayc() root_container.type = C_ROOT; root_container.layout = L_NONE; @@ -62,9 +64,9 @@ void init_layout(void) { &root_container.sway_root->output_layout_change); } -static int index_child(const swayc_t *child) { +static int index_child(const struct sway_container *child) { // TODO handle floating - swayc_t *parent = child->parent; + struct sway_container *parent = child->parent; int i, len; len = parent->children->length; for (i = 0; i < len; ++i) { @@ -79,16 +81,18 @@ static int index_child(const swayc_t *child) { return i; } -swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { +struct sway_container *container_add_sibling(struct sway_container *fixed, + struct sway_container *active) { // TODO handle floating - swayc_t *parent = fixed->parent; + struct sway_container *parent = fixed->parent; int i = index_child(fixed); list_insert(parent->children, i + 1, active); active->parent = parent; return active->parent; } -void add_child(swayc_t *parent, swayc_t *child) { +void container_add_child(struct sway_container *parent, + struct sway_container *child) { wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", child, child->type, child->width, child->height, parent, parent->type, parent->width, parent->height); @@ -96,15 +100,17 @@ void add_child(swayc_t *parent, swayc_t *child) { child->parent = parent; // set focus for this container /* TODO WLR - if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) { + if (parent->type == C_WORKSPACE && child->type == C_VIEW && + (parent->workspace_layout == L_TABBED || parent->workspace_layout == + L_STACKED)) { child = new_container(child, parent->workspace_layout); } */ } -swayc_t *remove_child(swayc_t *child) { +struct sway_container *container_remove_child(struct sway_container *child) { int i; - swayc_t *parent = child->parent; + struct sway_container *parent = child->parent; for (i = 0; i < parent->children->length; ++i) { if (parent->children->items[i] == child) { list_del(parent->children, i); @@ -115,7 +121,8 @@ swayc_t *remove_child(swayc_t *child) { return parent; } -enum swayc_layouts default_layout(swayc_t *output) { +enum sway_container_layout container_get_default_layout( + struct sway_container *output) { /* TODO WLR if (config->default_layout != L_NONE) { //return config->default_layout; @@ -129,8 +136,8 @@ enum swayc_layouts default_layout(swayc_t *output) { } static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { - swayc_t *a = *(void **)_a; - swayc_t *b = *(void **)_b; + struct sway_container *a = *(void **)_a; + struct sway_container *b = *(void **)_b; int retval = 0; if (isdigit(a->name[0]) && isdigit(b->name[0])) { @@ -146,21 +153,22 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { return retval; } -void sort_workspaces(swayc_t *output) { +void container_sort_workspaces(struct sway_container *output) { list_stable_sort(output->children, sort_workspace_cmp_qsort); } -static void apply_horiz_layout(swayc_t *container, const double x, +static void apply_horiz_layout(struct sway_container *container, const double x, const double y, const double width, const double height, const int start, const int end); -static void apply_vert_layout(swayc_t *container, const double x, +static void apply_vert_layout(struct sway_container *container, const double x, const double y, const double width, const double height, const int start, const int end); -void arrange_windows(swayc_t *container, double width, double height) { +void arrange_windows(struct sway_container *container, + double width, double height) { int i; if (width == -1 || height == -1) { width = container->width; @@ -181,7 +189,7 @@ void arrange_windows(swayc_t *container, double width, double height) { case C_ROOT: // TODO: wlr_output_layout probably for (i = 0; i < container->children->length; ++i) { - swayc_t *output = container->children->items[i]; + struct sway_container *output = container->children->items[i]; wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); arrange_windows(output, -1, -1); @@ -197,13 +205,14 @@ void arrange_windows(swayc_t *container, double width, double height) { } // arrange all workspaces: for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; + struct sway_container *child = container->children->items[i]; arrange_windows(child, -1, -1); } return; case C_WORKSPACE: { - swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); + struct sway_container *output = + container_parent(container, C_OUTPUT); struct wlr_box *area = &output->sway_output->usable_area; wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", area->width, area->height, area->x, area->y); @@ -252,14 +261,15 @@ void arrange_windows(swayc_t *container, double width, double height) { } } -static void apply_horiz_layout(swayc_t *container, +static void apply_horiz_layout(struct sway_container *container, const double x, const double y, const double width, const double height, const int start, const int end) { double scale = 0; // Calculate total width for (int i = start; i < end; ++i) { - double *old_width = &((swayc_t *)container->children->items[i])->width; + double *old_width = + &((struct sway_container *)container->children->items[i])->width; if (*old_width <= 0) { if (end - start > 1) { *old_width = width / (end - start - 1); @@ -276,7 +286,7 @@ static void apply_horiz_layout(swayc_t *container, if (scale > 0.1) { wlr_log(L_DEBUG, "Arranging %p horizontally", container); for (int i = start; i < end; ++i) { - swayc_t *child = container->children->items[i]; + struct sway_container *child = container->children->items[i]; wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); @@ -301,7 +311,7 @@ static void apply_horiz_layout(swayc_t *container, } } -void apply_vert_layout(swayc_t *container, +void apply_vert_layout(struct sway_container *container, const double x, const double y, const double width, const double height, const int start, const int end) { @@ -309,7 +319,8 @@ void apply_vert_layout(swayc_t *container, double scale = 0; // Calculate total height for (i = start; i < end; ++i) { - double *old_height = &((swayc_t *)container->children->items[i])->height; + double *old_height = + &((struct sway_container *)container->children->items[i])->height; if (*old_height <= 0) { if (end - start > 1) { *old_height = height / (end - start - 1); @@ -326,7 +337,7 @@ void apply_vert_layout(swayc_t *container, if (scale > 0.1) { wlr_log(L_DEBUG, "Arranging %p vertically", container); for (i = start; i < end; ++i) { - swayc_t *child = container->children->items[i]; + struct sway_container *child = container->children->items[i]; wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); @@ -354,15 +365,16 @@ void apply_vert_layout(swayc_t *container, /** * Get swayc in the direction of newly entered output. */ -static swayc_t *get_swayc_in_output_direction(swayc_t *output, - enum movement_direction dir, struct sway_seat *seat) { +static struct sway_container *get_swayc_in_output_direction( + struct sway_container *output, enum movement_direction dir, + struct sway_seat *seat) { if (!output) { return NULL; } - swayc_t *ws = sway_seat_get_focus_inactive(seat, output); + struct sway_container *ws = sway_seat_get_focus_inactive(seat, output); if (ws->type != C_WORKSPACE) { - ws = swayc_parent_by_type(ws, C_WORKSPACE); + ws = container_parent(ws, C_WORKSPACE); } if (ws == NULL) { @@ -380,13 +392,15 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output, return ws->children->items[0]; case MOVE_UP: case MOVE_DOWN: { - swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); + struct sway_container *focused = + sway_seat_get_focus_inactive(seat, ws); if (focused && focused->parent) { - swayc_t *parent = focused->parent; + struct sway_container *parent = focused->parent; if (parent->layout == L_VERT) { if (dir == MOVE_UP) { // get child furthest down on new output - return parent->children->items[parent->children->length-1]; + int idx = parent->children->length - 1; + return parent->children->items[idx]; } else if (dir == MOVE_DOWN) { // get child furthest up on new output return parent->children->items[0]; @@ -404,13 +418,14 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output, return ws; } -static void get_layout_center_position(swayc_t *container, int *x, int *y) { +static void get_layout_center_position(struct sway_container *container, + int *x, int *y) { // FIXME view coords are inconsistently referred to in layout/output systems if (container->type == C_OUTPUT) { *x = container->x + container->width/2; *y = container->y + container->height/2; } else { - swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); + struct sway_container *output = container_parent(container, C_OUTPUT); if (container->type == C_WORKSPACE) { // Workspace coordinates are actually wrong/arbitrary, but should // be same as output. @@ -423,7 +438,8 @@ static void get_layout_center_position(swayc_t *container, int *x, int *y) { } } -static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) { +static bool sway_dir_to_wlr(enum movement_direction dir, + enum wlr_direction *out) { switch (dir) { case MOVE_UP: *out = WLR_DIRECTION_UP; @@ -444,12 +460,12 @@ static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out return true; } -static swayc_t *sway_output_from_wlr(struct wlr_output *output) { +static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { if (output == NULL) { return NULL; } for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *o = root_container.children->items[i]; + struct sway_container *o = root_container.children->items[i]; if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) { return o; } @@ -457,13 +473,14 @@ static swayc_t *sway_output_from_wlr(struct wlr_output *output) { return NULL; } -static swayc_t *get_swayc_in_direction_under(swayc_t *container, - enum movement_direction dir, struct sway_seat *seat, swayc_t *limit) { +static struct sway_container *get_swayc_in_direction_under( + struct sway_container *container, enum movement_direction dir, + struct sway_seat *seat, struct sway_container *limit) { if (dir == MOVE_CHILD) { return sway_seat_get_focus_inactive(seat, container); } - swayc_t *parent = container->parent; + struct sway_container *parent = container->parent; if (dir == MOVE_PARENT) { if (parent->type == C_OUTPUT) { return NULL; @@ -496,9 +513,10 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, /* if (container->type == C_VIEW && swayc_is_fullscreen(container)) { wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); - container = swayc_parent_by_type(container, C_OUTPUT); + container = container_parent(container, C_OUTPUT); get_layout_center_position(container, &abs_pos); - swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); + struct sway_container *output = + swayc_adjacent_output(container, dir, &abs_pos, true); return get_swayc_in_output_direction(output, dir); } if (container->type == C_WORKSPACE && container->fullscreen) { @@ -507,7 +525,7 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, } */ - swayc_t *wrap_candidate = NULL; + struct sway_container *wrap_candidate = NULL; while (true) { // Test if we can even make a difference here bool can_move = false; @@ -521,16 +539,19 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, } int lx, ly; get_layout_center_position(container, &lx, &ly); - struct wlr_output_layout *layout = root_container.sway_root->output_layout; + struct wlr_output_layout *layout = + root_container.sway_root->output_layout; struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output(layout, wlr_dir, container->sway_output->wlr_output, lx, ly); - swayc_t *adjacent = sway_output_from_wlr(wlr_adjacent); + struct sway_container *adjacent = + sway_output_from_wlr(wlr_adjacent); if (!adjacent || adjacent == container) { return wrap_candidate; } - swayc_t *next = get_swayc_in_output_direction(adjacent, dir, seat); + struct sway_container *next = + get_swayc_in_output_direction(adjacent, dir, seat); if (next == NULL) { return NULL; } @@ -570,8 +591,9 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, } } } else { - wlr_log(L_DEBUG, "%s cont %d-%p dir %i sibling %d: %p", __func__, - idx, container, dir, desired, parent->children->items[desired]); + wlr_log(L_DEBUG, + "cont %d-%p dir %i sibling %d: %p", idx, + container, dir, desired, parent->children->items[desired]); return parent->children->items[desired]; } } @@ -587,7 +609,8 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, } } -swayc_t *get_swayc_in_direction(swayc_t *container, struct sway_seat *seat, +struct sway_container *container_get_in_direction( + struct sway_container *container, struct sway_seat *seat, enum movement_direction dir) { return get_swayc_in_direction_under(container, dir, seat, NULL); } diff --git a/sway/tree/view.c b/sway/tree/view.c index 9499adca..d5325c31 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,8 +1,8 @@ #include #include -#include "sway/container.h" -#include "sway/layout.h" -#include "sway/view.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" +#include "sway/tree/view.h" const char *view_get_title(struct sway_view *view) { if (view->iface.get_prop) { @@ -45,6 +45,7 @@ void view_set_size(struct sway_view *view, int width, int height) { } } +// TODO make view coordinates in layout coordinates void view_set_position(struct sway_view *view, double ox, double oy) { if (view->iface.set_position) { struct wlr_box box = { diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 861fda4d..ba04c55c 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -3,10 +3,10 @@ #include #include #include -#include "sway/container.h" +#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/workspace.h" +#include "sway/tree/workspace.h" #include "log.h" #include "util.h" @@ -17,7 +17,7 @@ struct workspace_by_number_data { const char *name; }; -void next_name_map(swayc_t *ws, void *data) { +void next_name_map(struct sway_container *ws, void *data) { int *count = data; ++count; } @@ -37,7 +37,7 @@ char *workspace_next_name(const char *output_name) { return name; } -static bool _workspace_by_number(swayc_t *view, void *data) { +static bool _workspace_by_number(struct sway_container *view, void *data) { if (view->type != C_WORKSPACE) { return false; } @@ -46,27 +46,28 @@ static bool _workspace_by_number(swayc_t *view, void *data) { return a == wbnd->len && strncmp(view->name, wbnd->name, a) == 0; } -swayc_t *workspace_by_number(const char* name) { +struct sway_container *workspace_by_number(const char* name) { struct workspace_by_number_data wbnd = {0, "1234567890", name}; wbnd.len = strspn(name, wbnd.cset); if (wbnd.len <= 0) { return NULL; } - return swayc_by_test(&root_container, _workspace_by_number, (void *) &wbnd); + return container_find(&root_container, + _workspace_by_number, (void *) &wbnd); } -static bool _workspace_by_name(swayc_t *view, void *data) { +static bool _workspace_by_name(struct sway_container *view, void *data) { return (view->type == C_WORKSPACE) && (strcasecmp(view->name, (char *) data) == 0); } -swayc_t *workspace_by_name(const char *name) { +struct sway_container *workspace_by_name(const char *name) { struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *current_workspace = NULL, *current_output = NULL; - swayc_t *focus = sway_seat_get_focus(seat); + struct sway_container *current_workspace = NULL, *current_output = NULL; + struct sway_container *focus = sway_seat_get_focus(seat); if (focus) { - current_workspace = swayc_parent_by_type(focus, C_WORKSPACE); - current_output = swayc_parent_by_type(focus, C_OUTPUT); + current_workspace = container_parent(focus, C_WORKSPACE); + current_output = container_parent(focus, C_OUTPUT); } if (strcmp(name, "prev") == 0) { return workspace_prev(current_workspace); @@ -79,12 +80,13 @@ swayc_t *workspace_by_name(const char *name) { } else if (strcmp(name, "current") == 0) { return current_workspace; } else { - return swayc_by_test(&root_container, _workspace_by_name, (void *) name); + return container_find(&root_container, _workspace_by_name, + (void *)name); } } -swayc_t *workspace_create(const char *name) { - swayc_t *parent; +struct sway_container *workspace_create(const char *name) { + struct sway_container *parent; // Search for workspace<->output pair int i, e = config->workspace_outputs->length; for (i = 0; i < e; ++i) { @@ -95,7 +97,7 @@ swayc_t *workspace_create(const char *name) { for (i = 0; i < e; ++i) { parent = root_container.children->items[i]; if (strcmp(parent->name, wso->output) == 0) { - return new_workspace(parent, name); + return container_workspace_create(parent, name); } } break; @@ -103,10 +105,11 @@ swayc_t *workspace_create(const char *name) { } // Otherwise create a new one struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *focus = + sway_seat_get_focus_inactive(seat, &root_container); parent = focus; - parent = swayc_parent_by_type(parent, C_OUTPUT); - return new_workspace(parent, name); + parent = container_parent(parent, C_OUTPUT); + return container_workspace_create(parent, name); } /** @@ -114,17 +117,18 @@ swayc_t *workspace_create(const char *name) { * the end and beginning. If next is false, the previous workspace is returned, * otherwise the next one is returned. */ -swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { +struct sway_container *workspace_output_prev_next_impl( + struct sway_container *output, bool next) { if (!sway_assert(output->type == C_OUTPUT, "Argument must be an output, is %d", output->type)) { return NULL; } struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, output); - swayc_t *workspace = (focus->type == C_WORKSPACE ? + struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); + struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : - swayc_parent_by_type(focus, C_WORKSPACE)); + container_parent(focus, C_WORKSPACE)); int i; for (i = 0; i < output->children->length; i++) { @@ -134,7 +138,8 @@ swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { } } - // Doesn't happen, at worst the for loop returns the previously active workspace + // Doesn't happen, at worst the for loop returns the previously active + // workspace return NULL; } @@ -144,13 +149,14 @@ swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { * next is false, the previous workspace is returned, otherwise the next one is * returned. */ -swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) { +struct sway_container *workspace_prev_next_impl( + struct sway_container *workspace, bool next) { if (!sway_assert(workspace->type == C_WORKSPACE, "Argument must be a workspace, is %d", workspace->type)) { return NULL; } - swayc_t *current_output = workspace->parent; + struct sway_container *current_output = workspace->parent; int offset = next ? 1 : -1; int start = next ? 0 : 1; int end; @@ -166,54 +172,57 @@ swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) { } } - // Given workspace is the first/last on the output, jump to the previous/next output + // Given workspace is the first/last on the output, jump to the + // previous/next output int num_outputs = root_container.children->length; for (i = 0; i < num_outputs; i++) { if (root_container.children->items[i] == current_output) { - swayc_t *next_output = root_container.children->items[ + struct sway_container *next_output = root_container.children->items[ wrap(i + offset, num_outputs)]; return workspace_output_prev_next_impl(next_output, next); } } - // Doesn't happen, at worst the for loop returns the previously active workspace on the active output + // Doesn't happen, at worst the for loop returns the previously active + // workspace on the active output return NULL; } -swayc_t *workspace_output_next(swayc_t *current) { +struct sway_container *workspace_output_next(struct sway_container *current) { return workspace_output_prev_next_impl(current, true); } -swayc_t *workspace_next(swayc_t *current) { +struct sway_container *workspace_next(struct sway_container *current) { return workspace_prev_next_impl(current, true); } -swayc_t *workspace_output_prev(swayc_t *current) { +struct sway_container *workspace_output_prev(struct sway_container *current) { return workspace_output_prev_next_impl(current, false); } -swayc_t *workspace_prev(swayc_t *current) { +struct sway_container *workspace_prev(struct sway_container *current) { return workspace_prev_next_impl(current, false); } -bool workspace_switch(swayc_t *workspace) { +bool workspace_switch(struct sway_container *workspace) { if (!workspace) { return false; } struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + struct sway_container *focus = + sway_seat_get_focus_inactive(seat, &root_container); if (!seat || !focus) { return false; } - swayc_t *active_ws = focus; + struct sway_container *active_ws = focus; if (active_ws->type != C_WORKSPACE) { - swayc_parent_by_type(focus, C_WORKSPACE); + container_parent(focus, C_WORKSPACE); } if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { - swayc_t *new_ws = workspace_by_name(prev_workspace_name); + struct sway_container *new_ws = workspace_by_name(prev_workspace_name); workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); } @@ -230,13 +239,14 @@ bool workspace_switch(swayc_t *workspace) { // TODO: Deal with sticky containers - wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); - swayc_t *next = sway_seat_get_focus_inactive(seat, workspace); + wlr_log(L_DEBUG, "Switching to workspace %p:%s", + workspace, workspace->name); + struct sway_container *next = sway_seat_get_focus_inactive(seat, workspace); if (next == NULL) { next = workspace; } sway_seat_set_focus(seat, next); - swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); + struct sway_container *output = container_parent(workspace, C_OUTPUT); arrange_windows(output, -1, -1); return true; } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 93d1219c..2d2b3b69 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -352,7 +352,7 @@ void ipc_bar_init(struct bar *bar, const char *bar_id) { } // add bar to the output - struct output *bar_output = new_output(name); + struct output *bar_output = container_output_create(name); bar_output->idx = i; list_add(bar->outputs, bar_output); } -- cgit v1.2.3 From 9b38ef950fcf293ba11f54c14d8b3a87f050b154 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 10:11:15 -0400 Subject: Implement focus_follows_mouse Also contains two other small changes: - Clicking any button will focus the container clicked (not just left) - Remove seamless_mouse (doesn't make sense on wlroots) --- include/sway/config.h | 1 - sway/commands.c | 1 + sway/commands/focus_follows_mouse.c | 12 +++++++++ sway/config.c | 1 - sway/input/cursor.c | 53 +++++++++++++++++++------------------ sway/meson.build | 1 + 6 files changed, 41 insertions(+), 28 deletions(-) create mode 100644 sway/commands/focus_follows_mouse.c (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index ac1105b4..03b51948 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -304,7 +304,6 @@ struct sway_config { bool reloading; bool reading; bool auto_back_and_forth; - bool seamless_mouse; bool show_marks; bool edge_gaps; diff --git a/sway/commands.c b/sway/commands.c index d983dcbb..90544220 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -98,6 +98,7 @@ static struct cmd_handler handlers[] = { { "bindsym", cmd_bindsym }, { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, + { "focus_follows_mouse", cmd_focus_follows_mouse }, { "include", cmd_include }, { "input", cmd_input }, { "mode", cmd_mode }, diff --git a/sway/commands/focus_follows_mouse.c b/sway/commands/focus_follows_mouse.c new file mode 100644 index 00000000..661e7852 --- /dev/null +++ b/sway/commands/focus_follows_mouse.c @@ -0,0 +1,12 @@ +#include +#include +#include "sway/commands.h" + +struct cmd_results *cmd_focus_follows_mouse(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1))) { + return error; + } + config->focus_follows_mouse = !strcasecmp(argv[0], "yes"); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index e9e7057d..0eecf7f6 100644 --- a/sway/config.c +++ b/sway/config.c @@ -178,7 +178,6 @@ static void config_defaults(struct sway_config *config) { config->active = false; config->failed = false; config->auto_back_and_forth = false; - config->seamless_mouse = true; config->reading = false; config->show_marks = true; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 9cdd66d8..35dd5dc8 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -125,7 +125,10 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, struct wlr_seat *seat = cursor->seat->wlr_seat; struct wlr_surface *surface = NULL; double sx, sy; - container_at_cursor(cursor, &surface, &sx, &sy); + struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); + if (c && config->focus_follows_mouse) { + sway_seat_set_focus(cursor->seat, c); + } // reset cursor if switching between clients struct wl_client *client = NULL; @@ -170,33 +173,31 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, button); struct wlr_event_pointer_button *event = data; - if (event->button == BTN_LEFT) { - struct wlr_surface *surface = NULL; - double sx, sy; - struct sway_container *cont = - container_at_cursor(cursor, &surface, &sx, &sy); - // Avoid moving keyboard focus from a surface that accepts it to one - // that does not unless the change would move us to a new workspace. - // - // This prevents, for example, losing focus when clicking on swaybar. - // - // TODO: Replace this condition with something like - // !surface_accepts_keyboard_input - if (surface && cont && cont->type != C_VIEW) { - struct sway_container *new_ws = cont; - if (new_ws && new_ws->type != C_WORKSPACE) { - new_ws = container_parent(new_ws, C_WORKSPACE); - } - struct sway_container *old_ws = sway_seat_get_focus(cursor->seat); - if (old_ws && old_ws->type != C_WORKSPACE) { - old_ws = container_parent(old_ws, C_WORKSPACE); - } - if (new_ws != old_ws) { - sway_seat_set_focus(cursor->seat, cont); - } - } else { + struct wlr_surface *surface = NULL; + double sx, sy; + struct sway_container *cont = + container_at_cursor(cursor, &surface, &sx, &sy); + // Avoid moving keyboard focus from a surface that accepts it to one + // that does not unless the change would move us to a new workspace. + // + // This prevents, for example, losing focus when clicking on swaybar. + // + // TODO: Replace this condition with something like + // !surface_accepts_keyboard_input + if (surface && cont && cont->type != C_VIEW) { + struct sway_container *new_ws = cont; + if (new_ws && new_ws->type != C_WORKSPACE) { + new_ws = container_parent(new_ws, C_WORKSPACE); + } + struct sway_container *old_ws = sway_seat_get_focus(cursor->seat); + if (old_ws && old_ws->type != C_WORKSPACE) { + old_ws = container_parent(old_ws, C_WORKSPACE); + } + if (new_ws != old_ws) { sway_seat_set_focus(cursor->seat, cont); } + } else { + sway_seat_set_focus(cursor->seat, cont); } wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, diff --git a/sway/meson.build b/sway/meson.build index 5bc57964..0cc620ea 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -13,6 +13,7 @@ sway_sources = files( 'commands/exec.c', 'commands/exec_always.c', 'commands/focus.c', + 'commands/focus_follows_mouse.c', 'commands/kill.c', 'commands/include.c', 'commands/input.c', -- cgit v1.2.3 From 35445b40a273ca1548915e1f17097a45aebbd44c Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 12:16:00 -0400 Subject: remove unused attachment config --- include/sway/config.h | 27 ++++++++++++++++++++++++++- include/sway/input/seat.h | 1 - sway/input/seat.c | 10 ---------- 3 files changed, 26 insertions(+), 12 deletions(-) (limited to 'include/sway/config.h') diff --git a/include/sway/config.h b/include/sway/config.h index 03b51948..91f772b5 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -377,6 +377,7 @@ void free_config(struct sway_config *config); void config_clear_handler_context(struct sway_config *config); void free_sway_variable(struct sway_variable *var); + /** * Does variable replacement for a string based on the config's currently loaded variables. */ @@ -385,44 +386,68 @@ char *do_var_replacement(char *str); struct cmd_results *check_security_config(); int input_identifier_cmp(const void *item, const void *data); + struct input_config *new_input_config(const char* identifier); + void merge_input_config(struct input_config *dst, struct input_config *src); + struct input_config *copy_input_config(struct input_config *ic); + void free_input_config(struct input_config *ic); + void apply_input_config(struct input_config *input); int seat_name_cmp(const void *item, const void *data); + struct seat_config *new_seat_config(const char* name); + void merge_seat_config(struct seat_config *dst, struct seat_config *src); + struct seat_config *copy_seat_config(struct seat_config *seat); + void free_seat_config(struct seat_config *ic); + struct seat_attachment_config *seat_attachment_config_new(); + struct seat_attachment_config *seat_config_get_attachment( struct seat_config *seat_config, char *identifier); + void apply_seat_config(struct seat_config *seat); int output_name_cmp(const void *item, const void *data); + void output_get_identifier(char *identifier, size_t len, struct sway_output *output); + struct output_config *new_output_config(const char *name); + void merge_output_config(struct output_config *dst, struct output_config *src); + void apply_output_config(struct output_config *oc, struct sway_container *output); + void free_output_config(struct output_config *oc); int workspace_output_cmp_workspace(const void *a, const void *b); int sway_binding_cmp(const void *a, const void *b); + int sway_binding_cmp_qsort(const void *a, const void *b); + int sway_binding_cmp_keys(const void *a, const void *b); + void free_sway_binding(struct sway_binding *sb); + struct sway_binding *sway_binding_dup(struct sway_binding *sb); -/* Bar stuff */ void load_swaybars(); + void invoke_swaybar(struct bar_config *bar); + void terminate_swaybg(pid_t pid); + struct bar_config *default_bar_config(void); + void free_bar_config(struct bar_config *bar); /* Global config singleton. */ diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 3a1cf350..5c3c2c4f 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -8,7 +8,6 @@ struct sway_seat_device { struct sway_seat *sway_seat; struct sway_input_device *input_device; struct sway_keyboard *keyboard; - struct seat_attachment_config *attachment_config; struct wl_list link; // sway_seat::devices }; diff --git a/sway/input/seat.c b/sway/input/seat.c index 38b617b7..27636c1e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -202,13 +202,6 @@ void seat_configure_device(struct sway_seat *seat, return; } - struct seat_config *seat_config = seat_get_config(seat); - - if (seat_config) { - seat_device->attachment_config = - seat_config_get_attachment(seat_config, input_device->identifier); - } - switch (input_device->wlr_device->type) { case WLR_INPUT_DEVICE_POINTER: seat_configure_pointer(seat, seat_device); @@ -426,9 +419,6 @@ struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config) { struct sway_seat_device *seat_device = NULL; - wl_list_for_each(seat_device, &seat->devices, link) { - seat_device->attachment_config = NULL; - } if (!seat_config) { return; -- cgit v1.2.3 From 0e3ddf255ef56b7fe2b868232b80d04ea961120b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 8 Apr 2018 14:15:13 -0400 Subject: Add input "identifier" map_to_output "identifier" --- include/sway/commands.h | 1 + include/sway/config.h | 4 +++- sway/commands.c | 1 + sway/commands/input/map_to_output.c | 27 +++++++++++++++++++++++++++ sway/config/input.c | 4 ++++ sway/input/seat.c | 30 ++++++++++++++++++++++++++++++ sway/meson.build | 1 + sway/sway-input.5.txt | 20 ++++++++++++++++++++ 8 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 sway/commands/input/map_to_output.c (limited to 'include/sway/config.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index edb5a213..bc5d5412 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -192,6 +192,7 @@ sway_cmd input_cmd_drag_lock; sway_cmd input_cmd_dwt; sway_cmd input_cmd_events; sway_cmd input_cmd_left_handed; +sway_cmd input_cmd_map_to_output; sway_cmd input_cmd_middle_emulation; sway_cmd input_cmd_natural_scroll; sway_cmd input_cmd_pointer_accel; diff --git a/include/sway/config.h b/include/sway/config.h index 91f772b5..ed49fbbd 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -52,7 +52,7 @@ struct sway_mode { }; /** - * libinput options for input devices + * options for input devices */ struct input_config { char *identifier; @@ -75,6 +75,8 @@ struct input_config { char *xkb_rules; char *xkb_variant; + char *mapped_output; + bool capturable; struct wlr_box region; }; diff --git a/sway/commands.c b/sway/commands.c index 20b8a2aa..55929659 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -187,6 +187,7 @@ static struct cmd_handler input_handlers[] = { { "dwt", input_cmd_dwt }, { "events", input_cmd_events }, { "left_handed", input_cmd_left_handed }, + { "map_to_output", input_cmd_map_to_output }, { "middle_emulation", input_cmd_middle_emulation }, { "natural_scroll", input_cmd_natural_scroll }, { "pointer_accel", input_cmd_pointer_accel }, diff --git a/sway/commands/input/map_to_output.c b/sway/commands/input/map_to_output.c new file mode 100644 index 00000000..60e4608e --- /dev/null +++ b/sway/commands/input/map_to_output.c @@ -0,0 +1,27 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include "sway/config.h" +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_map_to_output(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "map_to_output", EXPECTED_EQUAL_TO, 1))) { + return error; + } + struct input_config *current_input_config = + config->handler_context.input_config; + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "map_to_output", + "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + new_config->mapped_output = strdup(argv[0]); + apply_input_config(new_config); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config/input.c b/sway/config/input.c index c4f6211d..5e657c43 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -88,6 +88,10 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { free(dst->xkb_variant); dst->xkb_variant = strdup(src->xkb_variant); } + if (src->mapped_output) { + free(dst->mapped_output); + dst->mapped_output = strdup(src->mapped_output); + } } struct input_config *copy_input_config(struct input_config *ic) { diff --git a/sway/input/seat.c b/sway/input/seat.c index d9b42828..7b01fe88 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,6 +1,7 @@ #define _XOPEN_SOURCE 700 #define _POSIX_C_SOURCE 199309L #include +#include #include #include #include @@ -219,10 +220,38 @@ struct sway_seat *seat_create(struct sway_input_manager *input, return seat; } +static void seat_apply_input_config(struct sway_seat *seat, + struct sway_seat_device *sway_device) { + struct input_config *ic = input_device_get_config( + sway_device->input_device); + if (!ic) { + return; + } + wlr_log(L_DEBUG, "Applying input config to %s", + sway_device->input_device->identifier); + if (ic->mapped_output) { + struct sway_container *output = NULL; + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *_output = root_container.children->items[i]; + if (strcasecmp(_output->name, ic->mapped_output) == 0) { + output = _output; + break; + } + } + if (output) { + wlr_cursor_map_input_to_output(seat->cursor->cursor, + sway_device->input_device->wlr_device, + output->sway_output->wlr_output); + wlr_log(L_DEBUG, "Mapped to output %s", output->name); + } + } +} + static void seat_configure_pointer(struct sway_seat *seat, struct sway_seat_device *sway_device) { wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); + seat_apply_input_config(seat, sway_device); } static void seat_configure_keyboard(struct sway_seat *seat, @@ -249,6 +278,7 @@ static void seat_configure_tablet_tool(struct sway_seat *seat, struct sway_seat_device *sway_device) { wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); + seat_apply_input_config(seat, sway_device); } static struct sway_seat_device *seat_get_device(struct sway_seat *seat, diff --git a/sway/meson.build b/sway/meson.build index 2521069f..d0730296 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -85,6 +85,7 @@ sway_sources = files( 'commands/input/dwt.c', 'commands/input/events.c', 'commands/input/left_handed.c', + 'commands/input/map_to_output.c', 'commands/input/middle_emulation.c', 'commands/input/natural_scroll.c', 'commands/input/pointer_accel.c', diff --git a/sway/sway-input.5.txt b/sway/sway-input.5.txt index 0603616b..05725360 100644 --- a/sway/sway-input.5.txt +++ b/sway/sway-input.5.txt @@ -40,6 +40,26 @@ For more information on these xkb configuration options, see **input** xkb_variant :: Sets the variant of the keyboard like _dvorak_ or _colemak_. +Mapping Configuration +--------------------- + +**input** map_to_output :: + Maps inputs from this device to the specified output. Only meaningful if the + device is a pointer, touch, or drawing tablet device. + +**input** map_to_region :: + Maps inputs from this device to the specified region of the global output + layout. Only meaningful if the device is a pointer, touch, or drawing tablet + device. + +**input** map_region :: + Ignores inputs from this device that do not occur within the specified region. + Can be in millimeters (e.g. 10mmx20mm\@10mm,20mm) or in terms of 0..1 (e.g. + 0.5x0.5\@0,0). Not all devices support millimeters. Only meaningful if the + device is not a keyboard an provides events in absolute terms (such as a + drawing tablet or touch screen - most pointers provide events relative to the + previous frame). + Libinput Configuration ~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3