From 6edc32848f67fe3ea370e12b64019cef6c137840 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 11 Oct 2017 21:04:56 -0400 Subject: [PATCH 001/522] Find and link to wlroots --- CMake/FindWlroots.cmake | 20 ++++++++++++++++++++ CMakeLists.txt | 1 + sway/CMakeLists.txt | 2 ++ 3 files changed, 23 insertions(+) create mode 100644 CMake/FindWlroots.cmake diff --git a/CMake/FindWlroots.cmake b/CMake/FindWlroots.cmake new file mode 100644 index 000000000..0e349d3ac --- /dev/null +++ b/CMake/FindWlroots.cmake @@ -0,0 +1,20 @@ +# - Find wlroots +# Find the wlroots libraries +# +# This module defines the following variables: +# WLR_FOUND - True if wlroots is found +# WLR_LIBRARIES - wlroots libraries +# WLR_INCLUDE_DIRS - wlroots include directories +# WLR_DEFINITIONS - Compiler switches required for using wlroots +# + +find_package(PkgConfig) +pkg_check_modules(PC_WLR QUIET wlroots) +find_path(WLR_INCLUDE_DIRS NAMES wlr/config.h HINTS ${PC_WLR_INCLUDE_DIRS}) +find_library(WLR_LIBRARIES NAMES wlroots HINTS ${PC_WLR_LIBRARY_DIRS}) + +set(WLR_DEFINITIONS ${PC_WLR_CFLAGS_OTHER}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(wlr DEFAULT_MSG WLR_LIBRARIES WLR_INCLUDE_DIRS) +mark_as_advanced(WLR_LIBRARIES WLR_INCLUDE_DIRS) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc5215708..34098eb36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ endif() find_package(JsonC 0.12.1 REQUIRED) find_package(PCRE REQUIRED) find_package(WLC REQUIRED) +find_package(Wlroots REQUIRED) find_package(Wayland REQUIRED) find_package(XKBCommon REQUIRED) find_package(Cairo REQUIRED) diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 48f7a7a82..67af0f70f 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories( ${PROTOCOLS_INCLUDE_DIRS} ${WLC_INCLUDE_DIRS} + ${WLR_INCLUDE_DIRS} ${PCRE_INCLUDE_DIRS} ${JSONC_INCLUDE_DIRS} ${XKBCOMMON_INCLUDE_DIRS} @@ -48,6 +49,7 @@ target_link_libraries(sway sway-protocols sway-wayland ${WLC_LIBRARIES} + ${WLR_LIBRARIES} ${XKBCOMMON_LIBRARIES} ${PCRE_LIBRARIES} ${JSONC_LIBRARIES} From 7c448b408126aef0561be0761871f968921d7db0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 22 Oct 2017 10:37:30 -0400 Subject: [PATCH 002/522] Fire up the wlroots backend and run the event loop --- include/sway/extensions.h | 56 ------ include/sway/server.h | 31 +++ sway/CMakeLists.txt | 3 +- sway/commands.c | 2 + sway/extensions.c | 407 -------------------------------------- sway/focus.c | 3 +- sway/ipc-server.c | 389 +++--------------------------------- sway/layout.c | 5 +- sway/main.c | 113 +++++------ sway/server.c | 54 +++++ sway/workspace.c | 1 - 11 files changed, 160 insertions(+), 904 deletions(-) delete mode 100644 include/sway/extensions.h create mode 100644 include/sway/server.h delete mode 100644 sway/extensions.c create mode 100644 sway/server.c diff --git a/include/sway/extensions.h b/include/sway/extensions.h deleted file mode 100644 index 5212eb3a2..000000000 --- a/include/sway/extensions.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _SWAY_EXTENSIONS_H -#define _SWAY_EXTENSIONS_H - -#include -#include -#include "wayland-desktop-shell-server-protocol.h" -#include "list.h" - -struct background_config { - wlc_handle output; - wlc_resource surface; - // we need the wl_resource of the surface in the destructor - struct wl_resource *wl_surface_res; - struct wl_client *client; - wlc_handle handle; -}; - -struct panel_config { - // wayland resource used in callbacks, is used to track this panel - struct wl_resource *wl_resource; - wlc_handle output; - wlc_resource surface; - // we need the wl_resource of the surface in the destructor - struct wl_resource *wl_surface_res; - enum desktop_shell_panel_position panel_position; - // used to determine if client is a panel - struct wl_client *client; - // wlc handle for this panel's surface, not set until panel is created - wlc_handle handle; -}; - -struct desktop_shell_state { - list_t *backgrounds; - list_t *panels; - list_t *lock_surfaces; - bool is_locked; -}; - -struct swaylock_state { - bool active; - wlc_handle output; - wlc_resource surface; -}; - -struct decoration_state { - list_t *csd_resources; -}; - -extern struct desktop_shell_state desktop_shell; -extern struct decoration_state decoration_state; - -void register_extensions(void); - -void server_decoration_enable_csd(wlc_handle handle); - -#endif diff --git a/include/sway/server.h b/include/sway/server.h new file mode 100644 index 000000000..471a0270b --- /dev/null +++ b/include/sway/server.h @@ -0,0 +1,31 @@ +#ifndef _SWAY_SERVER_H +#define _SWAY_SERVER_H +#include +#include +#include +#include +#include +#include +// TODO WLR: make Xwayland optional +#include + +struct sway_server { + // TODO WLR + //struct roots_desktop *desktop; + //struct roots_input *input; + + struct wl_display *wl_display; + struct wl_event_loop *wl_event_loop; + + struct wlr_backend *backend; + struct wlr_renderer *renderer; + + struct wlr_data_device_manager *data_device_manager; +}; + +bool server_init(struct sway_server *server); +void server_fini(struct sway_server *server); + +struct sway_server server; + +#endif diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 67af0f70f..ac0530e5d 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -25,9 +25,7 @@ add_executable(sway container.c criteria.c debug_log.c - extensions.c focus.c - handlers.c input.c input_state.c ipc-json.c @@ -38,6 +36,7 @@ add_executable(sway workspace.c border.c security.c + server.c ) add_definitions( diff --git a/sway/commands.c b/sway/commands.c index c7dbf7315..e11818934 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -120,6 +120,7 @@ void input_cmd_apply(struct input_config *input) { // 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]; @@ -134,6 +135,7 @@ void input_cmd_apply(struct input_config *input) { break; } } + */ } } diff --git a/sway/extensions.c b/sway/extensions.c deleted file mode 100644 index 917465610..000000000 --- a/sway/extensions.c +++ /dev/null @@ -1,407 +0,0 @@ -#include -#include -#include -#include -#include "wayland-desktop-shell-server-protocol.h" -#include "wayland-swaylock-server-protocol.h" -#include "wayland-gamma-control-server-protocol.h" -#include "wayland-server-decoration-server-protocol.h" -#include "sway/layout.h" -#include "sway/input_state.h" -#include "sway/extensions.h" -#include "sway/security.h" -#include "sway/ipc-server.h" -#include "log.h" - -struct desktop_shell_state desktop_shell; -struct decoration_state decoration_state; - -static struct panel_config *find_or_create_panel_config(struct wl_resource *resource) { - for (int i = 0; i < desktop_shell.panels->length; i++) { - struct panel_config *conf = desktop_shell.panels->items[i]; - if (conf->wl_resource == resource) { - sway_log(L_DEBUG, "Found existing panel config for resource %p", resource); - return conf; - } - } - sway_log(L_DEBUG, "Creating panel config for resource %p", resource); - struct panel_config *config = calloc(1, sizeof(struct panel_config)); - if (!config) { - sway_log(L_ERROR, "Unable to create panel config"); - return NULL; - } - list_add(desktop_shell.panels, config); - config->wl_resource = resource; - return config; -} - -void background_surface_destructor(struct wl_resource *resource) { - sway_log(L_DEBUG, "Background surface killed"); - int i; - for (i = 0; i < desktop_shell.backgrounds->length; ++i) { - struct background_config *config = desktop_shell.backgrounds->items[i]; - if (config->wl_surface_res == resource) { - list_del(desktop_shell.backgrounds, i); - break; - } - } -} - -void panel_surface_destructor(struct wl_resource *resource) { - sway_log(L_DEBUG, "Panel surface killed"); - int i; - for (i = 0; i < desktop_shell.panels->length; ++i) { - struct panel_config *config = desktop_shell.panels->items[i]; - if (config->wl_surface_res == resource) { - list_del(desktop_shell.panels, i); - arrange_windows(&root_container, -1, -1); - break; - } - } -} - -void lock_surface_destructor(struct wl_resource *resource) { - sway_log(L_DEBUG, "Lock surface killed"); - int i; - for (i = 0; i < desktop_shell.lock_surfaces->length; ++i) { - struct wl_resource *surface = desktop_shell.lock_surfaces->items[i]; - if (surface == resource) { - list_del(desktop_shell.lock_surfaces, i); - arrange_windows(&root_container, -1, -1); - break; - } - } - if (desktop_shell.lock_surfaces->length == 0) { - sway_log(L_DEBUG, "Desktop shell unlocked"); - desktop_shell.is_locked = false; - - // We need to now give focus back to the focus which we internally - // track, since when we lock sway we don't actually change our internal - // focus tracking. - swayc_t *focus = get_focused_container(swayc_active_workspace()); - set_focused_container(focus); - wlc_view_focus(focus->handle); - } -} - -static void set_background(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *_output, struct wl_resource *surface) { - pid_t pid; - wl_client_get_credentials(client, &pid, NULL, NULL); - if (!(get_feature_policy_mask(pid) & FEATURE_BACKGROUND)) { - sway_log(L_INFO, "Denying background feature to %d", pid); - return; - } - wlc_handle output = wlc_handle_from_wl_output_resource(_output); - if (!output) { - return; - } - sway_log(L_DEBUG, "Setting surface %p as background for output %d", surface, (int)output); - struct background_config *config = malloc(sizeof(struct background_config)); - if (!config) { - sway_log(L_ERROR, "Unable to allocate background config"); - return; - } - config->client = client; - config->output = output; - config->surface = wlc_resource_from_wl_surface_resource(surface); - config->wl_surface_res = surface; - list_add(desktop_shell.backgrounds, config); - wl_resource_set_destructor(surface, background_surface_destructor); - arrange_windows(swayc_by_handle(output), -1, -1); - wlc_output_schedule_render(config->output); -} - -static void set_panel(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *_output, struct wl_resource *surface) { - pid_t pid; - wl_client_get_credentials(client, &pid, NULL, NULL); - if (!(get_feature_policy_mask(pid) & FEATURE_PANEL)) { - sway_log(L_INFO, "Denying panel feature to %d", pid); - return; - } - wlc_handle output = wlc_handle_from_wl_output_resource(_output); - if (!output) { - return; - } - sway_log(L_DEBUG, "Setting surface %p as panel for output %d (wl_resource: %p)", surface, (int)output, resource); - struct panel_config *config = find_or_create_panel_config(resource); - config->output = output; - config->client = client; - config->surface = wlc_resource_from_wl_surface_resource(surface); - config->wl_surface_res = surface; - wl_resource_set_destructor(surface, panel_surface_destructor); - arrange_windows(&root_container, -1, -1); - wlc_output_schedule_render(config->output); -} - -static void desktop_set_lock_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface) { - sway_log(L_ERROR, "desktop_set_lock_surface is not currently supported"); -} - -static void desktop_unlock(struct wl_client *client, struct wl_resource *resource) { - sway_log(L_ERROR, "desktop_unlock is not currently supported"); -} - -static void set_grab_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface) { - sway_log(L_ERROR, "desktop_set_grab_surface is not currently supported"); -} - -static void desktop_ready(struct wl_client *client, struct wl_resource *resource) { - // nop -} - -static void set_panel_position(struct wl_client *client, struct wl_resource *resource, uint32_t position) { - pid_t pid; - wl_client_get_credentials(client, &pid, NULL, NULL); - if (!(get_feature_policy_mask(pid) & FEATURE_PANEL)) { - sway_log(L_INFO, "Denying panel feature to %d", pid); - return; - } - struct panel_config *config = find_or_create_panel_config(resource); - sway_log(L_DEBUG, "Panel position for wl_resource %p changed %d => %d", resource, config->panel_position, position); - config->panel_position = position; - arrange_windows(&root_container, -1, -1); -} - -static struct desktop_shell_interface desktop_shell_implementation = { - .set_background = set_background, - .set_panel = set_panel, - .set_lock_surface = desktop_set_lock_surface, - .unlock = desktop_unlock, - .set_grab_surface = set_grab_surface, - .desktop_ready = desktop_ready, - .set_panel_position = set_panel_position -}; - -static void desktop_shell_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) { - if (version > 3) { - // Unsupported version - return; - } - - struct wl_resource *resource = wl_resource_create(client, &desktop_shell_interface, version, id); - if (!resource) { - wl_client_post_no_memory(client); - } - - wl_resource_set_implementation(resource, &desktop_shell_implementation, NULL, NULL); -} - -static void set_lock_surface(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *_output, struct wl_resource *surface) { - pid_t pid; - wl_client_get_credentials(client, &pid, NULL, NULL); - if (!(get_feature_policy_mask(pid) & FEATURE_LOCK)) { - sway_log(L_INFO, "Denying lock feature to %d", pid); - return; - } - swayc_t *output = swayc_by_handle(wlc_handle_from_wl_output_resource(_output)); - swayc_t *view = swayc_by_handle(wlc_handle_from_wl_surface_resource(surface)); - sway_log(L_DEBUG, "Setting lock surface to %p", view); - if (view && output) { - swayc_t *workspace = output->focused; - if (!swayc_is_child_of(view, workspace)) { - move_container_to(view, workspace); - } - // make the view floating so it doesn't rearrange other siblings. - if (!view->is_floating) { - destroy_container(remove_child(view)); - add_floating(workspace, view); - } - wlc_view_set_state(view->handle, WLC_BIT_FULLSCREEN, true); - wlc_view_bring_to_front(view->handle); - wlc_view_focus(view->handle); - desktop_shell.is_locked = true; - input_init(); - arrange_windows(workspace, -1, -1); - list_add(desktop_shell.lock_surfaces, surface); - wl_resource_set_destructor(surface, lock_surface_destructor); - } else { - sway_log(L_ERROR, "Attempted to set lock surface to non-view"); - } -} - -static void unlock(struct wl_client *client, struct wl_resource *resource) { - sway_log(L_ERROR, "unlock is not currently supported"); - // This isn't really necessary, we just unlock when the client exits. -} - -static struct lock_interface swaylock_implementation = { - .set_lock_surface = set_lock_surface, - .unlock = unlock -}; - -static void swaylock_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) { - if (version > 1) { - // Unsupported version - return; - } - - struct wl_resource *resource = wl_resource_create(client, &lock_interface, version, id); - if (!resource) { - wl_client_post_no_memory(client); - } - - wl_resource_set_implementation(resource, &swaylock_implementation, NULL, NULL); -} - -static void gamma_control_destroy(struct wl_client *client, struct wl_resource *res) { - wl_resource_destroy(res); -} - -static void gamma_control_set_gamma(struct wl_client *client, - struct wl_resource *res, struct wl_array *red, - struct wl_array *green, struct wl_array *blue) { - if (red->size != green->size || red->size != blue->size) { - wl_resource_post_error(res, GAMMA_CONTROL_ERROR_INVALID_GAMMA, - "The gamma ramps don't have the same size"); - return; - } - uint16_t *r = (uint16_t *)red->data; - uint16_t *g = (uint16_t *)green->data; - uint16_t *b = (uint16_t *)blue->data; - wlc_handle output = wlc_handle_from_wl_output_resource( - wl_resource_get_user_data(res)); - if (!output) { - return; - } - sway_log(L_DEBUG, "Setting gamma for output"); - wlc_output_set_gamma(output, red->size / sizeof(uint16_t), r, g, b); -} - -static void gamma_control_reset_gamma(struct wl_client *client, - struct wl_resource *resource) { - // This space intentionally left blank -} - -static struct gamma_control_interface gamma_control_implementation = { - .destroy = gamma_control_destroy, - .set_gamma = gamma_control_set_gamma, - .reset_gamma = gamma_control_reset_gamma -}; - -static void gamma_control_manager_destroy(struct wl_client *client, - struct wl_resource *res) { - wl_resource_destroy(res); -} - -static void gamma_control_manager_get(struct wl_client *client, - struct wl_resource *res, uint32_t id, struct wl_resource *_output) { - struct wl_resource *manager_res = wl_resource_create(client, - &gamma_control_interface, wl_resource_get_version(res), id); - wlc_handle output = wlc_handle_from_wl_output_resource(_output); - if (!output) { - return; - } - wl_resource_set_implementation(manager_res, &gamma_control_implementation, - _output, NULL); - gamma_control_send_gamma_size(manager_res, wlc_output_get_gamma_size(output)); -} - -static struct gamma_control_manager_interface gamma_manager_implementation = { - .destroy = gamma_control_manager_destroy, - .get_gamma_control = gamma_control_manager_get -}; - -static void gamma_control_manager_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) { - if (version > 1) { - // Unsupported version - return; - } - struct wl_resource *resource = wl_resource_create(client, - &gamma_control_manager_interface, version, id); - if (!resource) { - wl_client_post_no_memory(client); - } - wl_resource_set_implementation(resource, &gamma_manager_implementation, NULL, NULL); -} - -static void server_decoration_release(struct wl_client *client, - struct wl_resource *resource) { - wl_resource_destroy(resource); -} - -void server_decoration_enable_csd(wlc_handle handle) { - swayc_t *view = swayc_by_handle(handle); - if (!view) { - sway_log(L_DEBUG, "view invalid"); - return; - } - sway_log(L_DEBUG, "%s requested client side decorations", view->name); - view->border_type = B_NONE; - update_geometry(view); -} - -static void server_decoration_request_mode(struct wl_client *client, - struct wl_resource *resource, uint32_t mode) { - sway_log(L_DEBUG, "Client requested server decoration mode %d", mode); - if (mode == ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER) { - return; - } - struct wl_resource *surface = wl_resource_get_user_data(resource); - if (!surface) { - sway_log(L_DEBUG, "surface invalid"); - return; - } - wlc_handle handle = wlc_handle_from_wl_surface_resource(surface); - if (!handle) { - list_add(decoration_state.csd_resources, surface); - return; - } - server_decoration_enable_csd(handle); -} - -static struct org_kde_kwin_server_decoration_interface server_decoration_implementation = { - .release = server_decoration_release, - .request_mode = server_decoration_request_mode, -}; - -static void server_decoration_manager_create(struct wl_client *client, - struct wl_resource *resource, uint32_t id, struct wl_resource *surface) { - sway_log(L_DEBUG, "Client requested server decoration manager"); - struct wl_resource *manager = wl_resource_create(client, - &org_kde_kwin_server_decoration_interface, 1, id); - if (!manager) { - wl_client_post_no_memory(client); - } - wl_resource_set_implementation(manager, &server_decoration_implementation, surface, NULL); -} - -// Jesus christ KDE, these names are whack as hell -static struct org_kde_kwin_server_decoration_manager_interface server_decoration_manager_implementation = { - .create = server_decoration_manager_create, -}; - -static void server_decoration_manager_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) { - if (version > 1) { - // Unsupported version - return; - } - struct wl_resource *resource = wl_resource_create(client, - &org_kde_kwin_server_decoration_manager_interface, version, id); - if (!resource) { - wl_client_post_no_memory(client); - } - wl_resource_set_implementation(resource, &server_decoration_manager_implementation, NULL, NULL); - org_kde_kwin_server_decoration_manager_send_default_mode(resource, - ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER); -} - -void register_extensions(void) { - wl_global_create(wlc_get_wl_display(), &desktop_shell_interface, 3, NULL, desktop_shell_bind); - desktop_shell.backgrounds = create_list(); - desktop_shell.panels = create_list(); - desktop_shell.lock_surfaces = create_list(); - desktop_shell.is_locked = false; - decoration_state.csd_resources = create_list(); - wl_global_create(wlc_get_wl_display(), &lock_interface, 1, NULL, swaylock_bind); - wl_global_create(wlc_get_wl_display(), &gamma_control_manager_interface, 1, - NULL, gamma_control_manager_bind); - wl_global_create(wlc_get_wl_display(), &org_kde_kwin_server_decoration_manager_interface , - 1, NULL, server_decoration_manager_bind); -} diff --git a/sway/focus.c b/sway/focus.c index e9b032f83..66f7ee17f 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -4,7 +4,6 @@ #include "sway/workspace.h" #include "sway/layout.h" #include "sway/config.h" -#include "sway/extensions.h" #include "sway/input_state.h" #include "sway/ipc-server.h" #include "sway/border.h" @@ -163,12 +162,14 @@ bool set_focused_container(swayc_t *c) { if (c->type == C_VIEW) { wlc_view_set_state(c->handle, WLC_BIT_ACTIVATED, true); } + /* TODO WLR if (!desktop_shell.is_locked) { // If the system is locked, we do everything _but_ actually setting // focus. This includes making our internals think that this view is // focused. wlc_view_focus(c->handle); } + */ if (c->parent->layout != L_TABBED && c->parent->layout != L_STACKED) { update_container_border(c); } diff --git a/sway/ipc-server.c b/sway/ipc-server.c index b560b9306..9ba736d89 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -31,21 +30,22 @@ struct ucred { #include "sway/config.h" #include "sway/commands.h" #include "sway/input.h" +#include "sway/server.h" #include "stringop.h" #include "log.h" #include "list.h" #include "util.h" static int ipc_socket = -1; -static struct wlc_event_source *ipc_event_source = NULL; +static struct wl_event_source *ipc_event_source = NULL; static struct sockaddr_un *ipc_sockaddr = NULL; static list_t *ipc_client_list = NULL; static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; struct ipc_client { - struct wlc_event_source *event_source; - struct wlc_event_source *writable_event_source; + struct wl_event_source *event_source; + struct wl_event_source *writable_event_source; int fd; uint32_t payload_length; uint32_t security_policy; @@ -58,25 +58,6 @@ struct ipc_client { static list_t *ipc_get_pixel_requests = NULL; -struct get_pixels_request { - struct ipc_client *client; - wlc_handle output; - struct wlc_geometry geo; -}; - -struct get_clipboard_request { - struct ipc_client *client; - json_object *json; - int fd; - struct wlc_event_source *fd_event_source; - struct wlc_event_source *timer_event_source; - char *type; - unsigned int *pending; - char *buf; - size_t buf_size; - size_t buf_position; -}; - struct sockaddr_un *ipc_user_sockaddr(void); int ipc_handle_connection(int fd, uint32_t mask, void *data); int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); @@ -118,12 +99,13 @@ void ipc_init(void) { ipc_client_list = create_list(); ipc_get_pixel_requests = create_list(); - ipc_event_source = wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); + ipc_event_source = wl_event_loop_add_fd(server.wl_event_loop, ipc_socket, + WL_EVENT_READABLE, ipc_handle_connection, NULL); } void ipc_terminate(void) { if (ipc_event_source) { - wlc_event_source_remove(ipc_event_source); + wl_event_source_remove(ipc_event_source); } close(ipc_socket); unlink(ipc_sockaddr->sun_path); @@ -176,7 +158,7 @@ static pid_t get_client_pid(int client_fd) { int ipc_handle_connection(int fd, uint32_t mask, void *data) { (void) fd; (void) data; sway_log(L_DEBUG, "Event on IPC listening socket"); - assert(mask == WLC_EVENT_READABLE); + assert(mask == WL_EVENT_READABLE); int client_fd = accept(ipc_socket, NULL, NULL); if (client_fd == -1) { @@ -207,7 +189,8 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { client->payload_length = 0; client->fd = client_fd; client->subscribed_events = 0; - client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); + client->event_source = wl_event_loop_add_fd(server.wl_event_loop, client_fd, + WL_EVENT_READABLE, ipc_client_handle_readable, client); client->writable_event_source = NULL; client->write_buffer_size = 128; @@ -234,13 +217,13 @@ static const int ipc_header_size = sizeof(ipc_magic)+8; int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; - if (mask & WLC_EVENT_ERROR) { + if (mask & WL_EVENT_ERROR) { sway_log(L_ERROR, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } - if (mask & WLC_EVENT_HANGUP) { + if (mask & WL_EVENT_HANGUP) { sway_log(L_DEBUG, "Client %d hung up", client->fd); ipc_client_disconnect(client); return 0; @@ -296,13 +279,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; - if (mask & WLC_EVENT_ERROR) { + if (mask & WL_EVENT_ERROR) { sway_log(L_ERROR, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } - if (mask & WLC_EVENT_HANGUP) { + if (mask & WL_EVENT_HANGUP) { sway_log(L_DEBUG, "Client %d hung up", client->fd); ipc_client_disconnect(client); return 0; @@ -328,7 +311,7 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { client->write_buffer_len -= written; if (client->write_buffer_len == 0 && client->writable_event_source) { - wlc_event_source_remove(client->writable_event_source); + wl_event_source_remove(client->writable_event_source); client->writable_event_source = NULL; } @@ -345,9 +328,9 @@ void ipc_client_disconnect(struct ipc_client *client) { } sway_log(L_INFO, "IPC Client %d disconnected", client->fd); - wlc_event_source_remove(client->event_source); + wl_event_source_remove(client->event_source); if (client->writable_event_source) { - wlc_event_source_remove(client->writable_event_source); + wl_event_source_remove(client->writable_event_source); } int i = 0; while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++; @@ -365,165 +348,6 @@ bool output_by_name_test(swayc_t *view, void *data) { return !strcmp(name, view->name); } -void ipc_get_pixels(wlc_handle output) { - if (ipc_get_pixel_requests->length == 0) { - return; - } - - list_t *unhandled = create_list(); - - struct get_pixels_request *req; - int i; - for (i = 0; i < ipc_get_pixel_requests->length; ++i) { - req = ipc_get_pixel_requests->items[i]; - if (req->output != output) { - list_add(unhandled, req); - continue; - } - - const struct wlc_size *size = &req->geo.size; - struct wlc_geometry g_out; - char response_header[9]; - memset(response_header, 0, sizeof(response_header)); - char *data = malloc(sizeof(response_header) + size->w * size->h * 4); - if (!data) { - sway_log(L_ERROR, "Unable to allocate pixels for get_pixels"); - ipc_client_disconnect(req->client); - free(req); - continue; - } - wlc_pixels_read(WLC_RGBA8888, &req->geo, &g_out, data + sizeof(response_header)); - - response_header[0] = 1; - uint32_t *_size = (uint32_t *)(response_header + 1); - _size[0] = g_out.size.w; - _size[1] = g_out.size.h; - size_t len = sizeof(response_header) + (g_out.size.w * g_out.size.h * 4); - memcpy(data, response_header, sizeof(response_header)); - ipc_send_reply(req->client, data, len); - free(data); - // free the request since it has been handled - free(req); - } - - // free old list of pixel requests and set new list to all unhandled - // requests (request for another output). - list_free(ipc_get_pixel_requests); - ipc_get_pixel_requests = unhandled; -} - -static bool is_text_target(const char *target) { - return (strncmp(target, "text/", 5) == 0 - || strcmp(target, "UTF8_STRING") == 0 - || strcmp(target, "STRING") == 0 - || strcmp(target, "TEXT") == 0 - || strcmp(target, "COMPOUND_TEXT") == 0); -} - -static void release_clipboard_request(struct get_clipboard_request *req) { - if (--(*req->pending) == 0) { - const char *str = json_object_to_json_string(req->json); - ipc_send_reply(req->client, str, (uint32_t)strlen(str)); - json_object_put(req->json); - } - - free(req->type); - free(req->buf); - wlc_event_source_remove(req->fd_event_source); - wlc_event_source_remove(req->timer_event_source); - close(req->fd); - free(req); -} - -static int ipc_selection_data_cb(int fd, uint32_t mask, void *data) { - assert(data); - struct get_clipboard_request *req = (struct get_clipboard_request *)data; - - if (mask & WLC_EVENT_ERROR) { - sway_log(L_ERROR, "Selection data fd error"); - goto error; - } - - if (mask & WLC_EVENT_READABLE) { - static const unsigned int max_size = 8192 * 1024; - int amt = 0; - - do { - int size = req->buf_size - req->buf_position; - int amt = read(fd, req->buf + req->buf_position, size - 1); - if (amt < 0) { - if (errno == EAGAIN) { - return 0; - } - - sway_log_errno(L_INFO, "Failed to read from clipboard data fd"); - goto release; - } - - req->buf_position += amt; - if (req->buf_position >= req->buf_size - 1) { - if (req->buf_size >= max_size) { - sway_log(L_ERROR, "get_clipbard: selection data too large"); - goto error; - } - char *next = realloc(req->buf, req->buf_size *= 2); - if (!next) { - sway_log_errno(L_ERROR, "get_clipboard: realloc data buffer failed"); - goto error; - } - - req->buf = next; - } - } while(amt != 0); - - req->buf[req->buf_position] = '\0'; - - json_object *obj = json_object_new_object(); - json_object_object_add(obj, "success", json_object_new_boolean(true)); - if (is_text_target(req->type)) { - json_object_object_add(obj, "content", json_object_new_string(req->buf)); - json_object_object_add(req->json, req->type, obj); - } else { - size_t outlen; - char *b64 = b64_encode(req->buf, req->buf_position, &outlen); - json_object_object_add(obj, "content", json_object_new_string(b64)); - free(b64); - - char *type = malloc(strlen(req->type) + 8); - strcat(type, ";base64"); - json_object_object_add(req->json, type, obj); - free(type); - } - } - - goto release; - -error:; - json_object *obj = json_object_new_object(); - json_object_object_add(obj, "success", json_object_new_boolean(false)); - json_object_object_add(obj, "error", - json_object_new_string("Failed to retrieve data")); - json_object_object_add(req->json, req->type, obj); - -release: - release_clipboard_request(req); - return 0; -} - -static int ipc_selection_timer_cb(void *data) { - assert(data); - struct get_clipboard_request *req = (struct get_clipboard_request *)data; - - sway_log(L_INFO, "get_clipbard: timeout for type %s", req->type); - json_object *obj = json_object_new_object(); - json_object_object_add(obj, "success", json_object_new_boolean(false)); - json_object_object_add(obj, "error", json_object_new_string("Timeout")); - json_object_object_add(req->json, req->type, obj); - - release_clipboard_request(req); - return 0; -} - // greedy wildcard (only "*") matching bool mime_type_matches(const char *mime_type, const char *pattern) { const char *wildcard = NULL; @@ -553,125 +377,6 @@ bool mime_type_matches(const char *mime_type, const char *pattern) { return (*mime_type == *pattern); } -void ipc_get_clipboard(struct ipc_client *client, char *buf) { - size_t size; - const char **types = wlc_get_selection_types(&size); - if (client->payload_length == 0) { - json_object *obj = json_object_new_array(); - for (size_t i = 0; i < size; ++i) { - json_object_array_add(obj, json_object_new_string(types[i])); - } - - const char *str = json_object_to_json_string(obj); - ipc_send_reply(client, str, strlen(str)); - json_object_put(obj); - return; - } - - unescape_string(buf); - strip_quotes(buf); - list_t *requested = split_string(buf, " "); - json_object *json = json_object_new_object(); - unsigned int *pending = malloc(sizeof(unsigned int)); - *pending = 0; - - for (size_t l = 0; l < (size_t) requested->length; ++l) { - const char *pattern = requested->items[l]; - bool found = false; - for (size_t i = 0; i < size; ++i) { - if (!mime_type_matches(types[i], pattern)) { - continue; - } - - found = true; - - struct get_clipboard_request *req = malloc(sizeof(*req)); - if (!req) { - sway_log(L_ERROR, "get_clipboard: request malloc failed"); - goto data_error; - } - - int pipes[2]; - if (pipe(pipes) == -1) { - sway_log_errno(L_ERROR, "get_clipboard: pipe call failed"); - free(req); - goto data_error; - } - - fcntl(pipes[0], F_SETFD, FD_CLOEXEC | O_NONBLOCK); - fcntl(pipes[1], F_SETFD, FD_CLOEXEC | O_NONBLOCK); - - if (!wlc_get_selection_data(types[i], pipes[1])) { - close(pipes[0]); - close(pipes[1]); - free(req); - sway_log(L_ERROR, "get_clipboard: failed to retrieve " - "selection data"); - goto data_error; - } - - if (!(req->buf = malloc(512))) { - close(pipes[0]); - close(pipes[1]); - free(req); - sway_log_errno(L_ERROR, "get_clipboard: buf malloc failed"); - goto data_error; - } - - (*pending)++; - - req->client = client; - req->type = strdup(types[i]); - req->json = json; - req->pending = pending; - req->buf_position = 0; - req->buf_size = 512; - req->fd = pipes[0]; - req->timer_event_source = wlc_event_loop_add_timer(ipc_selection_timer_cb, req); - req->fd_event_source = wlc_event_loop_add_fd(pipes[0], - WLC_EVENT_READABLE | WLC_EVENT_ERROR | WLC_EVENT_HANGUP, - &ipc_selection_data_cb, req); - - wlc_event_source_timer_update(req->timer_event_source, 30000); - - // NOTE: remove this goto to enable retrieving multiple - // targets at once. The whole implementation is already - // made for it. The only reason it was disabled - // at the time of writing is that neither wlc's xselection - // implementation nor (apparently) gtk on wayland supports - // multiple send requests at the same time which makes - // every request except the last one fail (and therefore - // return empty data) - goto cleanup; - } - - if (!found) { - sway_log(L_INFO, "Invalid clipboard type %s requested", pattern); - } - } - - if (*pending == 0) { - static const char *error_empty = "{ \"success\": false, \"error\": " - "\"No matching types found\" }"; - ipc_send_reply(client, error_empty, (uint32_t)strlen(error_empty)); - free(json); - free(pending); - } - - goto cleanup; - -data_error:; - static const char *error_json = "{ \"success\": false, \"error\": " - "\"Failed to create clipboard data request\" }"; - ipc_send_reply(client, error_json, (uint32_t)strlen(error_json)); - free(json); - free(pending); - -cleanup: - list_free(requested); - free(types); -} - void ipc_client_handle_command(struct ipc_client *client) { if (!sway_assert(client != NULL, "client != NULL")) { return; @@ -830,52 +535,6 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } - case IPC_SWAY_GET_PIXELS: - { - char response_header[9]; - memset(response_header, 0, sizeof(response_header)); - - json_object *obj = json_tokener_parse(buf); - json_object *o, *x, *y, *w, *h; - - json_object_object_get_ex(obj, "output", &o); - json_object_object_get_ex(obj, "x", &x); - json_object_object_get_ex(obj, "y", &y); - json_object_object_get_ex(obj, "w", &w); - json_object_object_get_ex(obj, "h", &h); - - struct wlc_geometry g = { - .origin = { - .x = json_object_get_int(x), - .y = json_object_get_int(y) - }, - .size = { - .w = json_object_get_int(w), - .h = json_object_get_int(h) - } - }; - - swayc_t *output = swayc_by_test(&root_container, output_by_name_test, (void *)json_object_get_string(o)); - json_object_put(obj); - - if (!output) { - sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name"); - ipc_send_reply(client, response_header, sizeof(response_header)); - goto exit_cleanup; - } - struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request)); - if (!req) { - sway_log(L_ERROR, "Unable to allocate get_pixels request"); - goto exit_cleanup; - } - req->client = client; - req->output = output->handle; - req->geo = g; - list_add(ipc_get_pixel_requests, req); - wlc_output_schedule_render(output->handle); - goto exit_cleanup; - } - case IPC_GET_BAR_CONFIG: { if (!(client->security_policy & IPC_FEATURE_GET_BAR_CONFIG)) { @@ -917,14 +576,8 @@ void ipc_client_handle_command(struct ipc_client *client) { } case IPC_GET_CLIPBOARD: - { - if (!(client->security_policy & IPC_FEATURE_GET_CLIPBOARD)) { - goto exit_denied; - } - - ipc_get_clipboard(client, buf); - goto exit_cleanup; - } + // TODO WLR + break; default: sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); @@ -977,7 +630,9 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay client->write_buffer_len += payload_length; if (!client->writable_event_source) { - client->writable_event_source = wlc_event_loop_add_fd(client->fd, WLC_EVENT_WRITABLE, ipc_client_handle_writable, client); + client->writable_event_source = wl_event_loop_add_fd( + server.wl_event_loop, client->fd, WL_EVENT_WRITABLE, + ipc_client_handle_writable, client); } sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); diff --git a/sway/layout.c b/sway/layout.c index 69291dafd..22f81688a 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -3,7 +3,6 @@ #include #include #include -#include "sway/extensions.h" #include "sway/config.h" #include "sway/container.h" #include "sway/workspace.h" @@ -1001,6 +1000,7 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { { swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); width = output->width, height = output->height; + /* TODO WLR for (i = 0; i < desktop_shell.panels->length; ++i) { struct panel_config *config = desktop_shell.panels->items[i]; if (config->output == output->handle) { @@ -1022,6 +1022,7 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { } } } + */ int gap = swayc_gap(container); x = container->x = x + gap; y = container->y = y + gap; @@ -1380,11 +1381,13 @@ void arrange_windows(swayc_t *container, double width, double height) { } void arrange_backgrounds(void) { + /* TODO WLR struct background_config *bg; for (int i = 0; i < desktop_shell.backgrounds->length; ++i) { bg = desktop_shell.backgrounds->items[i]; wlc_view_send_to_back(bg->handle); } + */ } /** diff --git a/sway/main.c b/sway/main.c index cc9147b8a..efca96d5a 100644 --- a/sway/main.c +++ b/sway/main.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -15,13 +14,13 @@ #include #include #endif -#include "sway/extensions.h" #include "sway/layout.h" #include "sway/config.h" #include "sway/security.h" #include "sway/handlers.h" #include "sway/input.h" #include "sway/ipc-server.h" +#include "sway/server.h" #include "ipc-client.h" #include "readline.h" #include "stringop.h" @@ -31,11 +30,12 @@ static bool terminate_request = false; static int exit_value = 0; +struct sway_server server; void sway_terminate(int exit_code) { terminate_request = true; exit_value = exit_code; - wlc_terminate(); + wl_display_terminate(server.wl_display); } void sig_handler(int signal) { @@ -43,16 +43,6 @@ void sig_handler(int signal) { sway_terminate(EXIT_SUCCESS); } -static void wlc_log_handler(enum wlc_log_type type, const char *str) { - if (type == WLC_LOG_ERROR) { - sway_log(L_ERROR, "[wlc] %s", str); - } else if (type == WLC_LOG_WARN) { - sway_log(L_INFO, "[wlc] %s", str); - } else { - sway_log(L_DEBUG, "[wlc] %s", str); - } -} - void detect_raspi() { bool raspi = false; FILE *f = fopen("/sys/firmware/devicetree/base/model", "r"); @@ -189,19 +179,7 @@ static void log_env() { "LD_LIBRARY_PATH", "SWAY_CURSOR_THEME", "SWAY_CURSOR_SIZE", - "SWAYSOCK", - "WLC_DRM_DEVICE", - "WLC_SHM", - "WLC_OUTPUTS", - "WLC_XWAYLAND", - "WLC_LIBINPUT", - "WLC_REPEAT_DELAY", - "WLC_REPEAT_RATE", - "XKB_DEFAULT_RULES", - "XKB_DEFAULT_MODEL", - "XKB_DEFAULT_LAYOUT", - "XKB_DEFAULT_VARIANT", - "XKB_DEFAULT_OPTIONS", + "SWAYSOCK" }; for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { sway_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); @@ -295,6 +273,37 @@ static void executable_sanity_check() { #endif } +static void drop_permissions(bool keep_caps) { + if (getuid() != geteuid() || getgid() != getegid()) { + if (setgid(getgid()) != 0) { + sway_log(L_ERROR, "Unable to drop root"); + exit(EXIT_FAILURE); + } + if (setuid(getuid()) != 0) { + sway_log(L_ERROR, "Unable to drop root"); + exit(EXIT_FAILURE); + } + } + if (setuid(0) != -1) { + sway_log(L_ERROR, "Root privileges can be restored."); + exit(EXIT_FAILURE); + } +#ifdef __linux__ + if (keep_caps) { + // Drop every cap except CAP_SYS_PTRACE + cap_t caps = cap_init(); + cap_value_t keep = CAP_SYS_PTRACE; + sway_log(L_INFO, "Dropping extra capabilities"); + if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || + cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || + cap_set_proc(caps)) { + sway_log(L_ERROR, "Failed to drop extra capabilities"); + exit(EXIT_FAILURE); + } + } +#endif +} + int main(int argc, char **argv) { static int verbose = 0, debug = 0, validate = 0; @@ -374,7 +383,7 @@ int main(int argc, char **argv) { } } - // we need to setup logging before wlc_init in case it fails. + // TODO: switch logging over to wlroots? if (debug) { init_log(L_DEBUG); } else if (verbose || validate) { @@ -388,20 +397,7 @@ int main(int argc, char **argv) { sway_log(L_ERROR, "Don't use options with the IPC client"); exit(EXIT_FAILURE); } - if (getuid() != geteuid() || getgid() != getegid()) { - if (setgid(getgid()) != 0) { - sway_log(L_ERROR, "Unable to drop root"); - exit(EXIT_FAILURE); - } - if (setuid(getuid()) != 0) { - sway_log(L_ERROR, "Unable to drop root"); - exit(EXIT_FAILURE); - } - } - if (setuid(0) != -1) { - sway_log(L_ERROR, "Root privileges can be restored."); - exit(EXIT_FAILURE); - } + drop_permissions(false); char *socket_path = getenv("SWAYSOCK"); if (!socket_path) { sway_log(L_ERROR, "Unable to retrieve socket path"); @@ -413,8 +409,8 @@ int main(int argc, char **argv) { } executable_sanity_check(); -#ifdef __linux__ bool suid = false; +#ifdef __linux__ if (getuid() != geteuid() || getgid() != getegid()) { // Retain capabilities after setuid() if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { @@ -425,37 +421,14 @@ int main(int argc, char **argv) { } #endif - wlc_log_set_handler(wlc_log_handler); log_kernel(); log_distro(); log_env(); detect_proprietary(); detect_raspi(); - input_devices = create_list(); - - /* Changing code earlier than this point requires detailed review */ - /* (That code runs as root on systems without logind, and wlc_init drops to - * another user.) */ - register_wlc_handlers(); - if (!wlc_init()) { - return 1; - } - register_extensions(); - #ifdef __linux__ - if (suid) { - // Drop every cap except CAP_SYS_PTRACE - cap_t caps = cap_init(); - cap_value_t keep = CAP_SYS_PTRACE; - sway_log(L_INFO, "Dropping extra capabilities"); - if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || - cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || - cap_set_proc(caps)) { - sway_log(L_ERROR, "Failed to drop extra capabilities"); - exit(EXIT_FAILURE); - } - } + drop_permissions(suid); #endif // handle SIGTERM signals signal(SIGTERM, sig_handler); @@ -465,8 +438,10 @@ int main(int argc, char **argv) { sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); + if (!server_init(&server)) { + return 1; + } init_layout(); - ipc_init(); if (validate) { @@ -485,10 +460,10 @@ int main(int argc, char **argv) { security_sanity_check(); if (!terminate_request) { - wlc_run(); + wl_display_run(server.wl_display); } - list_free(input_devices); + server_fini(&server); ipc_terminate(); diff --git a/sway/server.c b/sway/server.c new file mode 100644 index 000000000..39fa5d28f --- /dev/null +++ b/sway/server.c @@ -0,0 +1,54 @@ +#define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include +#include +#include +#include +#include +// TODO WLR: make Xwayland optional +#include +#include "sway/server.h" +#include "log.h" + +bool server_init(struct sway_server *server) { + sway_log(L_DEBUG, "Initializing Wayland server"); + + server->wl_display = wl_display_create(); + server->wl_event_loop = wl_display_get_event_loop(server->wl_display); + server->backend = wlr_backend_autocreate(server->wl_display); + + server->renderer = wlr_gles2_renderer_create(server->backend); + wl_display_init_shm(server->wl_display); + + // TODO WLR + //server->desktop = desktop_create(server, server.config); + //server->input = input_create(&server, server.config); + server->data_device_manager = + wlr_data_device_manager_create(server->wl_display); + + const char *socket = wl_display_add_socket_auto(server->wl_display); + if (!socket) { + sway_log_errno(L_ERROR, "Unable to open wayland socket"); + wlr_backend_destroy(server->backend); + return false; + } + + sway_log(L_INFO, "Running compositor on wayland display '%s'", socket); + setenv("_WAYLAND_DISPLAY", socket, true); + + if (!wlr_backend_start(server->backend)) { + sway_log(L_ERROR, "Failed to start backend"); + wlr_backend_destroy(server->backend); + return false; + } + + setenv("WAYLAND_DISPLAY", socket, true); + return true; +} + +void server_fini(struct sway_server *server) { + // TODO WLR: tear down more stuff + wlr_backend_destroy(server->backend); +} diff --git a/sway/workspace.c b/sway/workspace.c index e0367190c..14cde1465 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -8,7 +8,6 @@ #include #include #include "sway/ipc-server.h" -#include "sway/extensions.h" #include "sway/workspace.h" #include "sway/layout.h" #include "sway/container.h" From c3457de28a37d074a960cd464445de02d6527997 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 22 Oct 2017 10:45:11 -0400 Subject: [PATCH 003/522] Fix build yml files --- .build.yml | 8 ++++++++ .travis.yml | 13 +++++++++++-- include/sway/server.h | 1 - 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.build.yml b/.build.yml index 9c9e8adb5..5fa8eb419 100644 --- a/.build.yml +++ b/.build.yml @@ -12,7 +12,15 @@ packages: - gdk-pixbuf2 sources: - https://git.sr.ht/~sircmpwn/sway + - https://git.sr.ht/~sircmpwn/wlroots tasks: + - wlroots: | + cd wlroots + mkdir build + cd build + meson --prefix=/usr .. + ninja + sudo ninja install - setup: | cd sway mkdir build diff --git a/.travis.yml b/.travis.yml index 3eeb16820..be7ac3e0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,17 @@ arch: - wlc-git - libcap script: - - "cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ." - - "make" + - git clone https://github.com/swaywm/wlroots + - cd wlroots + - mkdir build + - cd build + - meson --prefix=/usr .. + - sudo ninja install + - cd ../.. + - cmake . + - make + - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . + - make script: - "curl -s https://raw.githubusercontent.com/mikkeloscar/arch-travis/master/arch-travis.sh | bash" diff --git a/include/sway/server.h b/include/sway/server.h index 471a0270b..9cd760aca 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -11,7 +11,6 @@ struct sway_server { // TODO WLR - //struct roots_desktop *desktop; //struct roots_input *input; struct wl_display *wl_display; From 7414d9232751d378ff2840b7fb45e711b7f69477 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 22 Oct 2017 10:49:26 -0400 Subject: [PATCH 004/522] Also need meson --- .build.yml | 1 + .travis.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.build.yml b/.build.yml index 5fa8eb419..3717d6990 100644 --- a/.build.yml +++ b/.build.yml @@ -10,6 +10,7 @@ packages: - cairo - wayland - gdk-pixbuf2 + - meson sources: - https://git.sr.ht/~sircmpwn/sway - https://git.sr.ht/~sircmpwn/wlroots diff --git a/.travis.yml b/.travis.yml index be7ac3e0a..bc1ee45b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ arch: - gdk-pixbuf2 - wlc-git - libcap + - meson script: - git clone https://github.com/swaywm/wlroots - cd wlroots From 0f45fad18cf56910aa339c7c6ad1a661e96cfb0d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 22 Oct 2017 11:38:30 -0400 Subject: [PATCH 005/522] Establish sway input submodule --- include/sway/input.h | 11 ++++++----- include/sway/server.h | 5 ++--- sway/CMakeLists.txt | 3 ++- sway/{ => input}/input.c | 14 +++++++++++--- sway/ipc-server.c | 2 ++ sway/server.c | 5 ++--- 6 files changed, 25 insertions(+), 15 deletions(-) rename sway/{ => input}/input.c (89%) diff --git a/include/sway/input.h b/include/sway/input.h index 4ed9bffe7..eb92e470a 100644 --- a/include/sway/input.h +++ b/include/sway/input.h @@ -1,18 +1,19 @@ #ifndef _SWAY_INPUT_H #define _SWAY_INPUT_H - #include +#include "sway/server.h" #include "config.h" #include "list.h" +struct sway_input { + list_t *input_devices; +}; + struct input_config *new_input_config(const char* identifier); char* libinput_dev_unique_id(struct libinput_device *dev); -/** - * Global input device list. - */ -extern list_t *input_devices; +struct sway_input *sway_input_create(struct sway_server *server); /** * Pointer used when reading input blocked. diff --git a/include/sway/server.h b/include/sway/server.h index 9cd760aca..22069f9c9 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -10,9 +10,6 @@ #include struct sway_server { - // TODO WLR - //struct roots_input *input; - struct wl_display *wl_display; struct wl_event_loop *wl_event_loop; @@ -20,6 +17,8 @@ struct sway_server { struct wlr_renderer *renderer; struct wlr_data_device_manager *data_device_manager; + + struct sway_input *input; }; bool server_init(struct sway_server *server); diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index ac0530e5d..3c78aec94 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -26,7 +26,6 @@ add_executable(sway criteria.c debug_log.c focus.c - input.c input_state.c ipc-json.c ipc-server.c @@ -37,6 +36,8 @@ add_executable(sway border.c security.c server.c + + input/input.c ) add_definitions( diff --git a/sway/input.c b/sway/input/input.c similarity index 89% rename from sway/input.c rename to sway/input/input.c index 6263f79fe..02b4995ed 100644 --- a/sway/input.c +++ b/sway/input/input.c @@ -7,9 +7,20 @@ #include #include "sway/config.h" #include "sway/input.h" +#include "sway/server.h" #include "list.h" #include "log.h" +struct input_config *current_input_config = NULL; + +struct sway_input *sway_input_create(struct sway_server *server) { + struct sway_input *input = calloc(1, sizeof(struct sway_input)); + if (!input) { + return NULL; + } + return input; +} + struct input_config *new_input_config(const char* identifier) { struct input_config *input = calloc(1, sizeof(struct input_config)); if (!input) { @@ -64,6 +75,3 @@ char *libinput_dev_unique_id(struct libinput_device *device) { free(name); return identifier; } - -list_t *input_devices = NULL; -struct input_config *current_input_config = NULL; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 9ba736d89..d4db4e7a4 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -476,12 +476,14 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_denied; } json_object *inputs = json_object_new_array(); + /* TODO WLR if (input_devices) { for(int i = 0; ilength; i++) { struct libinput_device *device = input_devices->items[i]; json_object_array_add(inputs, ipc_json_describe_input(device)); } } + */ const char *json_string = json_object_to_json_string(inputs); ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); json_object_put(inputs); diff --git a/sway/server.c b/sway/server.c index 39fa5d28f..4a74cfb53 100644 --- a/sway/server.c +++ b/sway/server.c @@ -10,6 +10,7 @@ // TODO WLR: make Xwayland optional #include #include "sway/server.h" +#include "sway/input.h" #include "log.h" bool server_init(struct sway_server *server) { @@ -22,9 +23,7 @@ bool server_init(struct sway_server *server) { server->renderer = wlr_gles2_renderer_create(server->backend); wl_display_init_shm(server->wl_display); - // TODO WLR - //server->desktop = desktop_create(server, server.config); - //server->input = input_create(&server, server.config); + server->input = sway_input_create(server); server->data_device_manager = wlr_data_device_manager_create(server->wl_display); From 0ba6554c4f6c923274062862d895240eea4de350 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 11 Nov 2017 11:00:18 -0500 Subject: [PATCH 006/522] Move sway's internal tree code to sway/tree/ --- sway/CMakeLists.txt | 12 ++++++------ sway/{ => tree}/container.c | 0 sway/{ => tree}/criteria.c | 0 sway/{ => tree}/focus.c | 0 sway/{ => tree}/layout.c | 0 sway/{ => tree}/output.c | 0 sway/{ => tree}/workspace.c | 0 7 files changed, 6 insertions(+), 6 deletions(-) rename sway/{ => tree}/container.c (100%) rename sway/{ => tree}/criteria.c (100%) rename sway/{ => tree}/focus.c (100%) rename sway/{ => tree}/layout.c (100%) rename sway/{ => tree}/output.c (100%) rename sway/{ => tree}/workspace.c (100%) diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 3c78aec94..1df24222c 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -20,19 +20,19 @@ file(GLOB cmds add_executable(sway commands.c ${cmds} + tree/container.c + tree/criteria.c + tree/focus.c + tree/output.c + tree/workspace.c + tree/layout.c base64.c config.c - container.c - criteria.c debug_log.c - focus.c input_state.c ipc-json.c ipc-server.c - layout.c main.c - output.c - workspace.c border.c security.c server.c diff --git a/sway/container.c b/sway/tree/container.c similarity index 100% rename from sway/container.c rename to sway/tree/container.c diff --git a/sway/criteria.c b/sway/tree/criteria.c similarity index 100% rename from sway/criteria.c rename to sway/tree/criteria.c diff --git a/sway/focus.c b/sway/tree/focus.c similarity index 100% rename from sway/focus.c rename to sway/tree/focus.c diff --git a/sway/layout.c b/sway/tree/layout.c similarity index 100% rename from sway/layout.c rename to sway/tree/layout.c diff --git a/sway/output.c b/sway/tree/output.c similarity index 100% rename from sway/output.c rename to sway/tree/output.c diff --git a/sway/workspace.c b/sway/tree/workspace.c similarity index 100% rename from sway/workspace.c rename to sway/tree/workspace.c From 7eafcc75f6f8abd2346e0d72b063bc10ce24378f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 11 Nov 2017 11:58:43 -0500 Subject: [PATCH 007/522] Initialize outputs from backend and add to tree --- include/sway/container.h | 20 +++++++++++++++----- include/sway/server.h | 14 +++++++++++--- sway/CMakeLists.txt | 12 ++++++++---- sway/config.c | 14 ++++++++++---- sway/desktop/output.c | 21 +++++++++++++++++++++ sway/ipc-json.c | 17 +++++++++++------ sway/main.c | 3 ++- sway/server.c | 32 ++++++++++++++++++-------------- sway/tree/container.c | 20 ++++++++++---------- 9 files changed, 106 insertions(+), 47 deletions(-) create mode 100644 sway/desktop/output.c diff --git a/include/sway/container.h b/include/sway/container.h index 37192ce35..f6aae7d12 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -2,6 +2,7 @@ #define _SWAY_CONTAINER_H #include #include +#include #include #include "list.h" @@ -27,6 +28,14 @@ enum swayc_types { C_TYPES, }; +enum swayc_view_types { + V_WL_SHELL, + V_XDG_SHELL_V6, + V_XWAYLAND, + // Keep last + V_TYPES, +}; + /** * Different ways to arrange a container. */ @@ -63,12 +72,13 @@ enum swayc_border_types { * The tree is made of these. Views are containers that cannot have children. */ struct sway_container { - /** - * If this container maps to a WLC object, this is set to that object's - * handle. Otherwise, NULL. - */ + // TODO WLR: reconcile these wlc_handle handle; + union { + struct wlr_output *output; + } _handle; + /** * A unique ID to identify this container. Primarily used in the * get_tree JSON output. @@ -179,7 +189,7 @@ enum visibility_mask { /** * Allocates a new output container. */ -swayc_t *new_output(wlc_handle handle); +swayc_t *new_output(struct wlr_output *wlr_output); /** * Allocates a new workspace container. */ diff --git a/include/sway/server.h b/include/sway/server.h index 22069f9c9..f3e86bcba 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -12,6 +12,7 @@ struct sway_server { struct wl_display *wl_display; struct wl_event_loop *wl_event_loop; + const char *socket; struct wlr_backend *backend; struct wlr_renderer *renderer; @@ -19,11 +20,18 @@ struct sway_server { struct wlr_data_device_manager *data_device_manager; struct sway_input *input; -}; -bool server_init(struct sway_server *server); -void server_fini(struct sway_server *server); + struct wl_listener output_add; + struct wl_listener output_remove; + struct wl_listener output_frame; +}; struct sway_server server; +bool server_init(struct sway_server *server); +void server_fini(struct sway_server *server); +void server_run(struct sway_server *server); + +void output_add_notify(struct wl_listener *listener, void *data); + #endif diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 1df24222c..617a71f00 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -18,14 +18,20 @@ file(GLOB cmds ) add_executable(sway - commands.c - ${cmds} + desktop/output.c + tree/container.c tree/criteria.c tree/focus.c tree/output.c tree/workspace.c tree/layout.c + + input/input.c + + commands.c + ${cmds} + base64.c config.c debug_log.c @@ -36,8 +42,6 @@ add_executable(sway border.c security.c server.c - - input/input.c ) add_definitions( diff --git a/sway/config.c b/sway/config.c index a33b8edc1..78ab8f3b9 100644 --- a/sway/config.c +++ b/sway/config.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "wayland-desktop-shell-server-protocol.h" #include "sway/commands.h" #include "sway/config.h" @@ -930,6 +931,7 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { } static void invoke_swaybar(struct bar_config *bar) { + return; // TODO WLR // Pipe to communicate errors int filedes[2]; if (pipe(filedes) == -1) { @@ -1128,13 +1130,15 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { output->height = oc->height; sway_log(L_DEBUG, "Set %s size to %ix%i (%d)", oc->name, oc->width, oc->height, oc->scale); - struct wlc_size new_size = { .w = oc->width, .h = oc->height }; - wlc_output_set_resolution(output->handle, &new_size, (uint32_t)oc->scale); + // TODO WLR: modes + //struct wlc_size new_size = { .w = oc->width, .h = oc->height }; + //wlc_output_set_resolution(output->handle, &new_size, (uint32_t)oc->scale); } else if (oc) { - const struct wlc_size *new_size = wlc_output_get_resolution(output->handle); - wlc_output_set_resolution(output->handle, new_size, (uint32_t)oc->scale); + //const struct wlc_size *new_size = wlc_output_get_resolution(output->handle); + //wlc_output_set_resolution(output->handle, new_size, (uint32_t)oc->scale); } + // TODO WLR: wlr_output_layout // 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); @@ -1170,6 +1174,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { } } + /* TODO WLR if (oc && oc->background) { if (output->bg_pid != 0) { terminate_swaybg(output->bg_pid); @@ -1195,6 +1200,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { execvp(cmd[0], cmd); } } + */ } char *do_var_replacement(char *str) { diff --git a/sway/desktop/output.c b/sway/desktop/output.c new file mode 100644 index 000000000..51363e768 --- /dev/null +++ b/sway/desktop/output.c @@ -0,0 +1,21 @@ +#include +#include +#include "sway/server.h" +#include "sway/container.h" +#include "sway/workspace.h" +#include "log.h" + +void output_add_notify(struct wl_listener *listener, void *data) { + struct sway_server *server = wl_container_of(listener, server, output_add); + struct wlr_output *wlr_output = data; + sway_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); + swayc_t *op = new_output(wlr_output); + if (!sway_assert(op, "Failed to allocate output")) { + return; + } + // Switch to workspace if we need to + if (swayc_active_workspace() == NULL) { + swayc_t *ws = op->children->items[0]; + workspace_switch(ws); + } +} diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 6ab63c75e..064509c9f 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "sway/container.h" #include "sway/input.h" #include "sway/ipc-json.h" @@ -14,16 +16,19 @@ static json_object *ipc_json_create_rect(swayc_t *c) { json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); - struct wlc_size size; + struct wlr_box box; if (c->type == C_OUTPUT) { - size = *wlc_output_get_resolution(c->handle); + wlr_output_effective_resolution(c->_handle.output, + &box.width, &box.height); } else { - size.w = c->width; - size.h = c->height; + box.width = c->width; + box.width = c->height; } - json_object_object_add(rect, "width", json_object_new_int((int32_t)size.w)); - json_object_object_add(rect, "height", json_object_new_int((int32_t)size.h)); + json_object_object_add(rect, "width", + json_object_new_int((int32_t)box.width)); + json_object_object_add(rect, "height", + json_object_new_int((int32_t)box.height)); return rect; } diff --git a/sway/main.c b/sway/main.c index efca96d5a..7d6f2873d 100644 --- a/sway/main.c +++ b/sway/main.c @@ -441,6 +441,7 @@ int main(int argc, char **argv) { if (!server_init(&server)) { return 1; } + init_layout(); ipc_init(); @@ -460,7 +461,7 @@ int main(int argc, char **argv) { security_sanity_check(); if (!terminate_request) { - wl_display_run(server.wl_display); + server_run(&server); } server_fini(&server); diff --git a/sway/server.c b/sway/server.c index 4a74cfb53..b7ce46125 100644 --- a/sway/server.c +++ b/sway/server.c @@ -27,23 +27,14 @@ bool server_init(struct sway_server *server) { server->data_device_manager = wlr_data_device_manager_create(server->wl_display); - const char *socket = wl_display_add_socket_auto(server->wl_display); - if (!socket) { - sway_log_errno(L_ERROR, "Unable to open wayland socket"); + server->output_add.notify = output_add_notify; + wl_signal_add(&server->backend->events.output_add, &server->output_add); + + server->socket = wl_display_add_socket_auto(server->wl_display); + if (!sway_assert(server->socket, "Unable to open wayland socket")) { wlr_backend_destroy(server->backend); return false; } - - sway_log(L_INFO, "Running compositor on wayland display '%s'", socket); - setenv("_WAYLAND_DISPLAY", socket, true); - - if (!wlr_backend_start(server->backend)) { - sway_log(L_ERROR, "Failed to start backend"); - wlr_backend_destroy(server->backend); - return false; - } - - setenv("WAYLAND_DISPLAY", socket, true); return true; } @@ -51,3 +42,16 @@ void server_fini(struct sway_server *server) { // TODO WLR: tear down more stuff wlr_backend_destroy(server->backend); } + +void server_run(struct sway_server *server) { + sway_log(L_INFO, "Running compositor on wayland display '%s'", + server->socket); + setenv("_WAYLAND_DISPLAY", server->socket, true); + if (!sway_assert(wlr_backend_start(server->backend), + "Failed to start backend")) { + wlr_backend_destroy(server->backend); + return; + } + setenv("WAYLAND_DISPLAY", server->socket, true); + wl_display_run(server->wl_display); +} diff --git a/sway/tree/container.c b/sway/tree/container.c index 829fde692..61c9c5e35 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "sway/config.h" #include "sway/container.h" #include "sway/workspace.h" @@ -118,10 +120,10 @@ static void update_root_geometry() { // New containers -swayc_t *new_output(wlc_handle handle) { - struct wlc_size size; - output_get_scaled_size(handle, &size); - const char *name = wlc_output_get_name(handle); +swayc_t *new_output(struct wlr_output *wlr_output) { + struct wlr_box size; + wlr_output_effective_resolution(wlr_output, &size.width, &size.height); + const char *name = wlr_output->name; // Find current outputs to see if this already exists { int i, len = root_container.children->length; @@ -129,14 +131,12 @@ swayc_t *new_output(wlc_handle handle) { swayc_t *op = root_container.children->items[i]; const char *op_name = op->name; if (op_name && name && strcmp(op_name, name) == 0) { - sway_log(L_DEBUG, "restoring output %" PRIuPTR ":%s", handle, op_name); + sway_log(L_DEBUG, "restoring output %p: %s", wlr_output, op_name); return op; } } } - sway_log(L_DEBUG, "New output %" PRIuPTR ":%s", handle, name); - struct output_config *oc = NULL, *all = NULL; int i; for (i = 0; i < config->output_configs->length; ++i) { @@ -164,10 +164,10 @@ swayc_t *new_output(wlc_handle handle) { } swayc_t *output = new_swayc(C_OUTPUT); - output->handle = handle; + output->_handle.output = wlr_output; output->name = name ? strdup(name) : NULL; - output->width = size.w; - output->height = size.h; + output->width = size.width; + output->height = size.width; output->unmanaged = create_list(); output->bg_pid = 0; From 1efd5f819f9986bf27e390f4988359388606cea0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 11 Nov 2017 14:41:18 -0500 Subject: [PATCH 008/522] Wire up output frame loop --- include/sway/container.h | 6 +++--- include/sway/output.h | 13 +++++++++++- include/sway/server.h | 1 + sway/commands/focus.c | 1 + sway/commands/move.c | 1 + sway/desktop/output.c | 45 +++++++++++++++++++++++++++++++++++++--- sway/ipc-json.c | 4 +++- sway/server.c | 4 ++++ sway/tree/container.c | 12 ++++++----- sway/tree/output.c | 1 + 10 files changed, 75 insertions(+), 13 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index f6aae7d12..09e292915 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -4,7 +4,6 @@ #include #include #include - #include "list.h" typedef struct sway_container swayc_t; @@ -76,7 +75,7 @@ struct sway_container { wlc_handle handle; union { - struct wlr_output *output; + struct sway_output *output; } _handle; /** @@ -186,10 +185,11 @@ enum visibility_mask { VISIBLE = true } visible; +struct sway_output; /** * Allocates a new output container. */ -swayc_t *new_output(struct wlr_output *wlr_output); +swayc_t *new_output(struct sway_output *sway_output); /** * Allocates a new workspace container. */ diff --git a/include/sway/output.h b/include/sway/output.h index e1bdd3f0e..2a2222385 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -1,9 +1,20 @@ #ifndef _SWAY_OUTPUT_H #define _SWAY_OUTPUT_H - +#include +#include +#include #include "container.h" #include "focus.h" +struct sway_server; + +struct sway_output { + struct wlr_output *wlr_output; + struct wl_listener frame; + struct sway_server *server; + struct timespec last_frame; +}; + // Position is absolute coordinates on the edge where the adjacent output // should be searched for. swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos); diff --git a/include/sway/server.h b/include/sway/server.h index f3e86bcba..043c1a331 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -33,5 +33,6 @@ void server_fini(struct sway_server *server); void server_run(struct sway_server *server); void output_add_notify(struct wl_listener *listener, void *data); +void output_remove_notify(struct wl_listener *listener, void *data); #endif diff --git a/sway/commands/focus.c b/sway/commands/focus.c index defaba291..c83157b85 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include #include #include diff --git a/sway/commands/move.c b/sway/commands/move.c index 8d89f2ef7..52c73e22c 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include #include #include diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 51363e768..6d0bebc54 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -1,21 +1,60 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include #include #include +#include #include "sway/server.h" #include "sway/container.h" #include "sway/workspace.h" +#include "sway/output.h" #include "log.h" +static void output_frame_notify(struct wl_listener *listener, void *data) { + struct sway_output *soutput = wl_container_of( + listener, soutput, frame); + struct wlr_output *wlr_output = data; + struct sway_server *server = soutput->server; + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + wlr_output_make_current(wlr_output); + wlr_renderer_begin(server->renderer, wlr_output); + + wlr_renderer_end(server->renderer); + wlr_output_swap_buffers(wlr_output); + + soutput->last_frame = now; +} + void output_add_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_add); struct wlr_output *wlr_output = data; sway_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); - swayc_t *op = new_output(wlr_output); - if (!sway_assert(op, "Failed to allocate output")) { + + struct sway_output *output = calloc(1, sizeof(struct sway_output)); + output->wlr_output = wlr_output; + output->server = server; + + swayc_t *node = new_output(output); + if (!sway_assert(node, "Failed to allocate output")) { return; } + // Switch to workspace if we need to if (swayc_active_workspace() == NULL) { - swayc_t *ws = op->children->items[0]; + swayc_t *ws = node->children->items[0]; workspace_switch(ws); } + + output->frame.notify = output_frame_notify; + wl_signal_add(&wlr_output->events.frame, &output->frame); +} + +void output_remove_notify(struct wl_listener *listener, void *data) { + struct sway_server *server = wl_container_of(listener, server, output_remove); + struct wlr_output *wlr_output = data; + sway_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); + // TODO } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 064509c9f..1579a2d99 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -5,6 +6,7 @@ #include #include #include +#include "sway/output.h" #include "sway/container.h" #include "sway/input.h" #include "sway/ipc-json.h" @@ -18,7 +20,7 @@ static json_object *ipc_json_create_rect(swayc_t *c) { struct wlr_box box; if (c->type == C_OUTPUT) { - wlr_output_effective_resolution(c->_handle.output, + wlr_output_effective_resolution(c->_handle.output->wlr_output, &box.width, &box.height); } else { box.width = c->width; diff --git a/sway/server.c b/sway/server.c index b7ce46125..a7f47af37 100644 --- a/sway/server.c +++ b/sway/server.c @@ -30,6 +30,10 @@ bool server_init(struct sway_server *server) { server->output_add.notify = output_add_notify; wl_signal_add(&server->backend->events.output_add, &server->output_add); + server->output_remove.notify = output_remove_notify; + wl_signal_add(&server->backend->events.output_remove, + &server->output_remove); + server->socket = wl_display_add_socket_auto(server->wl_display); if (!sway_assert(server->socket, "Unable to open wayland socket")) { wlr_backend_destroy(server->backend); diff --git a/sway/tree/container.c b/sway/tree/container.c index 61c9c5e35..25bb858e0 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -120,10 +120,11 @@ static void update_root_geometry() { // New containers -swayc_t *new_output(struct wlr_output *wlr_output) { +swayc_t *new_output(struct sway_output *sway_output) { struct wlr_box size; - wlr_output_effective_resolution(wlr_output, &size.width, &size.height); - const char *name = wlr_output->name; + wlr_output_effective_resolution(sway_output->wlr_output, + &size.width, &size.height); + const char *name = sway_output->wlr_output->name; // Find current outputs to see if this already exists { int i, len = root_container.children->length; @@ -131,7 +132,8 @@ swayc_t *new_output(struct wlr_output *wlr_output) { swayc_t *op = root_container.children->items[i]; const char *op_name = op->name; if (op_name && name && strcmp(op_name, name) == 0) { - sway_log(L_DEBUG, "restoring output %p: %s", wlr_output, op_name); + sway_log(L_DEBUG, "restoring output %p: %s", + sway_output, op_name); return op; } } @@ -164,7 +166,7 @@ swayc_t *new_output(struct wlr_output *wlr_output) { } swayc_t *output = new_swayc(C_OUTPUT); - output->_handle.output = wlr_output; + output->_handle.output = sway_output; output->name = name ? strdup(name) : NULL; output->width = size.width; output->height = size.width; diff --git a/sway/tree/output.c b/sway/tree/output.c index c0f29c5ad..edfcac981 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include #include #include From 0c8491f7d0c735299a25f0ab929f5d1e0866b929 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 11 Nov 2017 18:06:50 -0500 Subject: [PATCH 009/522] Initial (awful) pass on xdg shell support --- include/sway/container.h | 13 ++-- include/sway/server.h | 6 ++ include/sway/view.h | 56 +++++++++++++++++ sway/CMakeLists.txt | 1 + sway/config.c | 2 +- sway/desktop/xdg_shell_v6.c | 117 ++++++++++++++++++++++++++++++++++++ sway/server.c | 5 ++ sway/tree/container.c | 60 +++++++++--------- 8 files changed, 223 insertions(+), 37 deletions(-) create mode 100644 include/sway/view.h create mode 100644 sway/desktop/xdg_shell_v6.c diff --git a/include/sway/container.h b/include/sway/container.h index 09e292915..d46ffa63b 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -11,6 +11,8 @@ typedef struct sway_container swayc_t; extern swayc_t root_container; extern swayc_t *current_focus; +struct sway_view; + /** * Different kinds of containers. * @@ -27,14 +29,6 @@ enum swayc_types { C_TYPES, }; -enum swayc_view_types { - V_WL_SHELL, - V_XDG_SHELL_V6, - V_XWAYLAND, - // Keep last - V_TYPES, -}; - /** * Different ways to arrange a container. */ @@ -76,6 +70,7 @@ struct sway_container { union { struct sway_output *output; + struct sway_view *view; } _handle; /** @@ -207,7 +202,7 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); * * Pass in a sibling view, or a workspace to become this container's parent. */ -swayc_t *new_view(swayc_t *sibling, wlc_handle handle); +swayc_t *new_view(swayc_t *sibling, struct sway_view *view); /** * Allocates a new floating view in the active workspace. */ diff --git a/include/sway/server.h b/include/sway/server.h index 043c1a331..5a8a8d318 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -5,6 +5,7 @@ #include #include #include +#include #include // TODO WLR: make Xwayland optional #include @@ -24,6 +25,9 @@ struct sway_server { struct wl_listener output_add; struct wl_listener output_remove; struct wl_listener output_frame; + + struct wlr_xdg_shell_v6 *xdg_shell_v6; + struct wl_listener xdg_shell_v6_surface; }; struct sway_server server; @@ -35,4 +39,6 @@ void server_run(struct sway_server *server); void output_add_notify(struct wl_listener *listener, void *data); void output_remove_notify(struct wl_listener *listener, void *data); +void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); + #endif diff --git a/include/sway/view.h b/include/sway/view.h new file mode 100644 index 000000000..979b20a8e --- /dev/null +++ b/include/sway/view.h @@ -0,0 +1,56 @@ +#ifndef _SWAY_VIEW_H +#define _SWAY_VIEW_H +#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; +}; + +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_CLASS, + VIEW_PROP_INSTANCE, + VIEW_PROP_APP_ID, +}; + +/** + * sway_view is a state container for surfaces that are arranged in the sway + * tree (shell surfaces). + */ +struct sway_view { + struct wl_listener destroy; + enum sway_view_type type; + struct sway_container *swayc; + + union { + struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; + }; + + union { + struct sway_xdg_surface_v6 *sway_xdg_surface_v6; + }; + + struct { + const char *(*get_prop)(struct sway_view *view, + enum sway_view_prop prop); + } iface; +}; + +#endif diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 617a71f00..f9209189e 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -19,6 +19,7 @@ file(GLOB cmds add_executable(sway desktop/output.c + desktop/xdg_shell_v6.c tree/container.c tree/criteria.c diff --git a/sway/config.c b/sway/config.c index 78ab8f3b9..aa40c49a5 100644 --- a/sway/config.c +++ b/sway/config.c @@ -932,6 +932,7 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { static void invoke_swaybar(struct bar_config *bar) { return; // TODO WLR + sway_log(L_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); // Pipe to communicate errors int filedes[2]; if (pipe(filedes) == -1) { @@ -1059,7 +1060,6 @@ void load_swaybars() { if (bar->pid != 0) { terminate_swaybar(bar->pid); } - sway_log(L_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); invoke_swaybar(bar); } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c new file mode 100644 index 000000000..e29b46d7d --- /dev/null +++ b/sway/desktop/xdg_shell_v6.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include "sway/commands.h" +#include "sway/container.h" +#include "sway/focus.h" +#include "sway/ipc-server.h" +#include "sway/server.h" +#include "sway/view.h" +#include "log.h" + +// TODO: move elsewhere +static void temp_ws_cleanup() { + swayc_t *op, *ws; + int i = 0, j; + if (!root_container.children) + return; + while (i < root_container.children->length) { + op = root_container.children->items[i++]; + if (!op->children) + continue; + j = 0; + while (j < op->children->length) { + ws = op->children->items[j++]; + if (ws->children->length == 0 && ws->floating->length == 0 && ws != op->focused) { + if (destroy_workspace(ws)) { + j--; + } + } + } + } +} + +// TODO: move elsewhere +static swayc_t *move_focus_to_tiling(swayc_t *focused) { + if (focused->is_floating) { + if (focused->parent->children->length == 0) { + return focused->parent; + } + // TODO find a better way of doing this + // Or to focused container + return get_focused_container(focused->parent->children->items[0]); + } + return focused; +} + +static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { + if (!sway_assert(view->type == SWAY_XDG_SHELL_V6_VIEW, + "xdg get_prop for non-xdg view!")) { + return NULL; + } + switch (prop) { + case VIEW_PROP_TITLE: + return view->wlr_xdg_surface_v6->title; + case VIEW_PROP_APP_ID: + return view->wlr_xdg_surface_v6->app_id; + default: + return NULL; + } +} + +void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { + struct sway_server *server = wl_container_of( + listener, server, xdg_shell_v6_surface); + struct wlr_xdg_surface_v6 *xdg_surface = data; + + if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { + // TODO: popups + return; + } + + sway_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", + xdg_surface->title, xdg_surface->app_id); + wlr_xdg_surface_v6_ping(xdg_surface); + + struct sway_xdg_surface_v6 *sway_surface = + calloc(1, sizeof(struct sway_xdg_surface_v6)); + if (!sway_assert(sway_surface, "Failed to allocate surface!")) { + return; + } + + struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); + if (!sway_assert(sway_view, "Failed to allocate view!")) { + return; + } + sway_view->type = SWAY_XDG_SHELL_V6_VIEW; + sway_view->iface.get_prop = get_prop; + sway_surface->view = sway_view; + + // TODO: + // - Consolodate common logic between shells + // - Wire up listeners + // - Handle popups + // - Look up pid and open on appropriate workspace + // - Set new view to maximized so it behaves nicely + // - Criteria + + suspend_workspace_cleanup = true; + //swayc_t *current_ws = swayc_active_workspace(); + swayc_t *prev_focus = get_focused_container(&root_container); + swayc_t *focused = move_focus_to_tiling(prev_focus); + + // TODO: fix new_view + swayc_t *view = new_view(focused, sway_view); + ipc_event_window(view, "new"); + set_focused_container(view); + + swayc_t *output = swayc_parent_by_type(view, C_OUTPUT); + arrange_windows(output, -1, -1); + + swayc_t *workspace = swayc_parent_by_type(focused, C_WORKSPACE); + if (workspace && workspace->fullscreen) { + set_focused_container(workspace->fullscreen); + } + suspend_workspace_cleanup = false; + temp_ws_cleanup(); +} diff --git a/sway/server.c b/sway/server.c index a7f47af37..940f28b31 100644 --- a/sway/server.c +++ b/sway/server.c @@ -34,6 +34,11 @@ bool server_init(struct sway_server *server) { wl_signal_add(&server->backend->events.output_remove, &server->output_remove); + server->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display); + wl_signal_add(&server->xdg_shell_v6->events.new_surface, + &server->xdg_shell_v6_surface); + server->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface; + server->socket = wl_display_add_socket_auto(server->wl_display); if (!sway_assert(server->socket, "Unable to open wayland socket")) { wlr_backend_destroy(server->backend); diff --git a/sway/tree/container.c b/sway/tree/container.c index 25bb858e0..82c0d8770 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -15,6 +15,7 @@ #include "sway/input_state.h" #include "sway/ipc-server.h" #include "sway/output.h" +#include "sway/view.h" #include "log.h" #include "stringop.h" @@ -291,44 +292,49 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { return cont; } -swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { +swayc_t *new_view(swayc_t *sibling, struct sway_view *view) { if (!ASSERT_NONNULL(sibling)) { return NULL; } - const char *title = wlc_view_get_title(handle); - swayc_t *view = new_swayc(C_VIEW); - sway_log(L_DEBUG, "Adding new view %" PRIuPTR ":%s to container %p %d", - handle, title, sibling, sibling ? sibling->type : 0); + const char *title = view->iface.get_prop(view, VIEW_PROP_TITLE); + swayc_t *swayc = new_swayc(C_VIEW); + sway_log(L_DEBUG, "Adding new view %p:%s to container %p %d", + swayc, title, sibling, sibling ? sibling->type : 0); // Setup values - view->handle = handle; - view->name = title ? strdup(title) : NULL; - const char *class = wlc_view_get_class(handle); - view->class = class ? strdup(class) : NULL; - const char *instance = wlc_view_get_instance(handle); - view->instance = instance ? strdup(instance) : NULL; - const char *app_id = wlc_view_get_app_id(handle); - view->app_id = app_id ? strdup(app_id) : NULL; - view->visible = true; - view->is_focused = true; - view->sticky = false; - view->width = 0; - view->height = 0; - view->desired_width = -1; - view->desired_height = -1; - // setup border - view->border_type = config->border; - view->border_thickness = config->border_thickness; + swayc->_handle.view = view; - view->is_floating = false; + swayc->name = title ? strdup(title) : NULL; + + const char *class = view->iface.get_prop(view, VIEW_PROP_CLASS); + swayc->class = class ? strdup(class) : NULL; + + const char *instance = view->iface.get_prop(view, VIEW_PROP_INSTANCE); + swayc->instance = instance ? strdup(instance) : NULL; + + const char *app_id = view->iface.get_prop(view, VIEW_PROP_APP_ID); + swayc->app_id = app_id ? strdup(app_id) : NULL; + + swayc->visible = true; + swayc->is_focused = true; + swayc->sticky = false; + swayc->width = 0; + swayc->height = 0; + swayc->desired_width = -1; + swayc->desired_height = -1; + // setup border + swayc->border_type = config->border; + swayc->border_thickness = config->border_thickness; + + swayc->is_floating = false; if (sibling->type == C_WORKSPACE) { // Case of focused workspace, just create as child of it - add_child(sibling, view); + add_child(sibling, swayc); } else { // Regular case, create as sibling of current container - add_sibling(sibling, view); + add_sibling(sibling, swayc); } - return view; + return swayc; } swayc_t *new_floating_view(wlc_handle handle) { From 733993a651c71f7e2198d505960d6bbd31e0e107 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 18 Nov 2017 11:22:02 -0500 Subject: [PATCH 010/522] Move everything to sway/old/ --- CMakeLists.txt | 12 +- common/log.c | 2 +- include/sway.h | 6 - include/sway/handlers.h | 11 -- include/sway/{ => old}/border.h | 0 include/sway/{ => old}/commands.h | 0 include/sway/{ => old}/config.h | 0 include/sway/{ => old}/container.h | 0 include/sway/{ => old}/criteria.h | 0 include/sway/{ => old}/focus.h | 0 include/sway/{ => old}/input.h | 0 include/sway/{ => old}/input_state.h | 0 include/sway/{ => old}/ipc-json.h | 0 include/sway/{ => old}/ipc-server.h | 8 - include/sway/{ => old}/layout.h | 0 include/sway/old/output.h | 36 +++++ include/sway/{ => old}/workspace.h | 0 include/sway/output.h | 22 +-- sway/CMakeLists.txt | 27 ---- sway/debug_log.c | 103 ------------- sway/desktop/output.c | 19 +-- sway/desktop/xdg_shell_v6.c | 61 +------- sway/main.c | 54 +++---- sway/{ => old}/border.c | 0 sway/{ => old}/commands.c | 0 sway/{ => old}/commands/assign.c | 0 sway/{ => old}/commands/bar.c | 0 sway/{ => old}/commands/bar/activate_button.c | 0 .../commands/bar/binding_mode_indicator.c | 0 sway/{ => old}/commands/bar/bindsym.c | 0 sway/{ => old}/commands/bar/colors.c | 0 sway/{ => old}/commands/bar/context_button.c | 0 sway/{ => old}/commands/bar/font.c | 0 sway/{ => old}/commands/bar/height.c | 0 sway/{ => old}/commands/bar/hidden_state.c | 0 sway/{ => old}/commands/bar/icon_theme.c | 0 sway/{ => old}/commands/bar/id.c | 0 sway/{ => old}/commands/bar/mode.c | 0 sway/{ => old}/commands/bar/modifier.c | 0 sway/{ => old}/commands/bar/output.c | 0 sway/{ => old}/commands/bar/pango_markup.c | 0 sway/{ => old}/commands/bar/position.c | 0 .../{ => old}/commands/bar/secondary_button.c | 0 .../{ => old}/commands/bar/separator_symbol.c | 0 sway/{ => old}/commands/bar/status_command.c | 0 .../commands/bar/strip_workspace_numbers.c | 0 sway/{ => old}/commands/bar/swaybar_command.c | 0 sway/{ => old}/commands/bar/tray_output.c | 0 sway/{ => old}/commands/bar/tray_padding.c | 0 .../commands/bar/workspace_buttons.c | 0 sway/{ => old}/commands/bar/wrap_scroll.c | 0 sway/{ => old}/commands/bind.c | 0 sway/{ => old}/commands/border.c | 0 sway/{ => old}/commands/client.c | 0 sway/{ => old}/commands/clipboard.c | 0 sway/{ => old}/commands/commands.c | 0 sway/{ => old}/commands/debuglog.c | 0 sway/{ => old}/commands/default_border.c | 0 .../commands/default_floating_border.c | 0 sway/{ => old}/commands/exec.c | 0 sway/{ => old}/commands/exec_always.c | 0 sway/{ => old}/commands/exit.c | 0 sway/{ => old}/commands/floating.c | 0 .../commands/floating_maximum_size.c | 0 .../commands/floating_minimum_size.c | 0 sway/{ => old}/commands/floating_mod.c | 0 sway/{ => old}/commands/floating_scroll.c | 0 sway/{ => old}/commands/focus.c | 0 sway/{ => old}/commands/focus_follows_mouse.c | 0 sway/{ => old}/commands/font.c | 0 sway/{ => old}/commands/for_window.c | 0 .../{ => old}/commands/force_focus_wrapping.c | 0 sway/{ => old}/commands/fullscreen.c | 0 sway/{ => old}/commands/gaps.c | 0 sway/{ => old}/commands/hide_edge_borders.c | 0 sway/{ => old}/commands/include.c | 0 sway/{ => old}/commands/input.c | 0 sway/{ => old}/commands/input/accel_profile.c | 0 sway/{ => old}/commands/input/click_method.c | 0 sway/{ => old}/commands/input/drag_lock.c | 0 sway/{ => old}/commands/input/dwt.c | 0 sway/{ => old}/commands/input/events.c | 0 sway/{ => old}/commands/input/left_handed.c | 0 .../commands/input/middle_emulation.c | 0 .../{ => old}/commands/input/natural_scroll.c | 0 sway/{ => old}/commands/input/pointer_accel.c | 0 sway/{ => old}/commands/input/scroll_method.c | 0 sway/{ => old}/commands/input/tap.c | 0 sway/{ => old}/commands/ipc.c | 0 sway/{ => old}/commands/kill.c | 0 sway/{ => old}/commands/layout.c | 0 sway/{ => old}/commands/log_colors.c | 0 sway/{ => old}/commands/mark.c | 0 sway/{ => old}/commands/mode.c | 0 sway/{ => old}/commands/mouse_warping.c | 0 sway/{ => old}/commands/move.c | 0 sway/{ => old}/commands/new_float.c | 0 sway/{ => old}/commands/new_window.c | 0 sway/{ => old}/commands/no_focus.c | 0 sway/{ => old}/commands/orientation.c | 0 sway/{ => old}/commands/output.c | 0 sway/{ => old}/commands/permit.c | 0 sway/{ => old}/commands/reload.c | 0 sway/{ => old}/commands/resize.c | 0 sway/{ => old}/commands/scratchpad.c | 0 sway/{ => old}/commands/seamless_mouse.c | 0 sway/{ => old}/commands/set.c | 0 sway/{ => old}/commands/show_marks.c | 0 sway/{ => old}/commands/smart_gaps.c | 0 sway/{ => old}/commands/split.c | 0 sway/{ => old}/commands/sticky.c | 0 sway/{ => old}/commands/unmark.c | 0 sway/{ => old}/commands/workspace.c | 0 .../commands/workspace_auto_back_and_forth.c | 0 sway/{ => old}/commands/workspace_layout.c | 0 sway/{ => old}/config.c | 138 +----------------- sway/{tree => old}/container.c | 0 sway/{tree => old}/criteria.c | 0 sway/{tree => old}/focus.c | 0 sway/{ => old}/handlers.c | 0 sway/{ => old}/input_state.c | 0 sway/{ => old}/ipc-json.c | 0 sway/{ => old}/ipc-server.c | 5 - sway/{tree => old}/layout.c | 0 sway/{tree => old}/output.c | 0 sway/{ => old}/security.c | 0 sway/{tree => old}/workspace.c | 0 sway/server.c | 2 - 128 files changed, 76 insertions(+), 430 deletions(-) delete mode 100644 include/sway.h delete mode 100644 include/sway/handlers.h rename include/sway/{ => old}/border.h (100%) rename include/sway/{ => old}/commands.h (100%) rename include/sway/{ => old}/config.h (100%) rename include/sway/{ => old}/container.h (100%) rename include/sway/{ => old}/criteria.h (100%) rename include/sway/{ => old}/focus.h (100%) rename include/sway/{ => old}/input.h (100%) rename include/sway/{ => old}/input_state.h (100%) rename include/sway/{ => old}/ipc-json.h (100%) rename include/sway/{ => old}/ipc-server.h (89%) rename include/sway/{ => old}/layout.h (100%) create mode 100644 include/sway/old/output.h rename include/sway/{ => old}/workspace.h (100%) delete mode 100644 sway/debug_log.c rename sway/{ => old}/border.c (100%) rename sway/{ => old}/commands.c (100%) rename sway/{ => old}/commands/assign.c (100%) rename sway/{ => old}/commands/bar.c (100%) rename sway/{ => old}/commands/bar/activate_button.c (100%) rename sway/{ => old}/commands/bar/binding_mode_indicator.c (100%) rename sway/{ => old}/commands/bar/bindsym.c (100%) rename sway/{ => old}/commands/bar/colors.c (100%) rename sway/{ => old}/commands/bar/context_button.c (100%) rename sway/{ => old}/commands/bar/font.c (100%) rename sway/{ => old}/commands/bar/height.c (100%) rename sway/{ => old}/commands/bar/hidden_state.c (100%) rename sway/{ => old}/commands/bar/icon_theme.c (100%) rename sway/{ => old}/commands/bar/id.c (100%) rename sway/{ => old}/commands/bar/mode.c (100%) rename sway/{ => old}/commands/bar/modifier.c (100%) rename sway/{ => old}/commands/bar/output.c (100%) rename sway/{ => old}/commands/bar/pango_markup.c (100%) rename sway/{ => old}/commands/bar/position.c (100%) rename sway/{ => old}/commands/bar/secondary_button.c (100%) rename sway/{ => old}/commands/bar/separator_symbol.c (100%) rename sway/{ => old}/commands/bar/status_command.c (100%) rename sway/{ => old}/commands/bar/strip_workspace_numbers.c (100%) rename sway/{ => old}/commands/bar/swaybar_command.c (100%) rename sway/{ => old}/commands/bar/tray_output.c (100%) rename sway/{ => old}/commands/bar/tray_padding.c (100%) rename sway/{ => old}/commands/bar/workspace_buttons.c (100%) rename sway/{ => old}/commands/bar/wrap_scroll.c (100%) rename sway/{ => old}/commands/bind.c (100%) rename sway/{ => old}/commands/border.c (100%) rename sway/{ => old}/commands/client.c (100%) rename sway/{ => old}/commands/clipboard.c (100%) rename sway/{ => old}/commands/commands.c (100%) rename sway/{ => old}/commands/debuglog.c (100%) rename sway/{ => old}/commands/default_border.c (100%) rename sway/{ => old}/commands/default_floating_border.c (100%) rename sway/{ => old}/commands/exec.c (100%) rename sway/{ => old}/commands/exec_always.c (100%) rename sway/{ => old}/commands/exit.c (100%) rename sway/{ => old}/commands/floating.c (100%) rename sway/{ => old}/commands/floating_maximum_size.c (100%) rename sway/{ => old}/commands/floating_minimum_size.c (100%) rename sway/{ => old}/commands/floating_mod.c (100%) rename sway/{ => old}/commands/floating_scroll.c (100%) rename sway/{ => old}/commands/focus.c (100%) rename sway/{ => old}/commands/focus_follows_mouse.c (100%) rename sway/{ => old}/commands/font.c (100%) rename sway/{ => old}/commands/for_window.c (100%) rename sway/{ => old}/commands/force_focus_wrapping.c (100%) rename sway/{ => old}/commands/fullscreen.c (100%) rename sway/{ => old}/commands/gaps.c (100%) rename sway/{ => old}/commands/hide_edge_borders.c (100%) rename sway/{ => old}/commands/include.c (100%) rename sway/{ => old}/commands/input.c (100%) rename sway/{ => old}/commands/input/accel_profile.c (100%) rename sway/{ => old}/commands/input/click_method.c (100%) rename sway/{ => old}/commands/input/drag_lock.c (100%) rename sway/{ => old}/commands/input/dwt.c (100%) rename sway/{ => old}/commands/input/events.c (100%) rename sway/{ => old}/commands/input/left_handed.c (100%) rename sway/{ => old}/commands/input/middle_emulation.c (100%) rename sway/{ => old}/commands/input/natural_scroll.c (100%) rename sway/{ => old}/commands/input/pointer_accel.c (100%) rename sway/{ => old}/commands/input/scroll_method.c (100%) rename sway/{ => old}/commands/input/tap.c (100%) rename sway/{ => old}/commands/ipc.c (100%) rename sway/{ => old}/commands/kill.c (100%) rename sway/{ => old}/commands/layout.c (100%) rename sway/{ => old}/commands/log_colors.c (100%) rename sway/{ => old}/commands/mark.c (100%) rename sway/{ => old}/commands/mode.c (100%) rename sway/{ => old}/commands/mouse_warping.c (100%) rename sway/{ => old}/commands/move.c (100%) rename sway/{ => old}/commands/new_float.c (100%) rename sway/{ => old}/commands/new_window.c (100%) rename sway/{ => old}/commands/no_focus.c (100%) rename sway/{ => old}/commands/orientation.c (100%) rename sway/{ => old}/commands/output.c (100%) rename sway/{ => old}/commands/permit.c (100%) rename sway/{ => old}/commands/reload.c (100%) rename sway/{ => old}/commands/resize.c (100%) rename sway/{ => old}/commands/scratchpad.c (100%) rename sway/{ => old}/commands/seamless_mouse.c (100%) rename sway/{ => old}/commands/set.c (100%) rename sway/{ => old}/commands/show_marks.c (100%) rename sway/{ => old}/commands/smart_gaps.c (100%) rename sway/{ => old}/commands/split.c (100%) rename sway/{ => old}/commands/sticky.c (100%) rename sway/{ => old}/commands/unmark.c (100%) rename sway/{ => old}/commands/workspace.c (100%) rename sway/{ => old}/commands/workspace_auto_back_and_forth.c (100%) rename sway/{ => old}/commands/workspace_layout.c (100%) rename sway/{ => old}/config.c (88%) rename sway/{tree => old}/container.c (100%) rename sway/{tree => old}/criteria.c (100%) rename sway/{tree => old}/focus.c (100%) rename sway/{ => old}/handlers.c (100%) rename sway/{ => old}/input_state.c (100%) rename sway/{ => old}/ipc-json.c (100%) rename sway/{ => old}/ipc-server.c (99%) rename sway/{tree => old}/layout.c (100%) rename sway/{tree => old}/output.c (100%) rename sway/{ => old}/security.c (100%) rename sway/{tree => old}/workspace.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34098eb36..b53670b6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,8 @@ add_subdirectory(wayland) add_subdirectory(sway) if(enable-swaybg) if(CAIRO_FOUND AND PANGO_FOUND) - add_subdirectory(swaybg) + # TODO WLR + #add_subdirectory(swaybg) else() message(WARNING "Not building swaybg - cairo, and pango are required.") endif() @@ -125,18 +126,21 @@ if(enable-swaymsg) add_subdirectory(swaymsg) endif() if(enable-swaygrab) - add_subdirectory(swaygrab) + # TODO WLR + #add_subdirectory(swaygrab) endif() if(enable-swaybar) if(CAIRO_FOUND AND PANGO_FOUND) - add_subdirectory(swaybar) + # TODO WLR + #add_subdirectory(swaybar) else() message(WARNING "Not building swaybar - cairo, and pango are required.") endif() endif() if(enable-swaylock) if(CAIRO_FOUND AND PANGO_FOUND AND PAM_FOUND) - add_subdirectory(swaylock) + # TODO WLR + #add_subdirectory(swaylock) else() message(WARNING "Not building swaylock - cairo, pango, and PAM are required.") endif() diff --git a/common/log.c b/common/log.c index 6dc9d7432..c47b4eeae 100644 --- a/common/log.c +++ b/common/log.c @@ -9,7 +9,6 @@ #include #include #include "log.h" -#include "sway.h" #include "readline.h" static int colored = 1; @@ -117,6 +116,7 @@ void _sway_log(const char *filename, int line, log_importance_t verbosity, const va_end(args); } +void sway_terminate(int code); void _sway_abort(const char *filename, int line, const char* format, ...) { va_list args; diff --git a/include/sway.h b/include/sway.h deleted file mode 100644 index b5cfb668e..000000000 --- a/include/sway.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SWAY_SWAY_H -#define _SWAY_SWAY_H - -void sway_terminate(int exit_code); - -#endif diff --git a/include/sway/handlers.h b/include/sway/handlers.h deleted file mode 100644 index 956b98f45..000000000 --- a/include/sway/handlers.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _SWAY_HANDLERS_H -#define _SWAY_HANDLERS_H -#include "container.h" -#include -#include - -void register_wlc_handlers(); - -extern uint32_t keys_pressed[32]; - -#endif diff --git a/include/sway/border.h b/include/sway/old/border.h similarity index 100% rename from include/sway/border.h rename to include/sway/old/border.h diff --git a/include/sway/commands.h b/include/sway/old/commands.h similarity index 100% rename from include/sway/commands.h rename to include/sway/old/commands.h diff --git a/include/sway/config.h b/include/sway/old/config.h similarity index 100% rename from include/sway/config.h rename to include/sway/old/config.h diff --git a/include/sway/container.h b/include/sway/old/container.h similarity index 100% rename from include/sway/container.h rename to include/sway/old/container.h diff --git a/include/sway/criteria.h b/include/sway/old/criteria.h similarity index 100% rename from include/sway/criteria.h rename to include/sway/old/criteria.h diff --git a/include/sway/focus.h b/include/sway/old/focus.h similarity index 100% rename from include/sway/focus.h rename to include/sway/old/focus.h diff --git a/include/sway/input.h b/include/sway/old/input.h similarity index 100% rename from include/sway/input.h rename to include/sway/old/input.h diff --git a/include/sway/input_state.h b/include/sway/old/input_state.h similarity index 100% rename from include/sway/input_state.h rename to include/sway/old/input_state.h diff --git a/include/sway/ipc-json.h b/include/sway/old/ipc-json.h similarity index 100% rename from include/sway/ipc-json.h rename to include/sway/old/ipc-json.h diff --git a/include/sway/ipc-server.h b/include/sway/old/ipc-server.h similarity index 89% rename from include/sway/ipc-server.h rename to include/sway/old/ipc-server.h index 1d1991345..0cc26d990 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/old/ipc-server.h @@ -1,8 +1,5 @@ #ifndef _SWAY_IPC_SERVER_H #define _SWAY_IPC_SERVER_H - -#include - #include "container.h" #include "config.h" #include "ipc.h" @@ -33,9 +30,4 @@ void ipc_event_modifier(uint32_t modifier, const char *state); void ipc_event_binding_keyboard(struct sway_binding *sb); const char *swayc_type_string(enum swayc_types type); -/** - * Send pixel data to registered clients. - */ -void ipc_get_pixels(wlc_handle output); - #endif diff --git a/include/sway/layout.h b/include/sway/old/layout.h similarity index 100% rename from include/sway/layout.h rename to include/sway/old/layout.h diff --git a/include/sway/old/output.h b/include/sway/old/output.h new file mode 100644 index 000000000..2a2222385 --- /dev/null +++ b/include/sway/old/output.h @@ -0,0 +1,36 @@ +#ifndef _SWAY_OUTPUT_H +#define _SWAY_OUTPUT_H +#include +#include +#include +#include "container.h" +#include "focus.h" + +struct sway_server; + +struct sway_output { + struct wlr_output *wlr_output; + struct wl_listener frame; + struct sway_server *server; + struct timespec last_frame; +}; + +// Position is absolute coordinates on the edge where the adjacent output +// should be searched for. +swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos); +swayc_t *swayc_opposite_output(enum movement_direction dir, const struct wlc_point *abs_pos); +swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir, const struct wlc_point *abs_pos, bool pick_closest); + +// Place absolute coordinates for given container into given wlc_point. +void get_absolute_position(swayc_t *container, struct wlc_point *point); + +// Place absolute coordinates for the center point of given container into +// given wlc_point. +void get_absolute_center_position(swayc_t *container, struct wlc_point *point); + +// stable sort workspaces on this output +void sort_workspaces(swayc_t *output); + +void output_get_scaled_size(wlc_handle handle, struct wlc_size *size); + +#endif diff --git a/include/sway/workspace.h b/include/sway/old/workspace.h similarity index 100% rename from include/sway/workspace.h rename to include/sway/old/workspace.h diff --git a/include/sway/output.h b/include/sway/output.h index 2a2222385..ffc6708dc 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -3,34 +3,14 @@ #include #include #include -#include "container.h" -#include "focus.h" struct sway_server; struct sway_output { struct wlr_output *wlr_output; - struct wl_listener frame; struct sway_server *server; struct timespec last_frame; + struct wl_listener frame; }; -// Position is absolute coordinates on the edge where the adjacent output -// should be searched for. -swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos); -swayc_t *swayc_opposite_output(enum movement_direction dir, const struct wlc_point *abs_pos); -swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir, const struct wlc_point *abs_pos, bool pick_closest); - -// Place absolute coordinates for given container into given wlc_point. -void get_absolute_position(swayc_t *container, struct wlc_point *point); - -// Place absolute coordinates for the center point of given container into -// given wlc_point. -void get_absolute_center_position(swayc_t *container, struct wlc_point *point); - -// stable sort workspaces on this output -void sort_workspaces(swayc_t *output); - -void output_get_scaled_size(wlc_handle handle, struct wlc_size *size); - #endif diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index f9209189e..73531a847 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -1,6 +1,5 @@ include_directories( ${PROTOCOLS_INCLUDE_DIRS} - ${WLC_INCLUDE_DIRS} ${WLR_INCLUDE_DIRS} ${PCRE_INCLUDE_DIRS} ${JSONC_INCLUDE_DIRS} @@ -11,37 +10,12 @@ include_directories( ${WAYLAND_INCLUDE_DIR} ) -file(GLOB cmds - "commands/*.c" - "commands/bar/*.c" - "commands/input/*.c" -) - add_executable(sway desktop/output.c desktop/xdg_shell_v6.c - tree/container.c - tree/criteria.c - tree/focus.c - tree/output.c - tree/workspace.c - tree/layout.c - - input/input.c - - commands.c - ${cmds} - base64.c - config.c - debug_log.c - input_state.c - ipc-json.c - ipc-server.c main.c - border.c - security.c server.c ) @@ -53,7 +27,6 @@ target_link_libraries(sway sway-common sway-protocols sway-wayland - ${WLC_LIBRARIES} ${WLR_LIBRARIES} ${XKBCOMMON_LIBRARIES} ${PCRE_LIBRARIES} diff --git a/sway/debug_log.c b/sway/debug_log.c deleted file mode 100644 index d1eafae8f..000000000 --- a/sway/debug_log.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "log.h" -#include "sway.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sway/workspace.h" - -/* XXX:DEBUG:XXX */ -static void container_log(const swayc_t *c, int depth) { - fprintf(stderr, "focus:%c", - c == get_focused_view(&root_container) ? 'K': - c == get_focused_container(&root_container) ? 'F' : // Focused - c == swayc_active_workspace() ? 'W' : // active workspace - c == &root_container ? 'R' : // root - 'X');// not any others - for (int i = 6; i > depth; i--) { fprintf(stderr, " "); } - fprintf(stderr,"|(%p)",c); - fprintf(stderr,"(p:%-8p)",c->parent); - fprintf(stderr,"(f:%-8p)",c->focused); - fprintf(stderr,"(h:%2" PRIuPTR ")",c->handle); - fprintf(stderr,"Type:%-4s|", - c->type == C_ROOT ? "root" : - c->type == C_OUTPUT ? "op" : - c->type == C_WORKSPACE ? "ws" : - c->type == C_CONTAINER ? "cont" : - c->type == C_VIEW ? "view" : "?"); - fprintf(stderr,"layout:%-5s|", - c->layout == L_NONE ? "-" : - c->layout == L_HORIZ ? "Horiz": - c->layout == L_VERT ? "Vert": - c->layout == L_STACKED ? "Stack": - c->layout == L_TABBED ? "Tab": - c->layout == L_FLOATING ? "Float": - c->layout == L_AUTO_LEFT ? "A_lft": - c->layout == L_AUTO_RIGHT ? "A_rgt": - c->layout == L_AUTO_TOP ? "A_top": - c->layout == L_AUTO_BOTTOM ? "A_bot": - "Unknown"); - fprintf(stderr, "w:%4.f|h:%4.f|", c->width, c->height); - fprintf(stderr, "x:%4.f|y:%4.f|", c->x, c->y); - fprintf(stderr, "g:%3d|",c->gaps); - fprintf(stderr, "vis:%c|", c->visible?'t':'f'); - fprintf(stderr, "children:%2d|",c->children?c->children->length:0); - fprintf(stderr, "name:%.16s\n", c->name); -} -void layout_log(const swayc_t *c, int depth) { - if (L_DEBUG > get_log_level()) return; - int i, d; - int e = c->children ? c->children->length : 0; - container_log(c, depth); - if (e) { - for (i = 0; i < e; ++i) { - fputc('|',stderr); - for (d = 0; d < depth; ++d) fputc('-', stderr); - layout_log(c->children->items[i], depth + 1); - } - } - if (c->type == C_WORKSPACE) { - e = c->floating?c->floating->length:0; - if (e) { - for (i = 0; i < e; ++i) { - fputc('|',stderr); - for (d = 0; d < depth; ++d) fputc('=', stderr); - layout_log(c->floating->items[i], depth + 1); - } - } - } -} - -const char *swayc_type_string(enum swayc_types type) { - return type == C_ROOT ? "ROOT" : - type == C_OUTPUT ? "OUTPUT" : - type == C_WORKSPACE ? "WORKSPACE" : - type == C_CONTAINER ? "CONTAINER" : - type == C_VIEW ? "VIEW" : - "UNKNOWN"; -} - -// Like sway_log, but also appends some info about given container to log output. -void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ...) { - sway_assert(cont, "swayc_log: no container ..."); - va_list args; - va_start(args, format); - char *txt = malloc(128); - vsprintf(txt, format, args); - va_end(args); - - char *debug_txt = malloc(32); - snprintf(debug_txt, 32, "%s '%s'", swayc_type_string(cont->type), cont->name); - - sway_log(verbosity, "%s (%s)", txt, debug_txt); - free(txt); - free(debug_txt); -} - -/* XXX:DEBUG:XXX */ diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6d0bebc54..6ddcac3ba 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -4,11 +4,9 @@ #include #include #include -#include "sway/server.h" -#include "sway/container.h" -#include "sway/workspace.h" -#include "sway/output.h" #include "log.h" +#include "sway/output.h" +#include "sway/server.h" static void output_frame_notify(struct wl_listener *listener, void *data) { struct sway_output *soutput = wl_container_of( @@ -37,19 +35,10 @@ void output_add_notify(struct wl_listener *listener, void *data) { output->wlr_output = wlr_output; output->server = server; - swayc_t *node = new_output(output); - if (!sway_assert(node, "Failed to allocate output")) { - return; - } - - // Switch to workspace if we need to - if (swayc_active_workspace() == NULL) { - swayc_t *ws = node->children->items[0]; - workspace_switch(ws); - } - output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); + + // TODO: Add to tree } void output_remove_notify(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index e29b46d7d..04f3f42c2 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -1,49 +1,10 @@ #include #include #include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/focus.h" -#include "sway/ipc-server.h" #include "sway/server.h" #include "sway/view.h" #include "log.h" -// TODO: move elsewhere -static void temp_ws_cleanup() { - swayc_t *op, *ws; - int i = 0, j; - if (!root_container.children) - return; - while (i < root_container.children->length) { - op = root_container.children->items[i++]; - if (!op->children) - continue; - j = 0; - while (j < op->children->length) { - ws = op->children->items[j++]; - if (ws->children->length == 0 && ws->floating->length == 0 && ws != op->focused) { - if (destroy_workspace(ws)) { - j--; - } - } - } - } -} - -// TODO: move elsewhere -static swayc_t *move_focus_to_tiling(swayc_t *focused) { - if (focused->is_floating) { - if (focused->parent->children->length == 0) { - return focused->parent; - } - // TODO find a better way of doing this - // Or to focused container - return get_focused_container(focused->parent->children->items[0]); - } - return focused; -} - static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { if (!sway_assert(view->type == SWAY_XDG_SHELL_V6_VIEW, "xdg get_prop for non-xdg view!")) { @@ -88,30 +49,10 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_surface->view = sway_view; // TODO: - // - Consolodate common logic between shells + // - Add to tree // - Wire up listeners // - Handle popups // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria - - suspend_workspace_cleanup = true; - //swayc_t *current_ws = swayc_active_workspace(); - swayc_t *prev_focus = get_focused_container(&root_container); - swayc_t *focused = move_focus_to_tiling(prev_focus); - - // TODO: fix new_view - swayc_t *view = new_view(focused, sway_view); - ipc_event_window(view, "new"); - set_focused_container(view); - - swayc_t *output = swayc_parent_by_type(view, C_OUTPUT); - arrange_windows(output, -1, -1); - - swayc_t *workspace = swayc_parent_by_type(focused, C_WORKSPACE); - if (workspace && workspace->fullscreen) { - set_focused_container(workspace->fullscreen); - } - suspend_workspace_cleanup = false; - temp_ws_cleanup(); } diff --git a/sway/main.c b/sway/main.c index 7d6f2873d..5710a099a 100644 --- a/sway/main.c +++ b/sway/main.c @@ -1,30 +1,24 @@ #define _XOPEN_SOURCE 700 #define _POSIX_C_SOURCE 200112L -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef __linux__ #include #include #endif -#include "sway/layout.h" -#include "sway/config.h" -#include "sway/security.h" -#include "sway/handlers.h" -#include "sway/input.h" -#include "sway/ipc-server.h" #include "sway/server.h" #include "ipc-client.h" #include "readline.h" #include "stringop.h" -#include "sway.h" #include "log.h" #include "util.h" @@ -39,7 +33,7 @@ void sway_terminate(int exit_code) { } void sig_handler(int signal) { - close_views(&root_container); + //close_views(&root_container); sway_terminate(EXIT_SUCCESS); } @@ -442,17 +436,17 @@ int main(int argc, char **argv) { return 1; } - init_layout(); - ipc_init(); + //init_layout(); + //ipc_init(); - 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); @@ -466,11 +460,11 @@ int main(int argc, char **argv) { server_fini(&server); - ipc_terminate(); + //ipc_terminate(); - if (config) { - free_config(config); - } + //if (config) { + // free_config(config); + //} return exit_value; } diff --git a/sway/border.c b/sway/old/border.c similarity index 100% rename from sway/border.c rename to sway/old/border.c diff --git a/sway/commands.c b/sway/old/commands.c similarity index 100% rename from sway/commands.c rename to sway/old/commands.c diff --git a/sway/commands/assign.c b/sway/old/commands/assign.c similarity index 100% rename from sway/commands/assign.c rename to sway/old/commands/assign.c diff --git a/sway/commands/bar.c b/sway/old/commands/bar.c similarity index 100% rename from sway/commands/bar.c rename to sway/old/commands/bar.c diff --git a/sway/commands/bar/activate_button.c b/sway/old/commands/bar/activate_button.c similarity index 100% rename from sway/commands/bar/activate_button.c rename to sway/old/commands/bar/activate_button.c diff --git a/sway/commands/bar/binding_mode_indicator.c b/sway/old/commands/bar/binding_mode_indicator.c similarity index 100% rename from sway/commands/bar/binding_mode_indicator.c rename to sway/old/commands/bar/binding_mode_indicator.c diff --git a/sway/commands/bar/bindsym.c b/sway/old/commands/bar/bindsym.c similarity index 100% rename from sway/commands/bar/bindsym.c rename to sway/old/commands/bar/bindsym.c diff --git a/sway/commands/bar/colors.c b/sway/old/commands/bar/colors.c similarity index 100% rename from sway/commands/bar/colors.c rename to sway/old/commands/bar/colors.c diff --git a/sway/commands/bar/context_button.c b/sway/old/commands/bar/context_button.c similarity index 100% rename from sway/commands/bar/context_button.c rename to sway/old/commands/bar/context_button.c diff --git a/sway/commands/bar/font.c b/sway/old/commands/bar/font.c similarity index 100% rename from sway/commands/bar/font.c rename to sway/old/commands/bar/font.c diff --git a/sway/commands/bar/height.c b/sway/old/commands/bar/height.c similarity index 100% rename from sway/commands/bar/height.c rename to sway/old/commands/bar/height.c diff --git a/sway/commands/bar/hidden_state.c b/sway/old/commands/bar/hidden_state.c similarity index 100% rename from sway/commands/bar/hidden_state.c rename to sway/old/commands/bar/hidden_state.c diff --git a/sway/commands/bar/icon_theme.c b/sway/old/commands/bar/icon_theme.c similarity index 100% rename from sway/commands/bar/icon_theme.c rename to sway/old/commands/bar/icon_theme.c diff --git a/sway/commands/bar/id.c b/sway/old/commands/bar/id.c similarity index 100% rename from sway/commands/bar/id.c rename to sway/old/commands/bar/id.c diff --git a/sway/commands/bar/mode.c b/sway/old/commands/bar/mode.c similarity index 100% rename from sway/commands/bar/mode.c rename to sway/old/commands/bar/mode.c diff --git a/sway/commands/bar/modifier.c b/sway/old/commands/bar/modifier.c similarity index 100% rename from sway/commands/bar/modifier.c rename to sway/old/commands/bar/modifier.c diff --git a/sway/commands/bar/output.c b/sway/old/commands/bar/output.c similarity index 100% rename from sway/commands/bar/output.c rename to sway/old/commands/bar/output.c diff --git a/sway/commands/bar/pango_markup.c b/sway/old/commands/bar/pango_markup.c similarity index 100% rename from sway/commands/bar/pango_markup.c rename to sway/old/commands/bar/pango_markup.c diff --git a/sway/commands/bar/position.c b/sway/old/commands/bar/position.c similarity index 100% rename from sway/commands/bar/position.c rename to sway/old/commands/bar/position.c diff --git a/sway/commands/bar/secondary_button.c b/sway/old/commands/bar/secondary_button.c similarity index 100% rename from sway/commands/bar/secondary_button.c rename to sway/old/commands/bar/secondary_button.c diff --git a/sway/commands/bar/separator_symbol.c b/sway/old/commands/bar/separator_symbol.c similarity index 100% rename from sway/commands/bar/separator_symbol.c rename to sway/old/commands/bar/separator_symbol.c diff --git a/sway/commands/bar/status_command.c b/sway/old/commands/bar/status_command.c similarity index 100% rename from sway/commands/bar/status_command.c rename to sway/old/commands/bar/status_command.c diff --git a/sway/commands/bar/strip_workspace_numbers.c b/sway/old/commands/bar/strip_workspace_numbers.c similarity index 100% rename from sway/commands/bar/strip_workspace_numbers.c rename to sway/old/commands/bar/strip_workspace_numbers.c diff --git a/sway/commands/bar/swaybar_command.c b/sway/old/commands/bar/swaybar_command.c similarity index 100% rename from sway/commands/bar/swaybar_command.c rename to sway/old/commands/bar/swaybar_command.c diff --git a/sway/commands/bar/tray_output.c b/sway/old/commands/bar/tray_output.c similarity index 100% rename from sway/commands/bar/tray_output.c rename to sway/old/commands/bar/tray_output.c diff --git a/sway/commands/bar/tray_padding.c b/sway/old/commands/bar/tray_padding.c similarity index 100% rename from sway/commands/bar/tray_padding.c rename to sway/old/commands/bar/tray_padding.c diff --git a/sway/commands/bar/workspace_buttons.c b/sway/old/commands/bar/workspace_buttons.c similarity index 100% rename from sway/commands/bar/workspace_buttons.c rename to sway/old/commands/bar/workspace_buttons.c diff --git a/sway/commands/bar/wrap_scroll.c b/sway/old/commands/bar/wrap_scroll.c similarity index 100% rename from sway/commands/bar/wrap_scroll.c rename to sway/old/commands/bar/wrap_scroll.c diff --git a/sway/commands/bind.c b/sway/old/commands/bind.c similarity index 100% rename from sway/commands/bind.c rename to sway/old/commands/bind.c diff --git a/sway/commands/border.c b/sway/old/commands/border.c similarity index 100% rename from sway/commands/border.c rename to sway/old/commands/border.c diff --git a/sway/commands/client.c b/sway/old/commands/client.c similarity index 100% rename from sway/commands/client.c rename to sway/old/commands/client.c diff --git a/sway/commands/clipboard.c b/sway/old/commands/clipboard.c similarity index 100% rename from sway/commands/clipboard.c rename to sway/old/commands/clipboard.c diff --git a/sway/commands/commands.c b/sway/old/commands/commands.c similarity index 100% rename from sway/commands/commands.c rename to sway/old/commands/commands.c diff --git a/sway/commands/debuglog.c b/sway/old/commands/debuglog.c similarity index 100% rename from sway/commands/debuglog.c rename to sway/old/commands/debuglog.c diff --git a/sway/commands/default_border.c b/sway/old/commands/default_border.c similarity index 100% rename from sway/commands/default_border.c rename to sway/old/commands/default_border.c diff --git a/sway/commands/default_floating_border.c b/sway/old/commands/default_floating_border.c similarity index 100% rename from sway/commands/default_floating_border.c rename to sway/old/commands/default_floating_border.c diff --git a/sway/commands/exec.c b/sway/old/commands/exec.c similarity index 100% rename from sway/commands/exec.c rename to sway/old/commands/exec.c diff --git a/sway/commands/exec_always.c b/sway/old/commands/exec_always.c similarity index 100% rename from sway/commands/exec_always.c rename to sway/old/commands/exec_always.c diff --git a/sway/commands/exit.c b/sway/old/commands/exit.c similarity index 100% rename from sway/commands/exit.c rename to sway/old/commands/exit.c diff --git a/sway/commands/floating.c b/sway/old/commands/floating.c similarity index 100% rename from sway/commands/floating.c rename to sway/old/commands/floating.c diff --git a/sway/commands/floating_maximum_size.c b/sway/old/commands/floating_maximum_size.c similarity index 100% rename from sway/commands/floating_maximum_size.c rename to sway/old/commands/floating_maximum_size.c diff --git a/sway/commands/floating_minimum_size.c b/sway/old/commands/floating_minimum_size.c similarity index 100% rename from sway/commands/floating_minimum_size.c rename to sway/old/commands/floating_minimum_size.c diff --git a/sway/commands/floating_mod.c b/sway/old/commands/floating_mod.c similarity index 100% rename from sway/commands/floating_mod.c rename to sway/old/commands/floating_mod.c diff --git a/sway/commands/floating_scroll.c b/sway/old/commands/floating_scroll.c similarity index 100% rename from sway/commands/floating_scroll.c rename to sway/old/commands/floating_scroll.c diff --git a/sway/commands/focus.c b/sway/old/commands/focus.c similarity index 100% rename from sway/commands/focus.c rename to sway/old/commands/focus.c diff --git a/sway/commands/focus_follows_mouse.c b/sway/old/commands/focus_follows_mouse.c similarity index 100% rename from sway/commands/focus_follows_mouse.c rename to sway/old/commands/focus_follows_mouse.c diff --git a/sway/commands/font.c b/sway/old/commands/font.c similarity index 100% rename from sway/commands/font.c rename to sway/old/commands/font.c diff --git a/sway/commands/for_window.c b/sway/old/commands/for_window.c similarity index 100% rename from sway/commands/for_window.c rename to sway/old/commands/for_window.c diff --git a/sway/commands/force_focus_wrapping.c b/sway/old/commands/force_focus_wrapping.c similarity index 100% rename from sway/commands/force_focus_wrapping.c rename to sway/old/commands/force_focus_wrapping.c diff --git a/sway/commands/fullscreen.c b/sway/old/commands/fullscreen.c similarity index 100% rename from sway/commands/fullscreen.c rename to sway/old/commands/fullscreen.c diff --git a/sway/commands/gaps.c b/sway/old/commands/gaps.c similarity index 100% rename from sway/commands/gaps.c rename to sway/old/commands/gaps.c diff --git a/sway/commands/hide_edge_borders.c b/sway/old/commands/hide_edge_borders.c similarity index 100% rename from sway/commands/hide_edge_borders.c rename to sway/old/commands/hide_edge_borders.c diff --git a/sway/commands/include.c b/sway/old/commands/include.c similarity index 100% rename from sway/commands/include.c rename to sway/old/commands/include.c diff --git a/sway/commands/input.c b/sway/old/commands/input.c similarity index 100% rename from sway/commands/input.c rename to sway/old/commands/input.c diff --git a/sway/commands/input/accel_profile.c b/sway/old/commands/input/accel_profile.c similarity index 100% rename from sway/commands/input/accel_profile.c rename to sway/old/commands/input/accel_profile.c diff --git a/sway/commands/input/click_method.c b/sway/old/commands/input/click_method.c similarity index 100% rename from sway/commands/input/click_method.c rename to sway/old/commands/input/click_method.c diff --git a/sway/commands/input/drag_lock.c b/sway/old/commands/input/drag_lock.c similarity index 100% rename from sway/commands/input/drag_lock.c rename to sway/old/commands/input/drag_lock.c diff --git a/sway/commands/input/dwt.c b/sway/old/commands/input/dwt.c similarity index 100% rename from sway/commands/input/dwt.c rename to sway/old/commands/input/dwt.c diff --git a/sway/commands/input/events.c b/sway/old/commands/input/events.c similarity index 100% rename from sway/commands/input/events.c rename to sway/old/commands/input/events.c diff --git a/sway/commands/input/left_handed.c b/sway/old/commands/input/left_handed.c similarity index 100% rename from sway/commands/input/left_handed.c rename to sway/old/commands/input/left_handed.c diff --git a/sway/commands/input/middle_emulation.c b/sway/old/commands/input/middle_emulation.c similarity index 100% rename from sway/commands/input/middle_emulation.c rename to sway/old/commands/input/middle_emulation.c diff --git a/sway/commands/input/natural_scroll.c b/sway/old/commands/input/natural_scroll.c similarity index 100% rename from sway/commands/input/natural_scroll.c rename to sway/old/commands/input/natural_scroll.c diff --git a/sway/commands/input/pointer_accel.c b/sway/old/commands/input/pointer_accel.c similarity index 100% rename from sway/commands/input/pointer_accel.c rename to sway/old/commands/input/pointer_accel.c diff --git a/sway/commands/input/scroll_method.c b/sway/old/commands/input/scroll_method.c similarity index 100% rename from sway/commands/input/scroll_method.c rename to sway/old/commands/input/scroll_method.c diff --git a/sway/commands/input/tap.c b/sway/old/commands/input/tap.c similarity index 100% rename from sway/commands/input/tap.c rename to sway/old/commands/input/tap.c diff --git a/sway/commands/ipc.c b/sway/old/commands/ipc.c similarity index 100% rename from sway/commands/ipc.c rename to sway/old/commands/ipc.c diff --git a/sway/commands/kill.c b/sway/old/commands/kill.c similarity index 100% rename from sway/commands/kill.c rename to sway/old/commands/kill.c diff --git a/sway/commands/layout.c b/sway/old/commands/layout.c similarity index 100% rename from sway/commands/layout.c rename to sway/old/commands/layout.c diff --git a/sway/commands/log_colors.c b/sway/old/commands/log_colors.c similarity index 100% rename from sway/commands/log_colors.c rename to sway/old/commands/log_colors.c diff --git a/sway/commands/mark.c b/sway/old/commands/mark.c similarity index 100% rename from sway/commands/mark.c rename to sway/old/commands/mark.c diff --git a/sway/commands/mode.c b/sway/old/commands/mode.c similarity index 100% rename from sway/commands/mode.c rename to sway/old/commands/mode.c diff --git a/sway/commands/mouse_warping.c b/sway/old/commands/mouse_warping.c similarity index 100% rename from sway/commands/mouse_warping.c rename to sway/old/commands/mouse_warping.c diff --git a/sway/commands/move.c b/sway/old/commands/move.c similarity index 100% rename from sway/commands/move.c rename to sway/old/commands/move.c diff --git a/sway/commands/new_float.c b/sway/old/commands/new_float.c similarity index 100% rename from sway/commands/new_float.c rename to sway/old/commands/new_float.c diff --git a/sway/commands/new_window.c b/sway/old/commands/new_window.c similarity index 100% rename from sway/commands/new_window.c rename to sway/old/commands/new_window.c diff --git a/sway/commands/no_focus.c b/sway/old/commands/no_focus.c similarity index 100% rename from sway/commands/no_focus.c rename to sway/old/commands/no_focus.c diff --git a/sway/commands/orientation.c b/sway/old/commands/orientation.c similarity index 100% rename from sway/commands/orientation.c rename to sway/old/commands/orientation.c diff --git a/sway/commands/output.c b/sway/old/commands/output.c similarity index 100% rename from sway/commands/output.c rename to sway/old/commands/output.c diff --git a/sway/commands/permit.c b/sway/old/commands/permit.c similarity index 100% rename from sway/commands/permit.c rename to sway/old/commands/permit.c diff --git a/sway/commands/reload.c b/sway/old/commands/reload.c similarity index 100% rename from sway/commands/reload.c rename to sway/old/commands/reload.c diff --git a/sway/commands/resize.c b/sway/old/commands/resize.c similarity index 100% rename from sway/commands/resize.c rename to sway/old/commands/resize.c diff --git a/sway/commands/scratchpad.c b/sway/old/commands/scratchpad.c similarity index 100% rename from sway/commands/scratchpad.c rename to sway/old/commands/scratchpad.c diff --git a/sway/commands/seamless_mouse.c b/sway/old/commands/seamless_mouse.c similarity index 100% rename from sway/commands/seamless_mouse.c rename to sway/old/commands/seamless_mouse.c diff --git a/sway/commands/set.c b/sway/old/commands/set.c similarity index 100% rename from sway/commands/set.c rename to sway/old/commands/set.c diff --git a/sway/commands/show_marks.c b/sway/old/commands/show_marks.c similarity index 100% rename from sway/commands/show_marks.c rename to sway/old/commands/show_marks.c diff --git a/sway/commands/smart_gaps.c b/sway/old/commands/smart_gaps.c similarity index 100% rename from sway/commands/smart_gaps.c rename to sway/old/commands/smart_gaps.c diff --git a/sway/commands/split.c b/sway/old/commands/split.c similarity index 100% rename from sway/commands/split.c rename to sway/old/commands/split.c diff --git a/sway/commands/sticky.c b/sway/old/commands/sticky.c similarity index 100% rename from sway/commands/sticky.c rename to sway/old/commands/sticky.c diff --git a/sway/commands/unmark.c b/sway/old/commands/unmark.c similarity index 100% rename from sway/commands/unmark.c rename to sway/old/commands/unmark.c diff --git a/sway/commands/workspace.c b/sway/old/commands/workspace.c similarity index 100% rename from sway/commands/workspace.c rename to sway/old/commands/workspace.c diff --git a/sway/commands/workspace_auto_back_and_forth.c b/sway/old/commands/workspace_auto_back_and_forth.c similarity index 100% rename from sway/commands/workspace_auto_back_and_forth.c rename to sway/old/commands/workspace_auto_back_and_forth.c diff --git a/sway/commands/workspace_layout.c b/sway/old/commands/workspace_layout.c similarity index 100% rename from sway/commands/workspace_layout.c rename to sway/old/commands/workspace_layout.c diff --git a/sway/config.c b/sway/old/config.c similarity index 88% rename from sway/config.c rename to sway/old/config.c index aa40c49a5..d14653e30 100644 --- a/sway/config.c +++ b/sway/old/config.c @@ -998,6 +998,7 @@ static void invoke_swaybar(struct bar_config *bar) { } static void terminate_swaybar(pid_t pid) { + return; // TODO WLR int ret = kill(pid, SIGTERM); if (ret != 0) { sway_log(L_ERROR, "Unable to terminate swaybar [pid: %d]", pid); @@ -1066,143 +1067,6 @@ void load_swaybars() { list_free(bars); } -void apply_input_config(struct input_config *ic, struct libinput_device *dev) { - if (!ic) { - return; - } - - sway_log(L_DEBUG, "apply_input_config(%s)", ic->identifier); - - if (ic->accel_profile != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) accel_set_profile(%d)", ic->identifier, ic->accel_profile); - libinput_device_config_accel_set_profile(dev, ic->accel_profile); - } - if (ic->click_method != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) click_set_method(%d)", ic->identifier, ic->click_method); - libinput_device_config_click_set_method(dev, ic->click_method); - } - if (ic->drag_lock != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) tap_set_drag_lock_enabled(%d)", ic->identifier, ic->click_method); - libinput_device_config_tap_set_drag_lock_enabled(dev, ic->drag_lock); - } - if (ic->dwt != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) dwt_set_enabled(%d)", ic->identifier, ic->dwt); - libinput_device_config_dwt_set_enabled(dev, ic->dwt); - } - if (ic->left_handed != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) left_handed_set_enabled(%d)", ic->identifier, ic->left_handed); - libinput_device_config_left_handed_set(dev, ic->left_handed); - } - if (ic->middle_emulation != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) middle_emulation_set_enabled(%d)", ic->identifier, ic->middle_emulation); - libinput_device_config_middle_emulation_set_enabled(dev, ic->middle_emulation); - } - if (ic->natural_scroll != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) natural_scroll_set_enabled(%d)", ic->identifier, ic->natural_scroll); - libinput_device_config_scroll_set_natural_scroll_enabled(dev, ic->natural_scroll); - } - if (ic->pointer_accel != FLT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) accel_set_speed(%f)", ic->identifier, ic->pointer_accel); - libinput_device_config_accel_set_speed(dev, ic->pointer_accel); - } - if (ic->scroll_method != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) scroll_set_method(%d)", ic->identifier, ic->scroll_method); - libinput_device_config_scroll_set_method(dev, ic->scroll_method); - } - if (ic->send_events != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) send_events_set_mode(%d)", ic->identifier, ic->send_events); - libinput_device_config_send_events_set_mode(dev, ic->send_events); - } - if (ic->tap != INT_MIN) { - sway_log(L_DEBUG, "apply_input_config(%s) tap_set_enabled(%d)", ic->identifier, ic->tap); - libinput_device_config_tap_set_enabled(dev, ic->tap); - } -} - -void apply_output_config(struct output_config *oc, swayc_t *output) { - if (oc && oc->enabled == 0) { - destroy_output(output); - return; - } - - if (oc && oc->width > 0 && oc->height > 0) { - output->width = oc->width; - output->height = oc->height; - - sway_log(L_DEBUG, "Set %s size to %ix%i (%d)", oc->name, oc->width, oc->height, oc->scale); - // TODO WLR: modes - //struct wlc_size new_size = { .w = oc->width, .h = oc->height }; - //wlc_output_set_resolution(output->handle, &new_size, (uint32_t)oc->scale); - } else if (oc) { - //const struct wlc_size *new_size = wlc_output_get_resolution(output->handle); - //wlc_output_set_resolution(output->handle, new_size, (uint32_t)oc->scale); - } - - // TODO WLR: wlr_output_layout - // 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; - } - } - - /* TODO WLR - if (oc && oc->background) { - 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); - } - } - */ -} - char *do_var_replacement(char *str) { int i; char *find = str; diff --git a/sway/tree/container.c b/sway/old/container.c similarity index 100% rename from sway/tree/container.c rename to sway/old/container.c diff --git a/sway/tree/criteria.c b/sway/old/criteria.c similarity index 100% rename from sway/tree/criteria.c rename to sway/old/criteria.c diff --git a/sway/tree/focus.c b/sway/old/focus.c similarity index 100% rename from sway/tree/focus.c rename to sway/old/focus.c diff --git a/sway/handlers.c b/sway/old/handlers.c similarity index 100% rename from sway/handlers.c rename to sway/old/handlers.c diff --git a/sway/input_state.c b/sway/old/input_state.c similarity index 100% rename from sway/input_state.c rename to sway/old/input_state.c diff --git a/sway/ipc-json.c b/sway/old/ipc-json.c similarity index 100% rename from sway/ipc-json.c rename to sway/old/ipc-json.c diff --git a/sway/ipc-server.c b/sway/old/ipc-server.c similarity index 99% rename from sway/ipc-server.c rename to sway/old/ipc-server.c index d4db4e7a4..fd64e81b1 100644 --- a/sway/ipc-server.c +++ b/sway/old/ipc-server.c @@ -1,10 +1,8 @@ // See https://i3wm.org/docs/ipc.html for protocol information - #ifndef __FreeBSD__ // Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0) #define _XOPEN_SOURCE 700 #endif - #include #include #include @@ -56,8 +54,6 @@ struct ipc_client { char *write_buffer; }; -static list_t *ipc_get_pixel_requests = NULL; - struct sockaddr_un *ipc_user_sockaddr(void); int ipc_handle_connection(int fd, uint32_t mask, void *data); int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); @@ -97,7 +93,6 @@ void ipc_init(void) { setenv("SWAYSOCK", ipc_sockaddr->sun_path, 1); ipc_client_list = create_list(); - ipc_get_pixel_requests = create_list(); ipc_event_source = wl_event_loop_add_fd(server.wl_event_loop, ipc_socket, WL_EVENT_READABLE, ipc_handle_connection, NULL); diff --git a/sway/tree/layout.c b/sway/old/layout.c similarity index 100% rename from sway/tree/layout.c rename to sway/old/layout.c diff --git a/sway/tree/output.c b/sway/old/output.c similarity index 100% rename from sway/tree/output.c rename to sway/old/output.c diff --git a/sway/security.c b/sway/old/security.c similarity index 100% rename from sway/security.c rename to sway/old/security.c diff --git a/sway/tree/workspace.c b/sway/old/workspace.c similarity index 100% rename from sway/tree/workspace.c rename to sway/old/workspace.c diff --git a/sway/server.c b/sway/server.c index 940f28b31..8892b917a 100644 --- a/sway/server.c +++ b/sway/server.c @@ -10,7 +10,6 @@ // TODO WLR: make Xwayland optional #include #include "sway/server.h" -#include "sway/input.h" #include "log.h" bool server_init(struct sway_server *server) { @@ -23,7 +22,6 @@ bool server_init(struct sway_server *server) { server->renderer = wlr_gles2_renderer_create(server->backend); wl_display_init_shm(server->wl_display); - server->input = sway_input_create(server); server->data_device_manager = wlr_data_device_manager_create(server->wl_display); From db4fb1c85c132e001fb1ae18f03f7585def1ae19 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 19 Nov 2017 17:04:28 -0500 Subject: [PATCH 011/522] Add outputs to the tree --- include/sway/container.h | 130 +++++++++++++++++++++++++++++++++++++++ include/sway/layout.h | 9 +++ include/sway/output.h | 2 + sway/CMakeLists.txt | 3 + sway/desktop/output.c | 4 +- sway/main.c | 5 +- sway/tree/container.c | 45 ++++++++++++++ sway/tree/layout.c | 35 +++++++++++ 8 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 include/sway/container.h create mode 100644 include/sway/layout.h create mode 100644 sway/tree/container.c create mode 100644 sway/tree/layout.c diff --git a/include/sway/container.h b/include/sway/container.h new file mode 100644 index 000000000..35d1c146e --- /dev/null +++ b/include/sway/container.h @@ -0,0 +1,130 @@ +#ifndef _SWAY_CONTAINER_H +#define _SWAY_CONTAINER_H +#include +#include +#include +#include "list.h" + +typedef struct sway_container swayc_t; + +extern swayc_t root_container; + +struct sway_view; + +/** + * 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_output; +struct sway_view; +struct wlr_output_layout; + +/** + * 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 wlr_output_layout *output_layout; // 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; + /** + * Which of this container's children has focus. + */ + struct sway_container *focused; + + /** + * 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; +}; + +swayc_t *new_output(struct sway_output *sway_output); + +#endif diff --git a/include/sway/layout.h b/include/sway/layout.h new file mode 100644 index 000000000..7e7a9c354 --- /dev/null +++ b/include/sway/layout.h @@ -0,0 +1,9 @@ +#ifndef _SWAY_LAYOUT_H +#define _SWAY_LAYOUT_H + +struct sway_container; + +void init_layout(void); +void add_child(struct sway_container *parent, struct sway_container *child); + +#endif diff --git a/include/sway/output.h b/include/sway/output.h index ffc6708dc..e2f81bcbc 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -5,9 +5,11 @@ #include struct sway_server; +struct sway_container; struct sway_output { struct wlr_output *wlr_output; + struct sway_container *swayc; struct sway_server *server; struct timespec last_frame; struct wl_listener frame; diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 73531a847..9a92466cd 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -14,6 +14,9 @@ add_executable(sway desktop/output.c desktop/xdg_shell_v6.c + tree/layout.c + tree/container.c + base64.c main.c server.c diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6ddcac3ba..27579c1b6 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -5,6 +5,7 @@ #include #include #include "log.h" +#include "sway/container.h" #include "sway/output.h" #include "sway/server.h" @@ -34,11 +35,10 @@ void output_add_notify(struct wl_listener *listener, void *data) { struct sway_output *output = calloc(1, sizeof(struct sway_output)); output->wlr_output = wlr_output; output->server = server; + output->swayc = new_output(output); output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); - - // TODO: Add to tree } void output_remove_notify(struct wl_listener *listener, void *data) { diff --git a/sway/main.c b/sway/main.c index 5710a099a..42262b055 100644 --- a/sway/main.c +++ b/sway/main.c @@ -16,10 +16,11 @@ #include #endif #include "sway/server.h" +#include "sway/layout.h" #include "ipc-client.h" +#include "log.h" #include "readline.h" #include "stringop.h" -#include "log.h" #include "util.h" static bool terminate_request = false; @@ -436,7 +437,7 @@ int main(int argc, char **argv) { return 1; } - //init_layout(); + init_layout(); //ipc_init(); //if (validate) { diff --git a/sway/tree/container.c b/sway/tree/container.c new file mode 100644 index 000000000..54bcf4780 --- /dev/null +++ b/sway/tree/container.c @@ -0,0 +1,45 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include "sway/container.h" +#include "sway/layout.h" +#include "sway/output.h" + +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; + swayc_t *c = calloc(1, sizeof(swayc_t)); + if (!c) { + return NULL; + } + c->id = next_id++; + 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(); + } + return c; +} + +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; + + 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; + + add_child(&root_container, output); + + // TODO: Create workspace + + return output; +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c new file mode 100644 index 000000000..06200bbf1 --- /dev/null +++ b/sway/tree/layout.c @@ -0,0 +1,35 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include "sway/container.h" +#include "list.h" +#include "log.h" + +swayc_t root_container; + +void init_layout(void) { + root_container.id = 0; // normally assigned in new_swayc() + root_container.type = C_ROOT; + root_container.layout = L_NONE; + root_container.name = strdup("root"); + root_container.children = create_list(); + root_container.output_layout = wlr_output_layout_create(); +} + +void add_child(swayc_t *parent, swayc_t *child) { + sway_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); + list_add(parent->children, child); + child->parent = parent; + // set focus for this container + if (!parent->focused) { + parent->focused = child; + } + /* TODO WLR + 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); + } + */ +} From c301b14a42c007bf3b69fef6053fa2466e201309 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 19 Nov 2017 17:05:09 -0500 Subject: [PATCH 012/522] Remove wlc dependency --- CMakeLists.txt | 1 - README.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b53670b6c..9580e15df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,6 @@ endif() find_package(JsonC 0.12.1 REQUIRED) find_package(PCRE REQUIRED) -find_package(WLC REQUIRED) find_package(Wlroots REQUIRED) find_package(Wayland REQUIRED) find_package(XKBCommon REQUIRED) diff --git a/README.md b/README.md index 29e8a674f..215cee4f6 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ channel or shoot an email to sir@cmpwn.com for advice. Install dependencies: * cmake -* [wlc](https://github.com/Cloudef/wlc) +* [wlroots](https://github.com/swaywm/wlroots) * wayland * xwayland * libinput >= 1.6.0 From b8f8de27b865248462955cddaad223acb76d05c1 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Wed, 22 Nov 2017 23:56:21 +0100 Subject: [PATCH 013/522] wlr_data_device header update wlroots 6a7560 renamed the header file --- include/sway/server.h | 2 +- sway/server.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index 5a8a8d318..60f35190d 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include // TODO WLR: make Xwayland optional diff --git a/sway/server.c b/sway/server.c index 8892b917a..f78bcef13 100644 --- a/sway/server.c +++ b/sway/server.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include // TODO WLR: make Xwayland optional From 6c1cd82e3244ba3cb5a248618580d19d0f5cfd3d Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Thu, 23 Nov 2017 00:15:31 +0100 Subject: [PATCH 014/522] xdg_shell_v6: add _POSIX_C_SOURCE define for struct timespec wlroots 1e0e73 added struct timespec to wlr_seat.h, so we need to define a _POSIX_C_SOURCE large enough whenever we include wlr_seat.h --- sway/desktop/xdg_shell_v6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 04f3f42c2..b3dbcfbeb 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 199309L #include #include #include From 977c1f6a30b9ef21be363ec9fca1d9044b2905c6 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Thu, 23 Nov 2017 00:23:37 +0100 Subject: [PATCH 015/522] common/util: replace WLC_BIT_MOD_* by WLR_MODIFIER_* This removes the last wlc/wlc.h include actually in use --- common/util.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/common/util.c b/common/util.c index d63698535..839811608 100644 --- a/common/util.c +++ b/common/util.c @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include #include "log.h" #include "readline.h" #include "util.h" @@ -29,16 +29,16 @@ static struct modifier_key { char *name; uint32_t mod; } modifiers[] = { - { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, - { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, - { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, - { "Ctrl", WLC_BIT_MOD_CTRL }, - { XKB_MOD_NAME_ALT, WLC_BIT_MOD_ALT }, - { "Alt", WLC_BIT_MOD_ALT }, - { XKB_MOD_NAME_NUM, WLC_BIT_MOD_MOD2 }, - { "Mod3", WLC_BIT_MOD_MOD3 }, - { XKB_MOD_NAME_LOGO, WLC_BIT_MOD_LOGO }, - { "Mod5", WLC_BIT_MOD_MOD5 }, + { XKB_MOD_NAME_SHIFT, WLR_MODIFIER_SHIFT }, + { XKB_MOD_NAME_CAPS, WLR_MODIFIER_CAPS }, + { XKB_MOD_NAME_CTRL, WLR_MODIFIER_CTRL }, + { "Ctrl", WLR_MODIFIER_CTRL }, + { XKB_MOD_NAME_ALT, WLR_MODIFIER_ALT }, + { "Alt", WLR_MODIFIER_ALT }, + { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 }, + { "Mod3", WLR_MODIFIER_MOD3 }, + { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO }, + { "Mod5", WLR_MODIFIER_MOD5 }, }; uint32_t get_modifier_mask_by_name(const char *name) { From aeda2e077f6184ecd26dc078c7b5db7f0dc54fd7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 22 Nov 2017 20:39:27 -0500 Subject: [PATCH 016/522] Add workspace to outputs --- include/sway/container.h | 1 + include/sway/layout.h | 2 ++ include/sway/workspace.h | 6 ++++++ sway/CMakeLists.txt | 3 ++- sway/tree/container.c | 34 ++++++++++++++++++++++++++++++---- sway/tree/layout.c | 37 +++++++++++++++++++++++++++++++++++++ sway/tree/workspace.c | 26 ++++++++++++++++++++++++++ 7 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 include/sway/workspace.h create mode 100644 sway/tree/workspace.c diff --git a/include/sway/container.h b/include/sway/container.h index 35d1c146e..2a96165f3 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -126,5 +126,6 @@ struct sway_container { }; swayc_t *new_output(struct sway_output *sway_output); +swayc_t *new_workspace(swayc_t *output, const char *name); #endif diff --git a/include/sway/layout.h b/include/sway/layout.h index 7e7a9c354..6356ad00a 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h @@ -5,5 +5,7 @@ struct sway_container; void init_layout(void); void add_child(struct sway_container *parent, struct sway_container *child); +enum swayc_layouts default_layout(struct sway_container *output); +void sort_workspaces(struct sway_container *output); #endif diff --git a/include/sway/workspace.h b/include/sway/workspace.h new file mode 100644 index 000000000..04b2ea4ef --- /dev/null +++ b/include/sway/workspace.h @@ -0,0 +1,6 @@ +#ifndef _SWAY_WORKSPACE_H +#define _SWAY_WORKSPACE_H + +char *workspace_next_name(const char *output_name); + +#endif diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 9a92466cd..6d520e76e 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -14,8 +14,9 @@ add_executable(sway desktop/output.c desktop/xdg_shell_v6.c - tree/layout.c tree/container.c + tree/layout.c + tree/workspace.c base64.c main.c diff --git a/sway/tree/container.c b/sway/tree/container.c index 54bcf4780..ac79356a5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -5,6 +5,8 @@ #include "sway/container.h" #include "sway/layout.h" #include "sway/output.h" +#include "sway/workspace.h" +#include "log.h" static swayc_t *new_swayc(enum swayc_types type) { // next id starts at 1 because 0 is assigned to root_container in layout.c @@ -27,8 +29,8 @@ 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; swayc_t *output = new_swayc(C_OUTPUT); @@ -39,7 +41,31 @@ swayc_t *new_output(struct sway_output *sway_output) { add_child(&root_container, output); - // TODO: Create workspace - + // Create workspace + char *ws_name = workspace_next_name(output->name); + sway_log(L_DEBUG, "Creating default workspace %s", ws_name); + new_workspace(output, ws_name); + free(ws_name); return output; } + +swayc_t *new_workspace(swayc_t *output, const char *name) { + if (!sway_assert(output, "new_workspace called with null output")) { + return NULL; + } + sway_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); + swayc_t *workspace = new_swayc(C_WORKSPACE); + + workspace->x = output->x; + workspace->y = output->y; + workspace->width = output->width; + 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); + + add_child(output, workspace); + sort_workspaces(output); + return workspace; +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 06200bbf1..5a70c570f 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -1,5 +1,7 @@ #define _POSIX_C_SOURCE 200809L +#include #include +#include #include #include #include "sway/container.h" @@ -33,3 +35,38 @@ void add_child(swayc_t *parent, swayc_t *child) { } */ } + +enum swayc_layouts default_layout(swayc_t *output) { + /* TODO WLR + if (config->default_layout != L_NONE) { + //return config->default_layout; + } else if (config->default_orientation != L_NONE) { + return config->default_orientation; + } else */if (output->width >= output->height) { + return L_HORIZ; + } else { + return L_VERT; + } +} + +static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { + swayc_t *a = *(void **)_a; + swayc_t *b = *(void **)_b; + int retval = 0; + + if (isdigit(a->name[0]) && isdigit(b->name[0])) { + int a_num = strtol(a->name, NULL, 10); + int b_num = strtol(b->name, NULL, 10); + retval = (a_num < b_num) ? -1 : (a_num > b_num); + } else if (isdigit(a->name[0])) { + retval = -1; + } else if (isdigit(b->name[0])) { + retval = 1; + } + + return retval; +} + +void sort_workspaces(swayc_t *output) { + list_stable_sort(output->children, sort_workspace_cmp_qsort); +} diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c new file mode 100644 index 000000000..e8ed4102c --- /dev/null +++ b/sway/tree/workspace.c @@ -0,0 +1,26 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include "sway/container.h" +#include "log.h" + +void next_name_map(swayc_t *ws, void *data) { + int *count = data; + ++count; +} + +char *workspace_next_name(const char *output_name) { + sway_log(L_DEBUG, "Workspace: Generating new workspace name for output %s", + output_name); + int count = 0; + next_name_map(&root_container, &count); + ++count; + int len = snprintf(NULL, 0, "%d", count); + char *name = malloc(len + 1); + if (!sway_assert(name, "Failed to allocate workspace name")) { + return NULL; + } + snprintf(name, len + 1, "%d", count); + return name; +} From 4ca1e77fdbbf559a5bb28d4936afa6ade63985cd Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 22 Nov 2017 21:06:08 -0500 Subject: [PATCH 017/522] Add views to tree and render them --- include/sway/container.h | 4 ++ include/sway/server.h | 2 + include/sway/view.h | 2 + sway/desktop/output.c | 74 +++++++++++++++++++++++++++++++++++++ sway/desktop/xdg_shell_v6.c | 11 ++++++ sway/server.c | 4 ++ sway/tree/container.c | 39 +++++++++++++++++++ 7 files changed, 136 insertions(+) diff --git a/include/sway/container.h b/include/sway/container.h index 2a96165f3..96e4db69a 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -125,7 +125,11 @@ struct sway_container { list_t *marks; }; +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); #endif diff --git a/include/sway/server.h b/include/sway/server.h index 60f35190d..b0684d15d 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ struct sway_server { struct wlr_backend *backend; struct wlr_renderer *renderer; + struct wlr_compositor *compositor; struct wlr_data_device_manager *data_device_manager; struct sway_input *input; diff --git a/include/sway/view.h b/include/sway/view.h index 979b20a8e..2675a6f58 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -1,6 +1,7 @@ #ifndef _SWAY_VIEW_H #define _SWAY_VIEW_H #include +#include #include struct sway_container; @@ -38,6 +39,7 @@ struct sway_view { struct wl_listener destroy; enum sway_view_type type; struct sway_container *swayc; + struct wlr_surface *surface; union { struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 27579c1b6..9e0c18e4a 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -3,11 +3,82 @@ #include #include #include +#include #include +#include #include "log.h" #include "sway/container.h" #include "sway/output.h" #include "sway/server.h" +#include "sway/view.h" + +static inline int64_t timespec_to_msec(const struct timespec *a) { + return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; +} + +static void output_frame_view(swayc_t *view, void *data) { + struct sway_output *output = data; + struct wlr_output *wlr_output = output->wlr_output; + struct sway_view *sway_view = view->sway_view; + struct wlr_surface *surface = sway_view->surface; + if (!wlr_surface_has_buffer(surface)) { + return; + } + // TODO + // - Force sway's resolution + // - Deal with wlr_output_layout + int width = surface->current->width; + int height = surface->current->height; + int render_width = width * wlr_output->scale; + int render_height = height * wlr_output->scale; + double ox = view->x, oy = view->y; + // TODO + //wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); + ox *= wlr_output->scale; + oy *= wlr_output->scale; + // TODO + //if (wlr_output_layout_intersects(desktop->layout, wlr_output, + // lx, ly, lx + render_width, ly + render_height)) { + // return; + //} + + // TODO + double rotation = 0; + float matrix[16]; + + float translate_origin[16]; + wlr_matrix_translate(&translate_origin, + (int)ox + render_width / 2, (int)oy + render_height / 2, 0); + + float rotate[16]; + wlr_matrix_rotate(&rotate, rotation); + + float translate_center[16]; + wlr_matrix_translate(&translate_center, -render_width / 2, + -render_height / 2, 0); + + float scale[16]; + wlr_matrix_scale(&scale, render_width, render_height, 1); + + float transform[16]; + wlr_matrix_mul(&translate_origin, &rotate, &transform); + wlr_matrix_mul(&transform, &translate_center, &transform); + wlr_matrix_mul(&transform, &scale, &transform); + wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix); + + wlr_render_with_matrix(output->server->renderer, surface->texture, &matrix); + + // TODO: move into wlroots + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + struct wlr_frame_callback *cb, *cnext; + wl_list_for_each_safe(cb, cnext, + &surface->current->frame_callback_list, link) { + wl_callback_send_done(cb->resource, timespec_to_msec(&now)); + wl_resource_destroy(cb->resource); + } +} static void output_frame_notify(struct wl_listener *listener, void *data) { struct sway_output *soutput = wl_container_of( @@ -21,6 +92,9 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { wlr_output_make_current(wlr_output); wlr_renderer_begin(server->renderer, wlr_output); + swayc_descendants_of_type( + &root_container, C_VIEW, output_frame_view, soutput); + wlr_renderer_end(server->renderer); wlr_output_swap_buffers(wlr_output); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index b3dbcfbeb..e2a61ebf5 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -2,6 +2,7 @@ #include #include #include +#include "sway/container.h" #include "sway/server.h" #include "sway/view.h" #include "log.h" @@ -47,6 +48,9 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { } sway_view->type = SWAY_XDG_SHELL_V6_VIEW; sway_view->iface.get_prop = get_prop; + sway_view->wlr_xdg_surface_v6 = xdg_surface; + sway_view->sway_xdg_surface_v6 = sway_surface; + sway_view->surface = xdg_surface->surface; sway_surface->view = sway_view; // TODO: @@ -56,4 +60,11 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria + + // TODO: actual focus semantics + swayc_t *parent = root_container.children->items[0]; + parent = parent->children->items[0]; // workspace + + swayc_t *cont = new_view(parent, sway_view); + sway_view->swayc = cont; } diff --git a/sway/server.c b/sway/server.c index f78bcef13..6e66bc3ca 100644 --- a/sway/server.c +++ b/sway/server.c @@ -6,6 +6,7 @@ #include #include #include +#include // TODO WLR: make Xwayland optional #include #include "sway/server.h" @@ -21,6 +22,9 @@ bool server_init(struct sway_server *server) { server->renderer = wlr_gles2_renderer_create(server->backend); wl_display_init_shm(server->wl_display); + server->compositor = wlr_compositor_create( + server->wl_display, server->renderer); + server->data_device_manager = wlr_data_device_manager_create(server->wl_display); diff --git a/sway/tree/container.c b/sway/tree/container.c index ac79356a5..d39316121 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -5,9 +5,23 @@ #include "sway/container.h" #include "sway/layout.h" #include "sway/output.h" +#include "sway/view.h" #include "sway/workspace.h" #include "log.h" +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; @@ -69,3 +83,28 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { sort_workspaces(output); 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")) { + return NULL; + } + const char *title = sway_view->iface.get_prop(sway_view, VIEW_PROP_TITLE); + swayc_t *swayc = new_swayc(C_VIEW); + sway_log(L_DEBUG, "Adding new view %p:%s to container %p %d", + swayc, title, sibling, sibling ? sibling->type : 0); + // Setup values + swayc->sway_view = sway_view; + swayc->name = title ? strdup(title) : NULL; + swayc->width = 0; + swayc->height = 0; + + if (sibling->type == C_WORKSPACE) { + // Case of focused workspace, just create as child of it + add_child(sibling, swayc); + } else { + // Regular case, create as sibling of current container + // TODO WLR + //add_sibling(sibling, swayc); + } + return swayc; +} From d7d21bb0f895248cafefc3d12e4aed033a8e5d17 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 22 Nov 2017 21:20:41 -0500 Subject: [PATCH 018/522] Add initial command subsystem (untested) Need to spin up the IPC server to test this --- include/sway/commands.h | 185 ++++++++++++++++++++++++++++++ sway/CMakeLists.txt | 3 + sway/commands.c | 247 ++++++++++++++++++++++++++++++++++++++++ sway/commands/exit.c | 19 ++++ 4 files changed, 454 insertions(+) create mode 100644 include/sway/commands.h create mode 100644 sway/commands.c create mode 100644 sway/commands/exit.c diff --git a/include/sway/commands.h b/include/sway/commands.h new file mode 100644 index 000000000..df5c68596 --- /dev/null +++ b/include/sway/commands.h @@ -0,0 +1,185 @@ +#ifndef _SWAY_COMMANDS_H +#define _SWAY_COMMANDS_H + +/** + * Indicates the result of a command's execution. + */ +enum cmd_status { + CMD_SUCCESS, /**< The command was successful */ + CMD_FAILURE, /**< The command resulted in an error */ + CMD_INVALID, /**< Unknown command or parser error */ + CMD_DEFER, /**< Command execution deferred */ + // Config Blocks + CMD_BLOCK_END, + CMD_BLOCK_MODE, + CMD_BLOCK_BAR, + CMD_BLOCK_BAR_COLORS, + CMD_BLOCK_INPUT, + CMD_BLOCK_COMMANDS, + CMD_BLOCK_IPC, + CMD_BLOCK_IPC_EVENTS, +}; + +/** + * Stores the result of executing a command. + */ +struct cmd_results { + enum cmd_status status; + char *input; + /** + * Human friendly error message, or NULL on success + */ + char *error; +}; + +enum expected_args { + EXPECTED_MORE_THAN, + EXPECTED_AT_LEAST, + EXPECTED_LESS_THAN, + EXPECTED_EQUAL_TO +}; + +struct cmd_results *checkarg(int argc, const char *name, + enum expected_args type, int val); + +/** + * Parse and handles a command. + */ +struct cmd_results *handle_command(char *command); +/** + * Allocates a cmd_results object. + */ +struct cmd_results *cmd_results_new(enum cmd_status status, const char* input, const char *error, ...); +/** + * Frees a cmd_results object. + */ +void free_cmd_results(struct cmd_results *results); +/** + * Serializes cmd_results to a JSON string. + * + * Free the JSON string later on. + */ +const char *cmd_results_to_json(struct cmd_results *results); + +typedef struct cmd_results *sway_cmd(int argc, char **argv); + +sway_cmd cmd_assign; +sway_cmd cmd_bar; +sway_cmd cmd_bindcode; +sway_cmd cmd_bindsym; +sway_cmd cmd_border; +sway_cmd cmd_client_focused; +sway_cmd cmd_client_focused_inactive; +sway_cmd cmd_client_unfocused; +sway_cmd cmd_client_urgent; +sway_cmd cmd_client_placeholder; +sway_cmd cmd_client_background; +sway_cmd cmd_clipboard; +sway_cmd cmd_commands; +sway_cmd cmd_debuglog; +sway_cmd cmd_default_border; +sway_cmd cmd_default_floating_border; +sway_cmd cmd_exec; +sway_cmd cmd_exec_always; +sway_cmd cmd_exit; +sway_cmd cmd_floating; +sway_cmd cmd_floating_maximum_size; +sway_cmd cmd_floating_minimum_size; +sway_cmd cmd_floating_mod; +sway_cmd cmd_floating_scroll; +sway_cmd cmd_focus; +sway_cmd cmd_focus_follows_mouse; +sway_cmd cmd_font; +sway_cmd cmd_for_window; +sway_cmd cmd_force_focus_wrapping; +sway_cmd cmd_fullscreen; +sway_cmd cmd_gaps; +sway_cmd cmd_hide_edge_borders; +sway_cmd cmd_include; +sway_cmd cmd_input; +sway_cmd cmd_ipc; +sway_cmd cmd_kill; +sway_cmd cmd_layout; +sway_cmd cmd_log_colors; +sway_cmd cmd_mark; +sway_cmd cmd_mode; +sway_cmd cmd_mouse_warping; +sway_cmd cmd_move; +sway_cmd cmd_new_float; +sway_cmd cmd_new_window; +sway_cmd cmd_no_focus; +sway_cmd cmd_orientation; +sway_cmd cmd_output; +sway_cmd cmd_permit; +sway_cmd cmd_reject; +sway_cmd cmd_reload; +sway_cmd cmd_resize; +sway_cmd cmd_scratchpad; +sway_cmd cmd_seamless_mouse; +sway_cmd cmd_set; +sway_cmd cmd_show_marks; +sway_cmd cmd_smart_gaps; +sway_cmd cmd_split; +sway_cmd cmd_splith; +sway_cmd cmd_splitt; +sway_cmd cmd_splitv; +sway_cmd cmd_sticky; +sway_cmd cmd_unmark; +sway_cmd cmd_workspace; +sway_cmd cmd_ws_auto_back_and_forth; +sway_cmd cmd_workspace_layout; + +sway_cmd bar_cmd_activate_button; +sway_cmd bar_cmd_binding_mode_indicator; +sway_cmd bar_cmd_bindsym; +sway_cmd bar_cmd_colors; +sway_cmd bar_cmd_context_button; +sway_cmd bar_cmd_font; +sway_cmd bar_cmd_mode; +sway_cmd bar_cmd_modifier; +sway_cmd bar_cmd_output; +sway_cmd bar_cmd_height; +sway_cmd bar_cmd_hidden_state; +sway_cmd bar_cmd_icon_theme; +sway_cmd bar_cmd_id; +sway_cmd bar_cmd_position; +sway_cmd bar_cmd_secondary_button; +sway_cmd bar_cmd_separator_symbol; +sway_cmd bar_cmd_status_command; +sway_cmd bar_cmd_pango_markup; +sway_cmd bar_cmd_strip_workspace_numbers; +sway_cmd bar_cmd_swaybar_command; +sway_cmd bar_cmd_tray_output; +sway_cmd bar_cmd_tray_padding; +sway_cmd bar_cmd_wrap_scroll; +sway_cmd bar_cmd_workspace_buttons; + +sway_cmd bar_colors_cmd_active_workspace; +sway_cmd bar_colors_cmd_background; +sway_cmd bar_colors_cmd_focused_background; +sway_cmd bar_colors_cmd_binding_mode; +sway_cmd bar_colors_cmd_focused_workspace; +sway_cmd bar_colors_cmd_inactive_workspace; +sway_cmd bar_colors_cmd_separator; +sway_cmd bar_colors_cmd_focused_separator; +sway_cmd bar_colors_cmd_statusline; +sway_cmd bar_colors_cmd_focused_statusline; +sway_cmd bar_colors_cmd_urgent_workspace; + +sway_cmd input_cmd_accel_profile; +sway_cmd input_cmd_click_method; +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_middle_emulation; +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 cmd_ipc_cmd; +sway_cmd cmd_ipc_events; +sway_cmd cmd_ipc_event_cmd; + +#endif diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 6d520e76e..b85d619ff 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -14,6 +14,9 @@ add_executable(sway desktop/output.c desktop/xdg_shell_v6.c + commands.c + commands/exit.c + tree/container.c tree/layout.c tree/workspace.c diff --git a/sway/commands.c b/sway/commands.c new file mode 100644 index 000000000..f8c2fd996 --- /dev/null +++ b/sway/commands.c @@ -0,0 +1,247 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include "sway/commands.h" +#include "stringop.h" +#include "log.h" + +struct cmd_handler { + char *command; + sway_cmd *handle; +}; + +// Returns error object, or NULL if check succeeds. +struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val) { + struct cmd_results *error = NULL; + switch (type) { + case EXPECTED_MORE_THAN: + if (argc > val) { + return NULL; + } + error = cmd_results_new(CMD_INVALID, name, "Invalid %s command " + "(expected more than %d argument%s, got %d)", + name, val, (char*[2]){"s", ""}[argc==1], argc); + break; + case EXPECTED_AT_LEAST: + if (argc >= val) { + return NULL; + } + error = cmd_results_new(CMD_INVALID, name, "Invalid %s command " + "(expected at least %d argument%s, got %d)", + name, val, (char*[2]){"s", ""}[argc==1], argc); + break; + case EXPECTED_LESS_THAN: + if (argc < val) { + return NULL; + }; + error = cmd_results_new(CMD_INVALID, name, "Invalid %s command " + "(expected less than %d argument%s, got %d)", + name, val, (char*[2]){"s", ""}[argc==1], argc); + break; + case EXPECTED_EQUAL_TO: + if (argc == val) { + return NULL; + }; + error = cmd_results_new(CMD_INVALID, name, "Invalid %s command " + "(expected %d arguments, got %d)", name, val, argc); + break; + } + return error; +} + +/** + * Check and add color to buffer. + * + * return error object, or NULL if color is valid. + */ +struct cmd_results *add_color(const char *name, char *buffer, const char *color) { + int len = strlen(color); + if (len != 7 && len != 9) { + return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); + } + + if (color[0] != '#') { + return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); + } + + int i; + for (i = 1; i < len; ++i) { + if (!isxdigit(color[i])) { + return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); + } + } + + // copy color to buffer + strncpy(buffer, color, len); + // add default alpha channel if color was defined without it + if (len == 7) { + buffer[7] = 'f'; + buffer[8] = 'f'; + } + buffer[9] = '\0'; + + return NULL; +} + +/* Keep alphabetized */ +static struct cmd_handler handlers[] = { + { "exit", cmd_exit }, +}; + +static int handler_compare(const void *_a, const void *_b) { + const struct cmd_handler *a = _a; + const struct cmd_handler *b = _b; + return strcasecmp(a->command, b->command); +} + +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); + /* TODO + if (block == CMD_BLOCK_BAR) { + res = bsearch(&d, bar_handlers, + sizeof(bar_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + } else if (block == CMD_BLOCK_BAR_COLORS){ + res = bsearch(&d, bar_colors_handlers, + sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + } else 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_IPC) { + res = bsearch(&d, ipc_handlers, + sizeof(ipc_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + } else if (block == CMD_BLOCK_IPC_EVENTS) { + res = bsearch(&d, ipc_event_handlers, + sizeof(ipc_event_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + } else { + */ + res = bsearch(&d, handlers, + sizeof(handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + //} + return res; +} + +struct cmd_results *handle_command(char *_exec) { + // Even though this function will process multiple commands we will only + // return the last error, if any (for now). (Since we have access to an + // error string we could e.g. concatonate all errors there.) + struct cmd_results *results = NULL; + char *exec = strdup(_exec); + char *head = exec; + char *cmdlist; + char *cmd; + + head = exec; + do { + // Split command list + cmdlist = argsep(&head, ";"); + cmdlist += strspn(cmdlist, whitespace); + do { + // Split commands + cmd = argsep(&cmdlist, ","); + cmd += strspn(cmd, whitespace); + if (strcmp(cmd, "") == 0) { + sway_log(L_INFO, "Ignoring empty command."); + continue; + } + sway_log(L_INFO, "Handling command '%s'", cmd); + //TODO better handling of argv + int argc; + char **argv = split_args(cmd, &argc); + if (strcmp(argv[0], "exec") != 0) { + int i; + for (i = 1; i < argc; ++i) { + if (*argv[i] == '\"' || *argv[i] == '\'') { + strip_quotes(argv[i]); + } + } + } + struct cmd_handler *handler = find_handler(argv[0], CMD_BLOCK_END); + if (!handler) { + if (results) { + free_cmd_results(results); + } + results = cmd_results_new(CMD_INVALID, cmd, "Unknown/invalid command"); + free_argv(argc, argv); + goto cleanup; + } + free_argv(argc, argv); + } while(cmdlist); + } while(head); +cleanup: + free(exec); + if (!results) { + results = cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + 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)); + if (!results) { + sway_log(L_ERROR, "Unable to allocate command results"); + return NULL; + } + results->status = status; + if (input) { + results->input = strdup(input); // input is the command name + } else { + results->input = NULL; + } + if (format) { + char *error = malloc(256); + va_list args; + va_start(args, format); + if (error) { + vsnprintf(error, 256, format, args); + } + va_end(args); + results->error = error; + } else { + results->error = NULL; + } + return results; +} + +void free_cmd_results(struct cmd_results *results) { + if (results->input) { + free(results->input); + } + if (results->error) { + free(results->error); + } + free(results); +} + +const char *cmd_results_to_json(struct cmd_results *results) { + json_object *result_array = json_object_new_array(); + json_object *root = json_object_new_object(); + json_object_object_add(root, "success", + json_object_new_boolean(results->status == CMD_SUCCESS)); + if (results->input) { + json_object_object_add( + root, "input", json_object_new_string(results->input)); + } + if (results->error) { + json_object_object_add( + root, "error", json_object_new_string(results->error)); + } + json_object_array_add(result_array, root); + const char *json = json_object_to_json_string(result_array); + free(result_array); + free(root); + return json; +} diff --git a/sway/commands/exit.c b/sway/commands/exit.c new file mode 100644 index 000000000..d294e344a --- /dev/null +++ b/sway/commands/exit.c @@ -0,0 +1,19 @@ +#include +#include "sway/commands.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); +} + From 7753a0ec750f17e1f014cda0dd2564ae0533cdd4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 22 Nov 2017 21:37:07 -0500 Subject: [PATCH 019/522] Wire up IPC server --- include/sway/ipc-json.h | 7 + include/sway/ipc-server.h | 12 ++ sway/CMakeLists.txt | 2 + sway/ipc-json.c | 18 ++ sway/ipc-server.c | 411 ++++++++++++++++++++++++++++++++++++++ sway/main.c | 5 +- 6 files changed, 453 insertions(+), 2 deletions(-) create mode 100644 include/sway/ipc-json.h create mode 100644 include/sway/ipc-server.h create mode 100644 sway/ipc-json.c create mode 100644 sway/ipc-server.c diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h new file mode 100644 index 000000000..5bfddcba9 --- /dev/null +++ b/include/sway/ipc-json.h @@ -0,0 +1,7 @@ +#ifndef _SWAY_IPC_JSON_H +#define _SWAY_IPC_JSON_H +#include + +json_object *ipc_json_get_version(); + +#endif diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h new file mode 100644 index 000000000..b85ff535d --- /dev/null +++ b/include/sway/ipc-server.h @@ -0,0 +1,12 @@ +#ifndef _SWAY_IPC_SERVER_H +#define _SWAY_IPC_SERVER_H +#include +#include "ipc.h" + +struct sway_server; + +void ipc_init(struct sway_server *server); +void ipc_terminate(void); +struct sockaddr_un *ipc_user_sockaddr(void); + +#endif diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index b85d619ff..274fcc4ad 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -24,6 +24,8 @@ add_executable(sway base64.c main.c server.c + ipc-json.c + ipc-server.c ) add_definitions( diff --git a/sway/ipc-json.c b/sway/ipc-json.c new file mode 100644 index 000000000..6fcb91fa4 --- /dev/null +++ b/sway/ipc-json.c @@ -0,0 +1,18 @@ +#include +#include +#include "sway/ipc-json.h" + +json_object *ipc_json_get_version() { + int major = 0, minor = 0, patch = 0; + json_object *version = json_object_new_object(); + + sscanf(SWAY_VERSION, "%u.%u.%u", &major, &minor, &patch); + + json_object_object_add(version, "human_readable", json_object_new_string(SWAY_VERSION)); + json_object_object_add(version, "variant", json_object_new_string("sway")); + json_object_object_add(version, "major", json_object_new_int(major)); + json_object_object_add(version, "minor", json_object_new_int(minor)); + json_object_object_add(version, "patch", json_object_new_int(patch)); + + return version; +} diff --git a/sway/ipc-server.c b/sway/ipc-server.c new file mode 100644 index 000000000..f3a6469ba --- /dev/null +++ b/sway/ipc-server.c @@ -0,0 +1,411 @@ +// See https://i3wm.org/docs/ipc.html for protocol information +#ifndef __FreeBSD__ +// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0) +#define _XOPEN_SOURCE 700 +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sway/commands.h" +#include "sway/ipc-json.h" +#include "sway/ipc-server.h" +#include "sway/server.h" +#include "list.h" +#include "log.h" + +static int ipc_socket = -1; +static struct wl_event_source *ipc_event_source = NULL; +static struct sockaddr_un *ipc_sockaddr = NULL; +static list_t *ipc_client_list = NULL; + +static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; + +struct ipc_client { + struct wl_event_source *event_source; + struct wl_event_source *writable_event_source; + struct sway_server *server; + int fd; + uint32_t payload_length; + uint32_t security_policy; + enum ipc_command_type current_command; + enum ipc_command_type subscribed_events; + size_t write_buffer_len; + size_t write_buffer_size; + char *write_buffer; +}; + +struct sockaddr_un *ipc_user_sockaddr(void); +int ipc_handle_connection(int fd, uint32_t mask, void *data); +int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); +int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data); +void ipc_client_disconnect(struct ipc_client *client); +void ipc_client_handle_command(struct ipc_client *client); +bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); + +void ipc_init(struct sway_server *server) { + ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); + if (ipc_socket == -1) { + sway_abort("Unable to create IPC socket"); + } + + ipc_sockaddr = ipc_user_sockaddr(); + + // We want to use socket name set by user, not existing socket from another sway instance. + if (getenv("SWAYSOCK") != NULL && access(getenv("SWAYSOCK"), F_OK) == -1) { + strncpy(ipc_sockaddr->sun_path, getenv("SWAYSOCK"), sizeof(ipc_sockaddr->sun_path)); + ipc_sockaddr->sun_path[sizeof(ipc_sockaddr->sun_path) - 1] = 0; + } + + unlink(ipc_sockaddr->sun_path); + if (bind(ipc_socket, (struct sockaddr *)ipc_sockaddr, sizeof(*ipc_sockaddr)) == -1) { + sway_abort("Unable to bind IPC socket"); + } + + if (listen(ipc_socket, 3) == -1) { + sway_abort("Unable to listen on IPC socket"); + } + + // Set i3 IPC socket path so that i3-msg works out of the box + setenv("I3SOCK", ipc_sockaddr->sun_path, 1); + setenv("SWAYSOCK", ipc_sockaddr->sun_path, 1); + + ipc_client_list = create_list(); + + ipc_event_source = wl_event_loop_add_fd(server->wl_event_loop, ipc_socket, + WL_EVENT_READABLE, ipc_handle_connection, server); +} + +void ipc_terminate(void) { + if (ipc_event_source) { + wl_event_source_remove(ipc_event_source); + } + close(ipc_socket); + unlink(ipc_sockaddr->sun_path); + + list_free(ipc_client_list); + + if (ipc_sockaddr) { + free(ipc_sockaddr); + } +} + +struct sockaddr_un *ipc_user_sockaddr(void) { + struct sockaddr_un *ipc_sockaddr = malloc(sizeof(struct sockaddr_un)); + if (ipc_sockaddr == NULL) { + sway_abort("Can't allocate ipc_sockaddr"); + } + + ipc_sockaddr->sun_family = AF_UNIX; + int path_size = sizeof(ipc_sockaddr->sun_path); + + // Env var typically set by logind, e.g. "/run/user/" + const char *dir = getenv("XDG_RUNTIME_DIR"); + if (!dir) { + dir = "/tmp"; + } + if (path_size <= snprintf(ipc_sockaddr->sun_path, path_size, + "%s/sway-ipc.%i.%i.sock", dir, getuid(), getpid())) { + sway_abort("Socket path won't fit into ipc_sockaddr->sun_path"); + } + + return ipc_sockaddr; +} + +int ipc_handle_connection(int fd, uint32_t mask, void *data) { + (void) fd; + struct sway_server *server = data; + sway_log(L_DEBUG, "Event on IPC listening socket"); + assert(mask == WL_EVENT_READABLE); + + int client_fd = accept(ipc_socket, NULL, NULL); + if (client_fd == -1) { + sway_log_errno(L_ERROR, "Unable to accept IPC client connection"); + return 0; + } + + int flags; + if ((flags = fcntl(client_fd, F_GETFD)) == -1 + || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { + sway_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); + close(client_fd); + return 0; + } + if ((flags = fcntl(client_fd, F_GETFL)) == -1 + || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { + sway_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); + close(client_fd); + return 0; + } + + struct ipc_client *client = malloc(sizeof(struct ipc_client)); + if (!client) { + sway_log(L_ERROR, "Unable to allocate ipc client"); + close(client_fd); + return 0; + } + client->server = server; + client->payload_length = 0; + client->fd = client_fd; + client->subscribed_events = 0; + client->event_source = wl_event_loop_add_fd(server->wl_event_loop, + client_fd, WL_EVENT_READABLE, ipc_client_handle_readable, client); + client->writable_event_source = NULL; + + client->write_buffer_size = 128; + client->write_buffer_len = 0; + client->write_buffer = malloc(client->write_buffer_size); + if (!client->write_buffer) { + sway_log(L_ERROR, "Unable to allocate ipc client write buffer"); + close(client_fd); + return 0; + } + + sway_log(L_DEBUG, "New client: fd %d", client_fd); + list_add(ipc_client_list, client); + return 0; +} + +static const int ipc_header_size = sizeof(ipc_magic) + 8; + +int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { + struct ipc_client *client = data; + + if (mask & WL_EVENT_ERROR) { + sway_log(L_ERROR, "IPC Client socket error, removing client"); + ipc_client_disconnect(client); + return 0; + } + + if (mask & WL_EVENT_HANGUP) { + sway_log(L_DEBUG, "Client %d hung up", client->fd); + ipc_client_disconnect(client); + return 0; + } + + sway_log(L_DEBUG, "Client %d readable", client->fd); + + int read_available; + if (ioctl(client_fd, FIONREAD, &read_available) == -1) { + sway_log_errno(L_INFO, "Unable to read IPC socket buffer size"); + ipc_client_disconnect(client); + return 0; + } + + // Wait for the rest of the command payload in case the header has already been read + if (client->payload_length > 0) { + if ((uint32_t)read_available >= client->payload_length) { + ipc_client_handle_command(client); + } + return 0; + } + + if (read_available < ipc_header_size) { + return 0; + } + + uint8_t buf[ipc_header_size]; + uint32_t *buf32 = (uint32_t*)(buf + sizeof(ipc_magic)); + // Should be fully available, because read_available >= ipc_header_size + ssize_t received = recv(client_fd, buf, ipc_header_size, 0); + if (received == -1) { + sway_log_errno(L_INFO, "Unable to receive header from IPC client"); + ipc_client_disconnect(client); + return 0; + } + + if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { + sway_log(L_DEBUG, "IPC header check failed"); + ipc_client_disconnect(client); + return 0; + } + + client->payload_length = buf32[0]; + client->current_command = (enum ipc_command_type)buf32[1]; + + if (read_available - received >= (long)client->payload_length) { + ipc_client_handle_command(client); + } + + return 0; +} + +int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { + struct ipc_client *client = data; + + if (mask & WL_EVENT_ERROR) { + sway_log(L_ERROR, "IPC Client socket error, removing client"); + ipc_client_disconnect(client); + return 0; + } + + if (mask & WL_EVENT_HANGUP) { + sway_log(L_DEBUG, "Client %d hung up", client->fd); + ipc_client_disconnect(client); + return 0; + } + + if (client->write_buffer_len <= 0) { + return 0; + } + + sway_log(L_DEBUG, "Client %d writable", client->fd); + + ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); + + if (written == -1 && errno == EAGAIN) { + return 0; + } else if (written == -1) { + sway_log_errno(L_INFO, "Unable to send data from queue to IPC client"); + ipc_client_disconnect(client); + return 0; + } + + memmove(client->write_buffer, client->write_buffer + written, client->write_buffer_len - written); + client->write_buffer_len -= written; + + if (client->write_buffer_len == 0 && client->writable_event_source) { + wl_event_source_remove(client->writable_event_source); + client->writable_event_source = NULL; + } + + return 0; +} + +void ipc_client_disconnect(struct ipc_client *client) { + if (!sway_assert(client != NULL, "client != NULL")) { + return; + } + + if (client->fd != -1) { + shutdown(client->fd, SHUT_RDWR); + } + + sway_log(L_INFO, "IPC Client %d disconnected", client->fd); + wl_event_source_remove(client->event_source); + if (client->writable_event_source) { + wl_event_source_remove(client->writable_event_source); + } + int i = 0; + while (i < ipc_client_list->length && ipc_client_list->items[i] != client) { + i++; + } + list_del(ipc_client_list, i); + free(client->write_buffer); + close(client->fd); + free(client); +} + +void ipc_client_handle_command(struct ipc_client *client) { + if (!sway_assert(client != NULL, "client != NULL")) { + return; + } + + char *buf = malloc(client->payload_length + 1); + if (!buf) { + sway_log_errno(L_INFO, "Unable to allocate IPC payload"); + ipc_client_disconnect(client); + return; + } + if (client->payload_length > 0) { + // Payload should be fully available + ssize_t received = recv(client->fd, buf, client->payload_length, 0); + if (received == -1) + { + sway_log_errno(L_INFO, "Unable to receive payload from IPC client"); + ipc_client_disconnect(client); + free(buf); + return; + } + } + buf[client->payload_length] = '\0'; + + const char *error_denied = "{ \"success\": false, \"error\": \"Permission denied\" }"; + + switch (client->current_command) { + case IPC_COMMAND: + { + struct cmd_results *results = handle_command(buf); + const char *json = cmd_results_to_json(results); + char reply[256]; + int length = snprintf(reply, sizeof(reply), "%s", json); + ipc_send_reply(client, reply, (uint32_t) length); + free_cmd_results(results); + goto exit_cleanup; + } + + case IPC_GET_VERSION: + { + json_object *version = ipc_json_get_version(); + const char *json_string = json_object_to_json_string(version); + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(version); // free + goto exit_cleanup; + } + + default: + sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); + goto exit_cleanup; + } + + ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); + sway_log(L_DEBUG, "Denied IPC client access to %i", client->current_command); + +exit_cleanup: + client->payload_length = 0; + free(buf); + return; +} + +bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { + assert(payload); + + char data[ipc_header_size]; + uint32_t *data32 = (uint32_t*)(data + sizeof(ipc_magic)); + + memcpy(data, ipc_magic, sizeof(ipc_magic)); + data32[0] = payload_length; + data32[1] = client->current_command; + + while (client->write_buffer_len + ipc_header_size + payload_length >= + client->write_buffer_size) { + client->write_buffer_size *= 2; + } + + if (client->write_buffer_size > 4e6) { // 4 MB + sway_log(L_ERROR, "Client write buffer too big, disconnecting client"); + ipc_client_disconnect(client); + return false; + } + + char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); + if (!new_buffer) { + sway_log(L_ERROR, "Unable to reallocate ipc client write buffer"); + ipc_client_disconnect(client); + return false; + } + client->write_buffer = new_buffer; + + memcpy(client->write_buffer + client->write_buffer_len, data, ipc_header_size); + client->write_buffer_len += ipc_header_size; + memcpy(client->write_buffer + client->write_buffer_len, payload, payload_length); + client->write_buffer_len += payload_length; + + if (!client->writable_event_source) { + client->writable_event_source = wl_event_loop_add_fd( + server.wl_event_loop, client->fd, WL_EVENT_WRITABLE, + ipc_client_handle_writable, client); + } + + sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); + return true; +} diff --git a/sway/main.c b/sway/main.c index 42262b055..5d5f9a57c 100644 --- a/sway/main.c +++ b/sway/main.c @@ -17,6 +17,7 @@ #endif #include "sway/server.h" #include "sway/layout.h" +#include "sway/ipc-server.h" #include "ipc-client.h" #include "log.h" #include "readline.h" @@ -438,7 +439,7 @@ int main(int argc, char **argv) { } init_layout(); - //ipc_init(); + ipc_init(&server); //if (validate) { // bool valid = load_main_config(config_path, false); @@ -461,7 +462,7 @@ int main(int argc, char **argv) { server_fini(&server); - //ipc_terminate(); + ipc_terminate(); //if (config) { // free_config(config); From b379b400718c05ce6cd43550b78704a2938a47c0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 22 Nov 2017 21:39:35 -0500 Subject: [PATCH 020/522] Invoke command handlers once parsed --- sway/commands.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sway/commands.c b/sway/commands.c index f8c2fd996..94a45253c 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -177,6 +177,16 @@ 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); + } + results = res; + goto cleanup; + } + free_cmd_results(res); free_argv(argc, argv); } while(cmdlist); } while(head); From 289ba64bdea0ed3d42fb195b64e19e0cac799c97 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 22 Nov 2017 21:47:22 -0500 Subject: [PATCH 021/522] Remove IPC_GET_PIXELS --- include/ipc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/ipc.h b/include/ipc.h index 2b16dc50d..9665a88d6 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -23,7 +23,6 @@ enum ipc_command_type { IPC_EVENT_BINDING = ((1<<31) | 5), IPC_EVENT_MODIFIER = ((1<<31) | 6), IPC_EVENT_INPUT = ((1<<31) | 7), - IPC_SWAY_GET_PIXELS = 0x81 }; #endif From ce1936bc65d01502e3a5f8681bb039cb95e82e0c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 25 Nov 2017 10:59:49 -0500 Subject: [PATCH 022/522] Arrange windows on desktop --- include/sway/container.h | 2 + include/sway/layout.h | 1 + include/sway/output.h | 1 + include/sway/view.h | 2 + sway/desktop/output.c | 15 ++- sway/desktop/xdg_shell_v6.c | 20 +++- sway/tree/container.c | 13 +++ sway/tree/layout.c | 205 ++++++++++++++++++++++++++++++++++++ 8 files changed, 253 insertions(+), 6 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index 96e4db69a..1a173f3ee 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -132,4 +132,6 @@ 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 *swayc_parent_by_type(swayc_t *container, enum swayc_types type); + #endif diff --git a/include/sway/layout.h b/include/sway/layout.h index 6356ad00a..505036a0b 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h @@ -7,5 +7,6 @@ void init_layout(void); void add_child(struct sway_container *parent, 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); #endif diff --git a/include/sway/output.h b/include/sway/output.h index e2f81bcbc..895cb07d4 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -13,6 +13,7 @@ struct sway_output { struct sway_server *server; struct timespec last_frame; struct wl_listener frame; + struct wl_listener resolution; }; #endif diff --git a/include/sway/view.h b/include/sway/view.h index 2675a6f58..9d5036741 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -52,6 +52,8 @@ struct sway_view { struct { const char *(*get_prop)(struct sway_view *view, enum sway_view_prop prop); + void (*set_dimensions)(struct sway_view *view, + int width, int height); } iface; }; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9e0c18e4a..033a4c446 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -8,6 +8,7 @@ #include #include "log.h" #include "sway/container.h" +#include "sway/layout.h" #include "sway/output.h" #include "sway/server.h" #include "sway/view.h" @@ -25,10 +26,9 @@ static void output_frame_view(swayc_t *view, void *data) { return; } // TODO - // - Force sway's resolution // - Deal with wlr_output_layout - int width = surface->current->width; - int height = surface->current->height; + int width = sway_view->swayc->width; + int height = sway_view->swayc->height; int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; double ox = view->x, oy = view->y; @@ -101,6 +101,12 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { soutput->last_frame = now; } +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); +} + void output_add_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_add); struct wlr_output *wlr_output = data; @@ -113,6 +119,9 @@ void output_add_notify(struct wl_listener *listener, void *data) { output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); + + output->resolution.notify = output_resolution_notify; + wl_signal_add(&wlr_output->events.resolution, &output->resolution); } void output_remove_notify(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index e2a61ebf5..8f1885c15 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -1,15 +1,21 @@ #define _POSIX_C_SOURCE 199309L +#include #include #include #include #include "sway/container.h" +#include "sway/layout.h" #include "sway/server.h" #include "sway/view.h" #include "log.h" +static bool assert_xdg(struct sway_view *view) { + return sway_assert(view->type == SWAY_XDG_SHELL_V6_VIEW, + "Expected xdg shell v6 view!"); +} + static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { - if (!sway_assert(view->type == SWAY_XDG_SHELL_V6_VIEW, - "xdg get_prop for non-xdg view!")) { + if (!assert_xdg(view)) { return NULL; } switch (prop) { @@ -22,6 +28,12 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } } +static void set_dimensions(struct sway_view *view, int width, int height) { + if (assert_xdg(view)) { + wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); + } +} + void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of( listener, server, xdg_shell_v6_surface); @@ -48,13 +60,13 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { } sway_view->type = SWAY_XDG_SHELL_V6_VIEW; sway_view->iface.get_prop = get_prop; + sway_view->iface.set_dimensions = set_dimensions; sway_view->wlr_xdg_surface_v6 = xdg_surface; sway_view->sway_xdg_surface_v6 = sway_surface; sway_view->surface = xdg_surface->surface; sway_surface->view = sway_view; // TODO: - // - Add to tree // - Wire up listeners // - Handle popups // - Look up pid and open on appropriate workspace @@ -67,4 +79,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { swayc_t *cont = new_view(parent, sway_view); sway_view->swayc = cont; + + arrange_windows(cont->parent, -1, -1); } diff --git a/sway/tree/container.c b/sway/tree/container.c index d39316121..a83c0f6ba 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -108,3 +108,16 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { } return swayc; } + +swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { + if (!sway_assert(container, "container is NULL")) { + return NULL; + } + if (!sway_assert(type < C_TYPES && type >= C_ROOT, "invalid type")) { + return NULL; + } + do { + container = container->parent; + } while (container && container->type != type); + return container; +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 5a70c570f..3d6b404de 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -1,10 +1,14 @@ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include +#include #include #include "sway/container.h" +#include "sway/output.h" +#include "sway/view.h" #include "list.h" #include "log.h" @@ -70,3 +74,204 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { void sort_workspaces(swayc_t *output) { list_stable_sort(output->children, sort_workspace_cmp_qsort); } + +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(swayc_t *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) { + int i; + if (width == -1 || height == -1) { + width = container->width; + height = container->height; + } + // pixels are indivisible. if we don't round the pixels, then the view + // calculations will be off (e.g. 50.5 + 50.5 = 101, but in reality it's + // 50 + 50 = 100). doing it here cascades properly to all width/height/x/y. + width = floor(width); + height = floor(height); + + sway_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, + container->name, container->width, container->height, container->x, + container->y); + + double x = 0, y = 0; + switch (container->type) { + case C_ROOT: + // TODO: wlr_output_layout probably + for (i = 0; i < container->children->length; ++i) { + swayc_t *output = container->children->items[i]; + sway_log(L_DEBUG, "Arranging output '%s' at %f,%f", + output->name, output->x, output->y); + arrange_windows(output, -1, -1); + } + return; + case C_OUTPUT: + { + int _width, _height; + wlr_output_effective_resolution( + container->sway_output->wlr_output, &_width, &_height); + width = container->width = _width; + height = container->height = _height; + } + // arrange all workspaces: + for (i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; + arrange_windows(child, -1, -1); + } + return; + case C_WORKSPACE: + { + swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); + width = output->width, height = output->height; + container->x = x; + container->y = y; + width = container->width; + height = container->height; + sway_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", + container->name, container->x, container->y); + } + // children are properly handled below + break; + case C_VIEW: + { + container->width = width; + container->height = height; + container->sway_view->iface.set_dimensions(container->sway_view, + container->width, container->height); + sway_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", + container->width, container->height, + container->x, container->y); + } + return; + default: + container->width = width; + container->height = height; + x = container->x; + y = container->y; + break; + } + + switch (container->layout) { + case L_HORIZ: + apply_horiz_layout(container, x, y, width, height, 0, + container->children->length); + break; + case L_VERT: + apply_vert_layout(container, x, y, width, height, 0, + container->children->length); + break; + default: + sway_log(L_DEBUG, "TODO: arrange layout type %d", container->layout); + apply_horiz_layout(container, x, y, width, height, 0, + container->children->length); + break; + } +} + +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 = &((swayc_t *)container->children->items[i])->width; + if (*old_width <= 0) { + if (end - start > 1) { + *old_width = width / (end - start - 1); + } else { + *old_width = width; + } + } + scale += *old_width; + } + scale = width / scale; + + // Resize windows + double child_x = x; + if (scale > 0.1) { + sway_log(L_DEBUG, "Arranging %p horizontally", container); + for (int i = start; i < end; ++i) { + swayc_t *child = container->children->items[i]; + sway_log(L_DEBUG, + "Calculating arrangement for %p:%d (will scale %f by %f)", + child, child->type, width, scale); + child->x = child_x; + child->y = y; + + if (i == end - 1) { + double remaining_width = x + width - child_x; + arrange_windows(child, remaining_width, height); + } else { + arrange_windows(child, child->width * scale, height); + } + child_x += child->width; + } + + // update focused view border last because it may + // depend on the title bar geometry of its siblings. + /* TODO WLR + if (focused && container->children->length > 1) { + update_container_border(focused); + } + */ + } +} + +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) { + int i; + double scale = 0; + // Calculate total height + for (i = start; i < end; ++i) { + double *old_height = &((swayc_t *)container->children->items[i])->height; + if (*old_height <= 0) { + if (end - start > 1) { + *old_height = height / (end - start - 1); + } else { + *old_height = height; + } + } + scale += *old_height; + } + scale = height / scale; + + // Resize + double child_y = y; + if (scale > 0.1) { + sway_log(L_DEBUG, "Arranging %p vertically", container); + for (i = start; i < end; ++i) { + swayc_t *child = container->children->items[i]; + sway_log(L_DEBUG, + "Calculating arrangement for %p:%d (will scale %f by %f)", + child, child->type, height, scale); + child->x = x; + child->y = child_y; + + if (i == end - 1) { + double remaining_height = y + height - child_y; + arrange_windows(child, width, remaining_height); + } else { + arrange_windows(child, width, child->height * scale); + } + child_y += child->height; + } + + // update focused view border last because it may + // depend on the title bar geometry of its siblings. + /* TODO WLR + if (focused && container->children->length > 1) { + update_container_border(focused); + } + */ + } +} From a57d46292694e388d74add7b0869bcafdb42b2bd Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 25 Nov 2017 15:49:10 -0500 Subject: [PATCH 023/522] Fix rendering issues, wire up some xdg listeners --- include/sway/view.h | 3 +++ sway/desktop/output.c | 6 ++++-- sway/desktop/xdg_shell_v6.c | 22 ++++++++++++++++++++-- sway/tree/layout.c | 5 ++--- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/include/sway/view.h b/include/sway/view.h index 9d5036741..fca444b71 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -14,6 +14,8 @@ struct sway_xdg_surface_v6 { struct wl_listener request_move; struct wl_listener request_resize; struct wl_listener request_maximize; + + int pending_width, pending_height; }; enum sway_view_type { @@ -40,6 +42,7 @@ 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; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 033a4c446..99c74d89b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -27,8 +27,8 @@ static void output_frame_view(swayc_t *view, void *data) { } // TODO // - Deal with wlr_output_layout - int width = sway_view->swayc->width; - int height = sway_view->swayc->height; + int width = sway_view->width; + int height = sway_view->height; int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; double ox = view->x, oy = view->y; @@ -122,6 +122,8 @@ 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); + + arrange_windows(output->swayc, -1, -1); } void output_remove_notify(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 8f1885c15..94682fcdf 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -29,9 +29,24 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } static void set_dimensions(struct sway_view *view, int width, int height) { - if (assert_xdg(view)) { - wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); + if (!assert_xdg(view)) { + return; } + view->sway_xdg_surface_v6->pending_width = width; + view->sway_xdg_surface_v6->pending_height = height; + wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); +} + +static void handle_commit(struct wl_listener *listener, void *data) { + struct sway_xdg_surface_v6 *sway_surface = + wl_container_of(listener, sway_surface, commit); + struct sway_view *view = sway_surface->view; + sway_log(L_DEBUG, "xdg surface commit %dx%d", + sway_surface->pending_width, sway_surface->pending_height); + // NOTE: We intentionally discard the view's desired width here + // TODO: Don't do that for floating views + view->width = sway_surface->pending_width; + view->height = sway_surface->pending_height; } void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { @@ -72,6 +87,9 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria + + sway_surface->commit.notify = handle_commit; + wl_signal_add(&xdg_surface->events.commit, &sway_surface->commit); // TODO: actual focus semantics swayc_t *parent = root_container.children->items[0]; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 3d6b404de..6e2586a79 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -129,11 +129,10 @@ void arrange_windows(swayc_t *container, double width, double height) { case C_WORKSPACE: { swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); - width = output->width, height = output->height; + container->width = output->width; + container->height = output->height; container->x = x; container->y = y; - width = container->width; - height = container->height; sway_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", container->name, container->x, container->y); } From 8caabe59c2e6f6174678e6c28be3381a7dabff10 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 25 Nov 2017 16:30:15 -0500 Subject: [PATCH 024/522] Handle view destruction properly --- include/sway/container.h | 2 ++ include/sway/layout.h | 1 + include/sway/view.h | 2 +- sway/desktop/xdg_shell_v6.c | 15 ++++++++++++- sway/tree/container.c | 42 +++++++++++++++++++++++++++++++++++++ sway/tree/layout.c | 13 ++++++++++++ 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index 1a173f3ee..08a98ed95 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -132,6 +132,8 @@ 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_view(swayc_t *view); + swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); #endif diff --git a/include/sway/layout.h b/include/sway/layout.h index 505036a0b..f3b62b05e 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h @@ -5,6 +5,7 @@ struct sway_container; void init_layout(void); void add_child(struct sway_container *parent, struct sway_container *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); diff --git a/include/sway/view.h b/include/sway/view.h index fca444b71..2707ca787 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -14,6 +14,7 @@ struct sway_xdg_surface_v6 { struct wl_listener request_move; struct wl_listener request_resize; struct wl_listener request_maximize; + struct wl_listener destroy; int pending_width, pending_height; }; @@ -38,7 +39,6 @@ enum sway_view_prop { * tree (shell surfaces). */ struct sway_view { - struct wl_listener destroy; enum sway_view_type type; struct sway_container *swayc; struct wlr_surface *surface; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 94682fcdf..45e443fcf 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -44,11 +44,22 @@ static void handle_commit(struct wl_listener *listener, void *data) { sway_log(L_DEBUG, "xdg surface commit %dx%d", sway_surface->pending_width, sway_surface->pending_height); // NOTE: We intentionally discard the view's desired width here - // TODO: Don't do that for floating views + // TODO: Let floating views do whatever view->width = sway_surface->pending_width; view->height = sway_surface->pending_height; } +static void handle_destroy(struct wl_listener *listener, void *data) { + struct sway_xdg_surface_v6 *sway_xdg_surface = + 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); + free(sway_xdg_surface->view); + free(sway_xdg_surface); + arrange_windows(parent, -1, -1); +} + void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of( listener, server, xdg_shell_v6_surface); @@ -90,6 +101,8 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_surface->commit.notify = handle_commit; wl_signal_add(&xdg_surface->events.commit, &sway_surface->commit); + sway_surface->destroy.notify = handle_destroy; + wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); // TODO: actual focus semantics swayc_t *parent = root_container.children->items[0]; diff --git a/sway/tree/container.c b/sway/tree/container.c index a83c0f6ba..c7bce38a7 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -109,6 +109,48 @@ 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; + } + 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_view(swayc_t *view) { + if (!sway_assert(view, "null view passed to destroy_view")) { + return NULL; + } + sway_log(L_DEBUG, "Destroying view '%s'", view->name); + swayc_t *parent = view->parent; + free_swayc(view); + + // TODO WLR: Destroy empty containers + /* + if (parent && parent->type == C_CONTAINER) { + return destroy_container(parent); + } + */ + return parent; +} + swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { if (!sway_assert(container, "container is NULL")) { return NULL; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 6e2586a79..ea7bb8bbf 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -40,6 +40,19 @@ void add_child(swayc_t *parent, swayc_t *child) { */ } +swayc_t *remove_child(swayc_t *child) { + int i; + swayc_t *parent = child->parent; + for (i = 0; i < parent->children->length; ++i) { + if (parent->children->items[i] == child) { + list_del(parent->children, i); + break; + } + } + child->parent = NULL; + return parent; +} + enum swayc_layouts default_layout(swayc_t *output) { /* TODO WLR if (config->default_layout != L_NONE) { From 6993a76232d97d533f0851ab05b84c6dd8806e6a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 28 Nov 2017 04:46:22 -0500 Subject: [PATCH 025/522] set mode on output --- sway/desktop/output.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 99c74d89b..169b044b4 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -117,6 +117,12 @@ void output_add_notify(struct wl_listener *listener, void *data) { output->server = server; output->swayc = new_output(output); + if (wl_list_length(&wlr_output->modes) > 0) { + struct wlr_output_mode *mode = NULL; + mode = wl_container_of((&wlr_output->modes)->prev, mode, link); + wlr_output_set_mode(wlr_output, mode); + } + output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); From 9696f50ebad2c414195fc561deea21a36693da5a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 28 Nov 2017 05:40:00 -0500 Subject: [PATCH 026/522] remove nvidia support claim --- sway/main.c | 61 ++++------------------------------------------------- 1 file changed, 4 insertions(+), 57 deletions(-) diff --git a/sway/main.c b/sway/main.c index 5d5f9a57c..c65d175b2 100644 --- a/sway/main.c +++ b/sway/main.c @@ -84,23 +84,16 @@ void detect_proprietary() { if (!f) { return; } - bool nvidia = false, nvidia_modeset = false, nvidia_uvm = false, nvidia_drm = false; while (!feof(f)) { char *line; if (!(line = read_line(f))) { break; } if (strstr(line, "nvidia")) { - nvidia = true; - } - if (strstr(line, "nvidia_modeset")) { - nvidia_modeset = true; - } - if (strstr(line, "nvidia_uvm")) { - nvidia_uvm = true; - } - if (strstr(line, "nvidia_drm")) { - nvidia_drm = true; + fprintf(stderr, "\x1B[1;31mWarning: Proprietary Nvidia drivers are " + "NOT supported. Use Nouveau.\x1B[0m\n"); + free(line); + break; } if (strstr(line, "fglrx")) { fprintf(stderr, "\x1B[1;31mWarning: Proprietary AMD drivers do " @@ -111,52 +104,6 @@ void detect_proprietary() { free(line); } fclose(f); - if (nvidia) { - fprintf(stderr, "\x1B[1;31mWarning: Proprietary nvidia driver support " - "is considered experimental. Nouveau is strongly recommended." - "\x1B[0m\n"); - if (!nvidia_modeset || !nvidia_uvm || !nvidia_drm) { - fprintf(stderr, "\x1B[1;31mWarning: You do not have all of the " - "necessary kernel modules loaded for nvidia support. " - "You need nvidia, nvidia_modeset, nvidia_uvm, and nvidia_drm." - "\x1B[0m\n"); - } -#ifdef __linux__ - f = fopen("/sys/module/nvidia_drm/parameters/modeset", "r"); - if (f) { - char *line = read_line(f); - if (line && strstr(line, "Y")) { - // nvidia-drm.modeset is set to 0 - fprintf(stderr, "\x1B[1;31mWarning: You must load " - "nvidia-drm with the modeset option on to use " - "the proprietary driver. Consider adding " - "nvidia-drm.modeset=1 to your kernel command line " - "parameters.\x1B[0m\n"); - } - fclose(f); - free(line); - } else { - // nvidia-drm.modeset is not set - fprintf(stderr, "\x1B[1;31mWarning: You must load " - "nvidia-drm with the modeset option on to use " - "the proprietary driver. Consider adding " - "nvidia-drm.modeset=1 to your kernel command line " - "parameters.\x1B[0m\n"); - } -#else - f = fopen("/proc/cmdline", "r"); - if (f) { - char *line = read_line(f); - if (line && !strstr(line, "nvidia-drm.modeset=1")) { - fprintf(stderr, "\x1B[1;31mWarning: You must add " - "nvidia-drm.modeset=1 to your kernel command line to use " - "the proprietary driver.\x1B[0m\n"); - } - fclose(f); - free(line); - } -#endif - } } void run_as_ipc_client(char *command, char *socket_path) { From ba6246ada199beafdc9c3585000bf9f59e4e91f8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 29 Nov 2017 09:03:12 -0500 Subject: [PATCH 027/522] working meson build --- meson.build | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 meson.build diff --git a/meson.build b/meson.build new file mode 100644 index 000000000..06eed97fb --- /dev/null +++ b/meson.build @@ -0,0 +1,66 @@ +project( + 'sway', + 'c', + license: 'MIT', + default_options: [ + 'c_std=c11', + 'warning_level=2', + 'werror=true', + ], +) + +cc = meson.get_compiler('c') + +jsonc = dependency('json-c', version: '>=0.12.1') +pcre = dependency('libpcre') +wlroots = dependency('wlroots') +wayland_server = dependency('wayland-server') +wayland_client = dependency('wayland-client') +wayland_egl = dependency('wayland-egl') +wayland_protos = dependency('wayland-protocols') +xkbcommon = dependency('xkbcommon') +pango = dependency('pango') +pixman = dependency('pixman-1') +libcap = dependency('libcap') + +math = cc.find_library('m') + +# TODO version +add_project_arguments('-DSWAY_VERSION="5"', language: 'c') + +sway_inc = include_directories('include') + +sway_sources = [ + 'sway/main.c', + 'sway/server.c', + 'sway/commands.c', + 'sway/commands/exit.c', + 'sway/ipc-json.c', + 'sway/ipc-server.c', + 'sway/desktop/output.c', + 'sway/desktop/xdg_shell_v6.c', + 'sway/tree/container.c', + 'sway/tree/layout.c', + 'sway/tree/workspace.c', + 'common/log.c', + 'common/list.c', + 'common/stringop.c', + 'common/readline.c', + 'common/ipc-client.c', +] + +sway_deps = [ + pixman, + wayland_server, + jsonc, + wlroots, + libcap, + math, +] + +executable( + 'sway', + sway_sources, + include_directories: [sway_inc], + dependencies: sway_deps +) From 88cc7e31781a0d42bdd4f9eee646c02ff03857c4 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 03:39:27 -0500 Subject: [PATCH 028/522] use meson subdirectories --- common/meson.build | 8 ++++++++ meson.build | 35 ++--------------------------------- sway/meson.build | 29 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 33 deletions(-) create mode 100644 common/meson.build create mode 100644 sway/meson.build diff --git a/common/meson.build b/common/meson.build new file mode 100644 index 000000000..ca1f17526 --- /dev/null +++ b/common/meson.build @@ -0,0 +1,8 @@ +sway_common = files( + 'log.c', + 'list.c', + 'util.c', + 'stringop.c', + 'readline.c', + 'ipc-client.c' +) diff --git a/meson.build b/meson.build index 06eed97fb..a28e10974 100644 --- a/meson.build +++ b/meson.build @@ -30,37 +30,6 @@ add_project_arguments('-DSWAY_VERSION="5"', language: 'c') sway_inc = include_directories('include') -sway_sources = [ - 'sway/main.c', - 'sway/server.c', - 'sway/commands.c', - 'sway/commands/exit.c', - 'sway/ipc-json.c', - 'sway/ipc-server.c', - 'sway/desktop/output.c', - 'sway/desktop/xdg_shell_v6.c', - 'sway/tree/container.c', - 'sway/tree/layout.c', - 'sway/tree/workspace.c', - 'common/log.c', - 'common/list.c', - 'common/stringop.c', - 'common/readline.c', - 'common/ipc-client.c', -] +subdir('common') +subdir('sway') -sway_deps = [ - pixman, - wayland_server, - jsonc, - wlroots, - libcap, - math, -] - -executable( - 'sway', - sway_sources, - include_directories: [sway_inc], - dependencies: sway_deps -) diff --git a/sway/meson.build b/sway/meson.build new file mode 100644 index 000000000..1f17ed31d --- /dev/null +++ b/sway/meson.build @@ -0,0 +1,29 @@ +sway_sources = sway_common + files( + 'main.c', + 'server.c', + 'commands.c', + 'commands/exit.c', + 'ipc-json.c', + 'ipc-server.c', + 'desktop/output.c', + 'desktop/xdg_shell_v6.c', + 'tree/container.c', + 'tree/layout.c', + 'tree/workspace.c', +) + +sway_deps = [ + pixman, + wayland_server, + jsonc, + wlroots, + libcap, + math, +] + +executable( + 'sway', + sway_sources, + include_directories: [sway_inc], + dependencies: sway_deps +) From 6924064766ac772564d1b924df8c2071c1660235 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 03:41:51 -0500 Subject: [PATCH 029/522] fix meson.build whitespace --- meson.build | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/meson.build b/meson.build index a28e10974..6f2681af9 100644 --- a/meson.build +++ b/meson.build @@ -11,18 +11,17 @@ project( cc = meson.get_compiler('c') -jsonc = dependency('json-c', version: '>=0.12.1') -pcre = dependency('libpcre') -wlroots = dependency('wlroots') +jsonc = dependency('json-c', version: '>=0.12.1') +pcre = dependency('libpcre') +wlroots = dependency('wlroots') wayland_server = dependency('wayland-server') wayland_client = dependency('wayland-client') wayland_egl = dependency('wayland-egl') wayland_protos = dependency('wayland-protocols') xkbcommon = dependency('xkbcommon') -pango = dependency('pango') -pixman = dependency('pixman-1') -libcap = dependency('libcap') - +pango = dependency('pango') +pixman = dependency('pixman-1') +libcap = dependency('libcap') math = cc.find_library('m') # TODO version From 86d1ecf783f8fd164ed63501c859b65cfc6bc022 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 04:29:32 -0500 Subject: [PATCH 030/522] meson add version info --- meson.build | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 6f2681af9..af383fbfd 100644 --- a/meson.build +++ b/meson.build @@ -24,8 +24,11 @@ pixman = dependency('pixman-1') libcap = dependency('libcap') math = cc.find_library('m') -# TODO version -add_project_arguments('-DSWAY_VERSION="5"', language: 'c') +git_commit_hash = run_command(['git', 'describe', '--always', '--tags']).stdout().strip() +git_branch = run_command(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).stdout().strip() +version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash, git_branch) + +add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') sway_inc = include_directories('include') From 739bafbd8ecdbbf2eb3fd42e1b3d9249236a3fcf Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 04:48:08 -0500 Subject: [PATCH 031/522] make meson version configurable --- meson.build | 16 +++++++++++++--- meson_options.txt | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 meson_options.txt diff --git a/meson.build b/meson.build index af383fbfd..ac161987d 100644 --- a/meson.build +++ b/meson.build @@ -23,10 +23,20 @@ pango = dependency('pango') pixman = dependency('pixman-1') libcap = dependency('libcap') math = cc.find_library('m') +git = find_program('git', required: false) -git_commit_hash = run_command(['git', 'describe', '--always', '--tags']).stdout().strip() -git_branch = run_command(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).stdout().strip() -version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash, git_branch) +version = get_option('sway_version') +if version != '' + version = '"@0@"'.format(version) +else + if not git.found() + error('git is required to make the version string') + endif + + git_commit_hash = run_command([git.path(), 'describe', '--always', '--tags']).stdout().strip() + git_branch = run_command([git.path(), 'rev-parse', '--abbrev-ref', 'HEAD']).stdout().strip() + version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash, git_branch) +endif add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 000000000..5015a9861 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('sway_version', type : 'string', description : 'The version string reported in `sway --version`.') From cc310cffb0bf4cd2333be26a2ae16848655a306b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 06:25:13 -0500 Subject: [PATCH 032/522] meson: common static library --- common/meson.build | 17 ++++++++++------- sway/meson.build | 5 +++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/common/meson.build b/common/meson.build index ca1f17526..3a4282ad5 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,8 +1,11 @@ -sway_common = files( - 'log.c', - 'list.c', - 'util.c', - 'stringop.c', - 'readline.c', - 'ipc-client.c' +lib_sway_common = static_library('sway-common', + files( + 'log.c', + 'list.c', + 'util.c', + 'stringop.c', + 'readline.c', + 'ipc-client.c' + ), + include_directories: sway_inc ) diff --git a/sway/meson.build b/sway/meson.build index 1f17ed31d..b02506c8a 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -1,4 +1,4 @@ -sway_sources = sway_common + files( +sway_sources = files( 'main.c', 'server.c', 'commands.c', @@ -25,5 +25,6 @@ executable( 'sway', sway_sources, include_directories: [sway_inc], - dependencies: sway_deps + dependencies: sway_deps, + link_with: [lib_sway_common] ) From 2f3633433e2f1d840f3a98ca777d79d658a66e3f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 08:31:13 -0500 Subject: [PATCH 033/522] add meson install files --- config.in | 4 +-- meson.build | 54 ++++++++++++++++++++++++++++++++++++++- meson_options.txt | 3 ++- security.d/00-defaults.in | 18 ++++++------- sway/meson.build | 3 ++- 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/config.in b/config.in index b39a39aab..086b66dc6 100644 --- a/config.in +++ b/config.in @@ -21,7 +21,7 @@ set $menu dmenu_run ### Output configuration # # Default wallpaper (more resolutions are available in __DATADIR__/backgrounds/sway/) -output * bg __DATADIR__/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill +output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill # # Example configuration: # @@ -194,4 +194,4 @@ bar { } } -include __SYSCONFDIR__/sway/config.d/* +include @sysconfdir@/sway/config.d/* diff --git a/meson.build b/meson.build index ac161987d..494f28668 100644 --- a/meson.build +++ b/meson.build @@ -11,6 +11,11 @@ project( cc = meson.get_compiler('c') +is_freebsd = host_machine.system().startswith('freebsd') +datadir = get_option('datadir') +sysconfdir = get_option('sysconfdir') +prefix = get_option('prefix') + jsonc = dependency('json-c', version: '>=0.12.1') pcre = dependency('libpcre') wlroots = dependency('wlroots') @@ -37,7 +42,6 @@ else git_branch = run_command([git.path(), 'rev-parse', '--abbrev-ref', 'HEAD']).stdout().strip() version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash, git_branch) endif - add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') sway_inc = include_directories('include') @@ -45,3 +49,51 @@ sway_inc = include_directories('include') subdir('common') subdir('sway') +config = configuration_data() +config.set('sysconfdir', join_paths(prefix, sysconfdir)) +config.set('datadir', join_paths(prefix, datadir)) +config.set('prefix', prefix) + +configure_file( + configuration: config, + input: 'config.in', + output: '@BASENAME@', + install_dir: sysconfdir + '/sway' +) + +if is_freebsd + configure_file( + configuration: config, + input: 'security.d/10-freebsd.in', + output: '@BASENAME@', + install_dir: sysconfdir + '/sway/security.d' + ) +else + configure_file( + configuration: config, + input: 'security.d/00-defaults.in', + output: '@BASENAME@', + install_dir: sysconfdir + '/sway/security.d' + ) +endif + +install_data( + 'sway.desktop', + install_dir: datadir + '/wayland-sessions' +) + +if (get_option('default_wallpaper')) + wallpaper_files = files( + 'assets/Sway_Wallpaper_Blue_768x1024.png', + 'assets/Sway_Wallpaper_Blue_768x1024_Portrait.png', + 'assets/Sway_Wallpaper_Blue_1136x640.png', + 'assets/Sway_Wallpaper_Blue_1136x640_Portrait.png', + 'assets/Sway_Wallpaper_Blue_1366x768.png', + 'assets/Sway_Wallpaper_Blue_1920x1080.png', + 'assets/Sway_Wallpaper_Blue_2048x1536.png', + 'assets/Sway_Wallpaper_Blue_2048x1536_Portrait.png', + ) + wallpaper_install_dir = datadir + '/backgrounds/sway' + + install_data(wallpaper_files, install_dir: wallpaper_install_dir) +endif diff --git a/meson_options.txt b/meson_options.txt index 5015a9861..03bc19862 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1 +1,2 @@ -option('sway_version', type : 'string', description : 'The version string reported in `sway --version`.') +option('sway_version', type : 'string', description: 'The version string reported in `sway --version`.') +option('default_wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.') diff --git a/security.d/00-defaults.in b/security.d/00-defaults.in index 05098dea0..e46264773 100644 --- a/security.d/00-defaults.in +++ b/security.d/00-defaults.in @@ -6,17 +6,17 @@ # installation. # # DO NOT CHANGE THIS FILE. Override these defaults by writing new files in -# __SYSCONFDIR__/sway/security.d/* +# @sysconfdir@/sway/security.d/* # Configures enabled compositor features for specific programs permit * fullscreen keyboard mouse -permit __PREFIX__/bin/swaylock lock -permit __PREFIX__/bin/swaybg background -permit __PREFIX__/bin/swaygrab screenshot -permit __PREFIX__/bin/swaybar panel +permit @prefix@/bin/swaylock lock +permit @prefix@/bin/swaybg background +permit @prefix@/bin/swaygrab screenshot +permit @prefix@/bin/swaybar panel # Configures enabled IPC features for specific programs -ipc __PREFIX__/bin/swaymsg { +ipc @prefix@/bin/swaymsg { * enabled events { @@ -24,7 +24,7 @@ ipc __PREFIX__/bin/swaymsg { } } -ipc __PREFIX__/bin/swaybar { +ipc @prefix@/bin/swaybar { bar-config enabled outputs enabled workspaces enabled @@ -36,12 +36,12 @@ ipc __PREFIX__/bin/swaybar { } } -ipc __PREFIX__/bin/swaygrab { +ipc @prefix@/bin/swaygrab { outputs enabled tree enabled } -ipc __PREFIX__/bin/swaylock { +ipc @prefix@/bin/swaylock { outputs enabled } diff --git a/sway/meson.build b/sway/meson.build index b02506c8a..cf2aa9137 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -26,5 +26,6 @@ executable( sway_sources, include_directories: [sway_inc], dependencies: sway_deps, - link_with: [lib_sway_common] + link_with: [lib_sway_common], + install: true ) From 03182706cffc4e996d352c51b143df805f80a928 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 11:34:44 -0500 Subject: [PATCH 034/522] meson build manpages --- meson.build | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/meson.build b/meson.build index 494f28668..34122accd 100644 --- a/meson.build +++ b/meson.build @@ -29,6 +29,39 @@ pixman = dependency('pixman-1') libcap = dependency('libcap') math = cc.find_library('m') git = find_program('git', required: false) +a2x = find_program('a2x', required: false) + +if a2x.found() + mandir = get_option('mandir') + man_files = [ + 'sway/sway.1.txt', + 'sway/sway.5.txt', + 'sway/sway-bar.5.txt', + 'sway/sway-input.5.txt', + 'sway/sway-security.7.txt', + 'swaymsg/swaymsg.1.txt', + ] + foreach filename : man_files + topic = filename.split('.')[-3].split('/')[-1] + section = filename.split('.')[-2] + + custom_target( + 'man-@0@-@1@'.format(topic, section), + input: filename, + output: '@BASENAME@', + command: [ + a2x, + '--no-xmllint', + '--doctype', 'manpage', + '--format', 'manpage', + '--destination-dir', meson.current_build_dir(), + '@INPUT@' + ], + install: true, + install_dir: '@0@/man@1@'.format(mandir, section) + ) + endforeach +endif version = get_option('sway_version') if version != '' From 1d702b6376b49c2e115c5b985ca241aedc40a48b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 11:40:49 -0500 Subject: [PATCH 035/522] meson build swaymsg --- meson.build | 1 + swaymsg/meson.build | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 swaymsg/meson.build diff --git a/meson.build b/meson.build index 34122accd..1c3221318 100644 --- a/meson.build +++ b/meson.build @@ -81,6 +81,7 @@ sway_inc = include_directories('include') subdir('common') subdir('sway') +subdir('swaymsg') config = configuration_data() config.set('sysconfdir', join_paths(prefix, sysconfdir)) diff --git a/swaymsg/meson.build b/swaymsg/meson.build new file mode 100644 index 000000000..2d678878f --- /dev/null +++ b/swaymsg/meson.build @@ -0,0 +1,8 @@ +executable( + 'swaymsg', + 'main.c', + include_directories: [sway_inc], + dependencies: [jsonc], + link_with: [lib_sway_common], + install: true +) From fe5c0316096b47d9a9bbede1d35e52e04ad9b40f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 11:51:58 -0500 Subject: [PATCH 036/522] meson zsh completions install --- meson.build | 12 ++++++++++++ meson_options.txt | 1 + 2 files changed, 13 insertions(+) diff --git a/meson.build b/meson.build index 1c3221318..05d92a914 100644 --- a/meson.build +++ b/meson.build @@ -131,3 +131,15 @@ if (get_option('default_wallpaper')) install_data(wallpaper_files, install_dir: wallpaper_install_dir) endif + +if (get_option('zsh_completions')) + zsh_files = files( + 'completions/zsh/_sway', + 'completions/zsh/_swaygrab', + 'completions/zsh/_swaylock', + 'completions/zsh/_swaymsg', + ) + zsh_install_dir = datadir + '/zsh/site-functions' + + install_data(zsh_files, install_dir: zsh_install_dir) +endif diff --git a/meson_options.txt b/meson_options.txt index 03bc19862..541ccf138 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,2 +1,3 @@ option('sway_version', type : 'string', description: 'The version string reported in `sway --version`.') option('default_wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.') +option('zsh_completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') From 517af37cc9a9f7b5efa3e22d7021aab691c80244 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 11:54:01 -0500 Subject: [PATCH 037/522] remove relevant CMakeLists.txt --- CMakeLists.txt | 165 --------------------------------- common/CMakeLists.txt | 15 --- completions/zsh/CMakeLists.txt | 4 - sway/CMakeLists.txt | 96 ------------------- swaymsg/CMakeLists.txt | 23 ----- 5 files changed, 303 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 common/CMakeLists.txt delete mode 100644 completions/zsh/CMakeLists.txt delete mode 100644 sway/CMakeLists.txt delete mode 100644 swaymsg/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 9580e15df..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,165 +0,0 @@ -cmake_minimum_required(VERSION 3.1.0) - -project(sway C) - -add_compile_options(-g) -set(CMAKE_C_STANDARD 99) -set(CMAKE_C_EXTENSIONS OFF) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) -add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-result -Werror) - -# Add Address Sanitiezed build type -set(CMAKE_C_FLAGS_ASAN - "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" - CACHE STRING "Flags used by the C compiler during address sanitizer builds." - FORCE ) -mark_as_advanced( - CMAKE_C_FLAGS_ASAN - CMAKE_EXE_LINKER_FLAGS_DEBUG - CMAKE_SHARED_LINKER_FLAGS_DEBUG - ) - -list(INSERT CMAKE_MODULE_PATH 0 - ${CMAKE_CURRENT_SOURCE_DIR}/CMake - ) - -if (VERSION) - add_definitions(-DSWAY_VERSION=\"${VERSION}\") -else() - execute_process( - COMMAND git describe --always --tags - OUTPUT_VARIABLE GIT_COMMIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - execute_process( - COMMAND git rev-parse --abbrev-ref HEAD - OUTPUT_VARIABLE GIT_BRANCH - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - - string(TIMESTAMP CURRENT_DATE "%Y-%m-%d" UTC) - add_definitions("-DSWAY_VERSION=\"${GIT_COMMIT_HASH} (${CURRENT_DATE}, branch \\\"${GIT_BRANCH}\\\")\"") -endif() - -option(enable-swaylock "Enables the swaylock utility" YES) -option(enable-swaybg "Enables the wallpaper utility" YES) -option(enable-swaybar "Enables the swaybar utility" YES) -option(enable-swaygrab "Enables the swaygrab utility" YES) -option(enable-swaymsg "Enables the swaymsg utility" YES) -option(enable-gdk-pixbuf "Use Pixbuf to support more image formats" YES) -option(enable-tray "Enables the swaybar tray" YES) -option(zsh-completions "Zsh shell completions" NO) -option(default-wallpaper "Installs the default wallpaper" YES) -option(LD_LIBRARY_PATH "Configure sway's default LD_LIBRARY_PATH") - -if (LD_LIBRARY_PATH) - add_definitions(-D_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}") -endif() - -find_package(JsonC 0.12.1 REQUIRED) -find_package(PCRE REQUIRED) -find_package(Wlroots REQUIRED) -find_package(Wayland REQUIRED) -find_package(XKBCommon REQUIRED) -find_package(Cairo REQUIRED) -find_package(Pango REQUIRED) -find_package(GdkPixbuf) -find_package(PAM) -find_package(DBus 1.10) - -find_package(LibInput REQUIRED) - -if (CMAKE_SYSTEM_NAME STREQUAL Linux) - find_package(Libcap REQUIRED) -endif (CMAKE_SYSTEM_NAME STREQUAL Linux) - -if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - find_package(EpollShim REQUIRED) -endif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - -include(FeatureSummary) -include(Manpage) -include(GNUInstallDirs) - -if (enable-gdk-pixbuf) - if (GDK_PIXBUF_FOUND) - set(WITH_GDK_PIXBUF YES) - add_definitions(-DWITH_GDK_PIXBUF) - else() - message(WARNING "gdk-pixbuf required but not found, only png images supported.") - endif() -else() - message(STATUS "Building without gdk-pixbuf, only png images supported.") -endif() - -if (enable-tray) - if (DBUS_FOUND) - set(ENABLE_TRAY TRUE) - add_definitions(-DENABLE_TRAY) - else() - message(WARNING "Tray required but DBus was not found. Tray will not be included") - endif() -else() - message(STATUS "Building without the tray.") -endif() - -include_directories(include) - -add_subdirectory(protocols) -add_subdirectory(common) -add_subdirectory(wayland) - -add_subdirectory(sway) -if(enable-swaybg) - if(CAIRO_FOUND AND PANGO_FOUND) - # TODO WLR - #add_subdirectory(swaybg) - else() - message(WARNING "Not building swaybg - cairo, and pango are required.") - endif() -endif() -if(enable-swaymsg) - add_subdirectory(swaymsg) -endif() -if(enable-swaygrab) - # TODO WLR - #add_subdirectory(swaygrab) -endif() -if(enable-swaybar) - if(CAIRO_FOUND AND PANGO_FOUND) - # TODO WLR - #add_subdirectory(swaybar) - else() - message(WARNING "Not building swaybar - cairo, and pango are required.") - endif() -endif() -if(enable-swaylock) - if(CAIRO_FOUND AND PANGO_FOUND AND PAM_FOUND) - # TODO WLR - #add_subdirectory(swaylock) - else() - message(WARNING "Not building swaylock - cairo, pango, and PAM are required.") - endif() -endif() -if(zsh-completions) - add_subdirectory(completions/zsh) -endif() -install( - FILES ${CMAKE_CURRENT_SOURCE_DIR}/sway.desktop - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/wayland-sessions - COMPONENT data - ) - -if(default-wallpaper) - install( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/assets/ - DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/backgrounds/sway - COMPONENT data - FILES_MATCHING PATTERN "*Wallpaper*" - ) -endif() - -feature_summary(WHAT ALL) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt deleted file mode 100644 index 4fa71f3a2..000000000 --- a/common/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -include_directories( - ${WLC_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} -) - -add_library(sway-common STATIC - ipc-client.c - list.c - log.c - util.c - readline.c - stringop.c -) - -target_link_libraries(sway-common m) diff --git a/completions/zsh/CMakeLists.txt b/completions/zsh/CMakeLists.txt deleted file mode 100644 index 62c850907..000000000 --- a/completions/zsh/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -install( - FILES _sway _swaymsg _swaygrab _swaylock - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/zsh/site-functions/ -) diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt deleted file mode 100644 index 274fcc4ad..000000000 --- a/sway/CMakeLists.txt +++ /dev/null @@ -1,96 +0,0 @@ -include_directories( - ${PROTOCOLS_INCLUDE_DIRS} - ${WLR_INCLUDE_DIRS} - ${PCRE_INCLUDE_DIRS} - ${JSONC_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} - ${LIBINPUT_INCLUDE_DIRS} - ${CAIRO_INCLUDE_DIRS} - ${PANGO_INCLUDE_DIRS} - ${WAYLAND_INCLUDE_DIR} -) - -add_executable(sway - desktop/output.c - desktop/xdg_shell_v6.c - - commands.c - commands/exit.c - - tree/container.c - tree/layout.c - tree/workspace.c - - base64.c - main.c - server.c - ipc-json.c - ipc-server.c -) - -add_definitions( - -DSYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}" -) - -target_link_libraries(sway - sway-common - sway-protocols - sway-wayland - ${WLR_LIBRARIES} - ${XKBCOMMON_LIBRARIES} - ${PCRE_LIBRARIES} - ${JSONC_LIBRARIES} - ${WAYLAND_SERVER_LIBRARIES} - ${LIBINPUT_LIBRARIES} - ${PANGO_LIBRARIES} - ${JSONC_LIBRARIES} - m -) - -if (CMAKE_SYSTEM_NAME STREQUAL Linux) - target_link_libraries(sway cap) -endif (CMAKE_SYSTEM_NAME STREQUAL Linux) - -install( - TARGETS sway - RUNTIME - DESTINATION bin - COMPONENT runtime -) - -add_custom_target(configs ALL) - -function(add_config name source destination) - add_custom_command( - OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} - COMMAND sed -r - 's?__PREFIX__?${CMAKE_INSTALL_PREFIX}?g\; s?__SYSCONFDIR__?${CMAKE_INSTALL_FULL_SYSCONFDIR}?g\; s?__DATADIR__?${CMAKE_INSTALL_FULL_DATADIR}?g' - ${PROJECT_SOURCE_DIR}/${source}.in > ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} - DEPENDS ${PROJECT_SOURCE_DIR}/${source}.in - COMMENT "Generating config file ${source}" - ) - - install( - FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} - DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/${destination} - COMPONENT configuration - ) - - add_custom_target(config-${name} DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name}) - add_dependencies(configs config-${name}) -endfunction() - -add_config(config config sway) -add_config(00-defaults security.d/00-defaults sway/security.d) - -if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - add_config(10-freebsd security.d/10-freebsd sway/security.d) -endif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - -if (A2X_FOUND) - add_manpage(sway 1) - add_manpage(sway 5) - add_manpage(sway-input 5) - add_manpage(sway-bar 5) - add_manpage(sway-security 7) -endif() diff --git a/swaymsg/CMakeLists.txt b/swaymsg/CMakeLists.txt deleted file mode 100644 index b428a409f..000000000 --- a/swaymsg/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -add_executable(swaymsg - main.c -) - -include_directories( - ${JSONC_INCLUDE_DIRS} -) - -target_link_libraries(swaymsg - sway-common - ${JSONC_LIBRARIES} -) - -install( - TARGETS swaymsg - RUNTIME - DESTINATION bin - COMPONENT runtime -) - -if (A2X_FOUND) - add_manpage(swaymsg 1) -endif() From d071ff08aeae2bbea4ac4a8e56c7a146c13d0869 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 1 Dec 2017 05:21:03 -0500 Subject: [PATCH 038/522] remove the rest of cmake --- .gitignore | 4 - CMake/FindA2X.cmake | 75 ------------ CMake/FindCairo.cmake | 42 ------- CMake/FindDBus.cmake | 59 --------- CMake/FindEpollShim.cmake | 17 --- CMake/FindGdkPixbuf.cmake | 43 ------- CMake/FindJsonC.cmake | 29 ----- CMake/FindLibInput.cmake | 66 ---------- CMake/FindLibcap.cmake | 56 --------- CMake/FindPAM.cmake | 245 -------------------------------------- CMake/FindPCRE.cmake | 37 ------ CMake/FindPango.cmake | 42 ------- CMake/FindWLC.cmake | 20 ---- CMake/FindWayland.cmake | 67 ----------- CMake/FindWlroots.cmake | 20 ---- CMake/FindXKBCommon.cmake | 19 --- CMake/Manpage.cmake | 33 ----- CMake/Wayland.cmake | 77 ------------ README.md | 10 +- protocols/CMakeLists.txt | 46 ------- swaybar/CMakeLists.txt | 51 -------- swaybg/CMakeLists.txt | 37 ------ swaygrab/CMakeLists.txt | 28 ----- swaylock/CMakeLists.txt | 51 -------- wayland/CMakeLists.txt | 32 ----- 25 files changed, 4 insertions(+), 1202 deletions(-) delete mode 100644 CMake/FindA2X.cmake delete mode 100644 CMake/FindCairo.cmake delete mode 100644 CMake/FindDBus.cmake delete mode 100644 CMake/FindEpollShim.cmake delete mode 100644 CMake/FindGdkPixbuf.cmake delete mode 100644 CMake/FindJsonC.cmake delete mode 100644 CMake/FindLibInput.cmake delete mode 100644 CMake/FindLibcap.cmake delete mode 100644 CMake/FindPAM.cmake delete mode 100644 CMake/FindPCRE.cmake delete mode 100644 CMake/FindPango.cmake delete mode 100644 CMake/FindWLC.cmake delete mode 100644 CMake/FindWayland.cmake delete mode 100644 CMake/FindWlroots.cmake delete mode 100644 CMake/FindXKBCommon.cmake delete mode 100644 CMake/Manpage.cmake delete mode 100644 CMake/Wayland.cmake delete mode 100644 protocols/CMakeLists.txt delete mode 100644 swaybar/CMakeLists.txt delete mode 100644 swaybg/CMakeLists.txt delete mode 100644 swaygrab/CMakeLists.txt delete mode 100644 swaylock/CMakeLists.txt delete mode 100644 wayland/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 48f8a0cb0..b6e56f7ab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ -CMakeCache.txt -CMakeFiles -Makefile -cmake_install.cmake install_manifest.txt *.swp *.o diff --git a/CMake/FindA2X.cmake b/CMake/FindA2X.cmake deleted file mode 100644 index b38f5086c..000000000 --- a/CMake/FindA2X.cmake +++ /dev/null @@ -1,75 +0,0 @@ -# -# (c)2015 KiCad Developers -# (c)2015 Brian Sidebotham -# -# CMake module to find a2x (part of the asciidoc toolchain). -# -# Variables generated: -# -# A2X_FOUND true when A2X_COMMAND is valid -# A2X_COMMAND The command to run a2x (may be a list including an interpreter) -# A2X_VERSION The a2x version that has been found -# - -# Have a go at finding a a2x executable -find_program( A2X_PROGRAM a2x ) - -# Found something, attempt to try and use it... -if( A2X_PROGRAM ) - execute_process( - COMMAND ${A2X_PROGRAM} --version - OUTPUT_VARIABLE _OUT - ERROR_VARIABLE _ERR - RESULT_VARIABLE _RES - OUTPUT_STRIP_TRAILING_WHITESPACE ) - - # If it worked, set the A2X_COMMAND - if( _RES MATCHES 0 ) - set( A2X_COMMAND "${A2X_PROGRAM}" ) - endif() -endif() - -# If nothing could be found, test to see if we can just find the script file, -# that we'll then run with the python interpreter -if( NOT A2X_COMMAND ) - find_file( A2X_SCRIPT a2x.py ) - - if( A2X_SCRIPT ) - # Find the python interpreter quietly - if( NOT PYTHONINTERP_FOUND ) - find_package( PYTHONINTERP QUIET ) - endif() - - if( NOT PYTHONINTERP_FOUND ) - # Python's not available so can't find a2x... - set( A2X_COMMAND "" ) - else() - # Build the python based command - set( A2X_COMMAND "${PYTHON_EXECUTABLE}" "${A2X_SCRIPT}" ) - - execute_process( - COMMAND ${A2X_COMMAND} --version - OUTPUT_VARIABLE _OUT - ERROR_VARIABLE _ERR - RESULT_VARIABLE _RES - OUTPUT_STRIP_TRAILING_WHITESPACE ) - - # If it still can't be run, then give up - if( NOT _RES MATCHES 0 ) - set( A2X_COMMAND "" ) - endif() - endif() - endif() -endif() - -# If we've found a command that works, check the version -if( A2X_COMMAND ) - string(REGEX REPLACE ".*a2x[^0-9.]*\([0-9.]+\).*" "\\1" A2X_VERSION "${_OUT}") -endif() - -# Generate the *_FOUND as necessary, etc. -include( FindPackageHandleStandardArgs ) -find_package_handle_standard_args( - A2X - REQUIRED_VARS A2X_COMMAND - VERSION_VAR A2X_VERSION ) diff --git a/CMake/FindCairo.cmake b/CMake/FindCairo.cmake deleted file mode 100644 index 10ab8fb02..000000000 --- a/CMake/FindCairo.cmake +++ /dev/null @@ -1,42 +0,0 @@ -# - Try to find the cairo library -# Once done this will define -# -# CAIRO_FOUND - system has cairo -# CAIRO_INCLUDE_DIRS - the cairo include directory -# CAIRO_LIBRARIES - Link these to use cairo -# -# Define CAIRO_MIN_VERSION for which version desired. -# - -find_package(PkgConfig) - -if(Cairo_FIND_REQUIRED) - set(_pkgconfig_REQUIRED "REQUIRED") -else(Cairo_FIND_REQUIRED) - set(_pkgconfig_REQUIRED "") -endif(Cairo_FIND_REQUIRED) - -if(CAIRO_MIN_VERSION) - pkg_check_modules(CAIRO ${_pkgconfig_REQUIRED} cairo>=${CAIRO_MIN_VERSION}) -else(CAIRO_MIN_VERSION) - pkg_check_modules(CAIRO ${_pkgconfig_REQUIRED} cairo) -endif(CAIRO_MIN_VERSION) - -if(NOT CAIRO_FOUND AND NOT PKG_CONFIG_FOUND) - find_path(CAIRO_INCLUDE_DIRS cairo.h) - find_library(CAIRO_LIBRARIES cairo) -else(NOT CAIRO_FOUND AND NOT PKG_CONFIG_FOUND) - # Make paths absolute https://stackoverflow.com/a/35476270 - # Important on FreeBSD because /usr/local/lib is not on /usr/bin/ld's default path - set(CAIRO_LIBS_ABSOLUTE) - foreach(lib ${CAIRO_LIBRARIES}) - set(var_name CAIRO_${lib}_ABS) - find_library(${var_name} ${lib} ${CAIRO_LIBRARY_DIRS}) - list(APPEND CAIRO_LIBS_ABSOLUTE ${${var_name}}) - endforeach() - set(CAIRO_LIBRARIES ${CAIRO_LIBS_ABSOLUTE}) -endif(NOT CAIRO_FOUND AND NOT PKG_CONFIG_FOUND) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(CAIRO DEFAULT_MSG CAIRO_LIBRARIES CAIRO_INCLUDE_DIRS) -mark_as_advanced(CAIRO_LIBRARIES CAIRO_INCLUDE_DIRS) diff --git a/CMake/FindDBus.cmake b/CMake/FindDBus.cmake deleted file mode 100644 index 4a1a18056..000000000 --- a/CMake/FindDBus.cmake +++ /dev/null @@ -1,59 +0,0 @@ -# - Try to find DBus -# Once done, this will define -# -# DBUS_FOUND - system has DBus -# DBUS_INCLUDE_DIRS - the DBus include directories -# DBUS_LIBRARIES - link these to use DBus -# -# Copyright (C) 2012 Raphael Kubo da Costa -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS -# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FIND_PACKAGE(PkgConfig) -PKG_CHECK_MODULES(PC_DBUS QUIET dbus-1) - -FIND_LIBRARY(DBUS_LIBRARIES - NAMES dbus-1 - HINTS ${PC_DBUS_LIBDIR} - ${PC_DBUS_LIBRARY_DIRS} -) - -FIND_PATH(DBUS_INCLUDE_DIR - NAMES dbus/dbus.h - HINTS ${PC_DBUS_INCLUDEDIR} - ${PC_DBUS_INCLUDE_DIRS} -) - -GET_FILENAME_COMPONENT(_DBUS_LIBRARY_DIR ${DBUS_LIBRARIES} PATH) -FIND_PATH(DBUS_ARCH_INCLUDE_DIR - NAMES dbus/dbus-arch-deps.h - HINTS ${PC_DBUS_INCLUDEDIR} - ${PC_DBUS_INCLUDE_DIRS} - ${_DBUS_LIBRARY_DIR} - ${DBUS_INCLUDE_DIR} - PATH_SUFFIXES include -) - -SET(DBUS_INCLUDE_DIRS ${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR}) - -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(DBUS REQUIRED_VARS DBUS_INCLUDE_DIRS DBUS_LIBRARIES) diff --git a/CMake/FindEpollShim.cmake b/CMake/FindEpollShim.cmake deleted file mode 100644 index b6bed1426..000000000 --- a/CMake/FindEpollShim.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# - Find EpollShim -# Once done, this will define -# -# EPOLLSHIM_FOUND - System has EpollShim -# EPOLLSHIM_INCLUDE_DIRS - The EpollShim include directories -# EPOLLSHIM_LIBRARIES - The libraries needed to use EpollShim - -find_path(EPOLLSHIM_INCLUDE_DIRS NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim) -find_library(EPOLLSHIM_LIBRARIES NAMES epoll-shim libepoll-shim HINTS /usr/local/lib) - -if (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES) - set(EPOLLSHIM_FOUND TRUE) -endif (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(EPOLLSHIM DEFAULT_MSG EPOLLSHIM_LIBRARIES EPOLLSHIM_INCLUDE_DIRS) -mark_as_advanced(EPOLLSHIM_INCLUDE_DIRS EPOLLSHIM_LIBRARIES) diff --git a/CMake/FindGdkPixbuf.cmake b/CMake/FindGdkPixbuf.cmake deleted file mode 100644 index 9cad4f926..000000000 --- a/CMake/FindGdkPixbuf.cmake +++ /dev/null @@ -1,43 +0,0 @@ -# - Try to find the gdk-pixbuf-2.0 library -# Once done this will define -# -# GDK_PIXBUF_FOUND - system has gdk-pixbuf-2.0 -# GDK_PIXBUF_INCLUDE_DIRS - the gdk-pixbuf-2.0 include directory -# GDK_PIXBUF_LIBRARIES - Link these to use gdk-pixbuf-2.0 -# -# Define GDK_PIXBUF_MIN_VERSION for which version desired. -# - -find_package(PkgConfig) - -if(GdkPixbuf_FIND_REQUIRED) - set(_pkgconfig_REQUIRED "REQUIRED") -else(GdkPixbuf_FIND_REQUIRED) - set(_pkgconfig_REQUIRED "") -endif(GdkPixbuf_FIND_REQUIRED) - -if(GDK_PIXBUF_MIN_VERSION) - pkg_check_modules(GDK_PIXBUF ${_pkgconfig_REQUIRED} "gdk-pixbuf-2.0>=${GDK_PIXBUF_MIN_VERSION}") -else(GDK_PIXBUF_MIN_VERSION) - pkg_check_modules(GDK_PIXBUF ${_pkgconfig_REQUIRED} "gdk-pixbuf-2.0") -endif(GDK_PIXBUF_MIN_VERSION) - -if(NOT GDK_PIXBUF_FOUND AND NOT PKG_CONFIG_FOUND) - find_path(GDK_PIXBUF_INCLUDE_DIRS gdk-pixbuf/gdk-pixbuf.h) - find_library(GDK_PIXBUF_LIBRARIES gdk_pixbuf-2.0) -else(NOT GDK_PIXBUF_FOUND AND NOT PKG_CONFIG_FOUND) - SET(GdkPixbuf_FOUND 1) - # Make paths absolute https://stackoverflow.com/a/35476270 - # Important on FreeBSD because /usr/local/lib is not on /usr/bin/ld's default path - set(GDK_PIXBUF_LIBS_ABSOLUTE) - foreach(lib ${GDK_PIXBUF_LIBRARIES}) - set(var_name GDK_PIXBUF_${lib}_ABS) - find_library(${var_name} ${lib} ${GDK_PIXBUF_LIBRARY_DIRS}) - list(APPEND GDK_PIXBUF_LIBS_ABSOLUTE ${${var_name}}) - endforeach() - set(GDK_PIXBUF_LIBRARIES ${GDK_PIXBUF_LIBS_ABSOLUTE}) -endif(NOT GDK_PIXBUF_FOUND AND NOT PKG_CONFIG_FOUND) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GDK_PIXBUF DEFAULT_MSG GDK_PIXBUF_LIBRARIES GDK_PIXBUF_INCLUDE_DIRS) -mark_as_advanced(GDK_PIXBUF_LIBRARIES GDK_PIXBUF_INCLUDE_DIRS) diff --git a/CMake/FindJsonC.cmake b/CMake/FindJsonC.cmake deleted file mode 100644 index bbf6930cf..000000000 --- a/CMake/FindJsonC.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# - Find json-c -# Find the json-c libraries -# -# This module defines the following variables: -# JSONC_FOUND - True if JSONC is found -# JSONC_LIBRARIES - JSONC libraries -# JSONC_INCLUDE_DIRS - JSONC include directories -# - -find_package(PkgConfig) - -if (JsonC_FIND_REQUIRED) - set(_pkgconfig_REQUIRED "REQUIRED") -else() - set(_pkgconfig_REQUIRED "") -endif() - -if(JsonC_FIND_VERSION) - pkg_check_modules(PC_JSONC ${_pkgconfig_REQUIRED} json-c=${JsonC_FIND_VERSION}) -else() - pkg_check_modules(PC_JSONC ${_pkgconfig_REQUIRED} json-c) -endif() - -find_path(JSONC_INCLUDE_DIRS NAMES json-c/json.h HINTS ${PC_JSONC_INCLUDE_DIRS}) -find_library(JSONC_LIBRARIES NAMES json-c HINTS ${PC_JSONC_LIBRARY_DIRS}) -include(FindPackageHandleStandardArgs) - -find_package_handle_standard_args(JSONC DEFAULT_MSG JSONC_LIBRARIES JSONC_INCLUDE_DIRS) -mark_as_advanced(JSONC_LIBRARIES JSONC_INCLUDE_DIRS) diff --git a/CMake/FindLibInput.cmake b/CMake/FindLibInput.cmake deleted file mode 100644 index 877219981..000000000 --- a/CMake/FindLibInput.cmake +++ /dev/null @@ -1,66 +0,0 @@ -#.rst: -# FindLibInput -# ------- -# -# Find LibInput library -# -# Try to find LibInpu library. The following values are defined -# -# :: -# -# LIBINPUT_FOUND - True if libinput is available -# LIBINPUT_INCLUDE_DIRS - Include directories for libinput -# LIBINPUT_LIBRARIES - List of libraries for libinput -# LIBINPUT_DEFINITIONS - List of definitions for libinput -# -# and also the following more fine grained variables -# -# :: -# -# LIBINPUT_VERSION -# LIBINPUT_VERSION_MAJOR -# LIBINPUT_VERSION_MINOR -# LIBINPUT_VERSION_MICRO -# -#============================================================================= -# Copyright (c) 2015 Jari Vetoniemi -# -# Distributed under the OSI-approved BSD License (the "License"); -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= - -include(FeatureSummary) -set_package_properties(LibInput PROPERTIES - URL "http://freedesktop.org/wiki/Software/libinput/" - DESCRIPTION "Library to handle input devices") - -find_package(PkgConfig) -pkg_check_modules(PC_INPUT QUIET libinput) -find_library(LIBINPUT_LIBRARIES NAMES input HINTS ${PC_INPUT_LIBRARY_DIRS}) -find_path(LIBINPUT_INCLUDE_DIRS libinput.h HINTS ${PC_INPUT_INCLUDE_DIRS}) - -set(LIBINPUT_VERSION ${PC_INPUT_VERSION}) -string(REPLACE "." ";" VERSION_LIST "${PC_INPUT_VERSION}") - -LIST(LENGTH VERSION_LIST n) -if (n EQUAL 3) - list(GET VERSION_LIST 0 LIBINPUT_VERSION_MAJOR) - list(GET VERSION_LIST 1 LIBINPUT_VERSION_MINOR) - list(GET VERSION_LIST 2 LIBINPUT_VERSION_MICRO) -endif () - -# This is compatible with libinput-version.h that exists in upstream -# but isn't in distribution (probably forgotten) -set(LIBINPUT_DEFINITIONS ${PC_INPUT_CFLAGS_OTHER} - -DLIBINPUT_VERSION=\"${LIBINPUT_VERSION}\" - -DLIBINPUT_VERSION_MAJOR=${LIBINPUT_VERSION_MAJOR} - -DLIBINPUT_VERSION_MINOR=${LIBINPUT_VERSION_MINOR} - -DLIBINPUT_VERSION_MICRO=${LIBINPUT_VERSION_MICRO}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LIBINPUT DEFAULT_MSG LIBINPUT_INCLUDE_DIRS LIBINPUT_LIBRARIES) -mark_as_advanced(LIBINPUT_INCLUDE_DIRS LIBINPUT_LIBRARIES LIBINPUT_DEFINITIONS - LIBINPUT_VERSION LIBINPUT_VERSION_MAJOR LIBINPUT_VERSION_MICRO LIBINPUT_VERSION_MINOR) diff --git a/CMake/FindLibcap.cmake b/CMake/FindLibcap.cmake deleted file mode 100644 index b34e5e373..000000000 --- a/CMake/FindLibcap.cmake +++ /dev/null @@ -1,56 +0,0 @@ -#.rst: -# FindLibcap -# ------- -# -# Find Libcap library -# -# Try to find Libcap library. The following values are defined -# -# :: -# -# Libcap_FOUND - True if Libcap is available -# Libcap_INCLUDE_DIRS - Include directories for Libcap -# Libcap_LIBRARIES - List of libraries for Libcap -# Libcap_DEFINITIONS - List of definitions for Libcap -# -# and also the following more fine grained variables -# -# :: -# -# Libcap_VERSION -# Libcap_VERSION_MAJOR -# Libcap_VERSION_MINOR -# -#============================================================================= -# Copyright (c) 2017 Jerzi Kaminsky -# -# Distributed under the OSI-approved BSD License (the "License"); -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= - -include(FeatureSummary) -set_package_properties(Libcap PROPERTIES - URL "https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2" - DESCRIPTION "Library for getting and setting POSIX.1e capabilities") - -find_package(PkgConfig) -pkg_check_modules(PC_CAP QUIET Libcap) -find_library(Libcap_LIBRARIES NAMES cap HINTS ${PC_CAP_LIBRARY_DIRS}) -find_path(Libcap_INCLUDE_DIRS sys/capability.h HINTS ${PC_CAP_INCLUDE_DIRS}) - -set(Libcap_VERSION ${PC_CAP_VERSION}) -string(REPLACE "." ";" VERSION_LIST "${PC_CAP_VERSION}") - -LIST(LENGTH VERSION_LIST n) -if (n EQUAL 2) - list(GET VERSION_LIST 0 Libcap_VERSION_MAJOR) - list(GET VERSION_LIST 1 Libcap_VERSION_MINOR) -endif () - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Libcap DEFAULT_MSG Libcap_INCLUDE_DIRS Libcap_LIBRARIES) -mark_as_advanced(Libcap_INCLUDE_DIRS Libcap_LIBRARIES Libcap_DEFINITIONS - Libcap_VERSION Libcap_VERSION_MAJOR Libcap_VERSION_MICRO Libcap_VERSION_MINOR) diff --git a/CMake/FindPAM.cmake b/CMake/FindPAM.cmake deleted file mode 100644 index 7e6e333ab..000000000 --- a/CMake/FindPAM.cmake +++ /dev/null @@ -1,245 +0,0 @@ -# - Try to find the PAM libraries -# Once done this will define -# -# PAM_FOUND - system has pam -# PAM_INCLUDE_DIR - the pam include directory -# PAM_LIBRARIES - libpam library - -if (PAM_INCLUDE_DIR AND PAM_LIBRARY) - set(PAM_FIND_QUIETLY TRUE) -endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) - -find_path(PAM_INCLUDE_DIR NAMES security/pam_appl.h pam/pam_appl.h) -find_library(PAM_LIBRARY pam) -find_library(DL_LIBRARY dl) - -if (PAM_INCLUDE_DIR AND PAM_LIBRARY) - set(PAM_FOUND TRUE) - if (DL_LIBRARY) - set(PAM_LIBRARIES ${PAM_LIBRARY} ${DL_LIBRARY}) - else (DL_LIBRARY) - set(PAM_LIBRARIES ${PAM_LIBRARY}) - endif (DL_LIBRARY) - - if (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) - set(HAVE_PAM_PAM_APPL_H 1) - endif (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) -endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) - -if (PAM_FOUND) - if (NOT PAM_FIND_QUIETLY) - message(STATUS "Found PAM: ${PAM_LIBRARIES}") - endif (NOT PAM_FIND_QUIETLY) -else (PAM_FOUND) - if (PAM_FIND_REQUIRED) - message(FATAL_ERROR "PAM was not found") - endif(PAM_FIND_REQUIRED) -endif (PAM_FOUND) - -mark_as_advanced(PAM_INCLUDE_DIR PAM_LIBRARY DL_LIBRARY) - -# This file taken from https://github.com/FreeRDP/FreeRDP -# -# -# -# Apache License -# Version 2.0, January 2004 -# http://www.apache.org/licenses/ -# -# TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -# -# 1. Definitions. -# -# "License" shall mean the terms and conditions for use, reproduction, -# and distribution as defined by Sections 1 through 9 of this document. -# -# "Licensor" shall mean the copyright owner or entity authorized by -# the copyright owner that is granting the License. -# -# "Legal Entity" shall mean the union of the acting entity and all -# other entities that control, are controlled by, or are under common -# control with that entity. For the purposes of this definition, -# "control" means (i) the power, direct or indirect, to cause the -# direction or management of such entity, whether by contract or -# otherwise, or (ii) ownership of fifty percent (50%) or more of the -# outstanding shares, or (iii) beneficial ownership of such entity. -# -# "You" (or "Your") shall mean an individual or Legal Entity -# exercising permissions granted by this License. -# -# "Source" form shall mean the preferred form for making modifications, -# including but not limited to software source code, documentation -# source, and configuration files. -# -# "Object" form shall mean any form resulting from mechanical -# transformation or translation of a Source form, including but -# not limited to compiled object code, generated documentation, -# and conversions to other media types. -# -# "Work" shall mean the work of authorship, whether in Source or -# Object form, made available under the License, as indicated by a -# copyright notice that is included in or attached to the work -# (an example is provided in the Appendix below). -# -# "Derivative Works" shall mean any work, whether in Source or Object -# form, that is based on (or derived from) the Work and for which the -# editorial revisions, annotations, elaborations, or other modifications -# represent, as a whole, an original work of authorship. For the purposes -# of this License, Derivative Works shall not include works that remain -# separable from, or merely link (or bind by name) to the interfaces of, -# the Work and Derivative Works thereof. -# -# "Contribution" shall mean any work of authorship, including -# the original version of the Work and any modifications or additions -# to that Work or Derivative Works thereof, that is intentionally -# submitted to Licensor for inclusion in the Work by the copyright owner -# or by an individual or Legal Entity authorized to submit on behalf of -# the copyright owner. For the purposes of this definition, "submitted" -# means any form of electronic, verbal, or written communication sent -# to the Licensor or its representatives, including but not limited to -# communication on electronic mailing lists, source code control systems, -# and issue tracking systems that are managed by, or on behalf of, the -# Licensor for the purpose of discussing and improving the Work, but -# excluding communication that is conspicuously marked or otherwise -# designated in writing by the copyright owner as "Not a Contribution." -# -# "Contributor" shall mean Licensor and any individual or Legal Entity -# on behalf of whom a Contribution has been received by Licensor and -# subsequently incorporated within the Work. -# -# 2. Grant of Copyright License. Subject to the terms and conditions of -# this License, each Contributor hereby grants to You a perpetual, -# worldwide, non-exclusive, no-charge, royalty-free, irrevocable -# copyright license to reproduce, prepare Derivative Works of, -# publicly display, publicly perform, sublicense, and distribute the -# Work and such Derivative Works in Source or Object form. -# -# 3. Grant of Patent License. Subject to the terms and conditions of -# this License, each Contributor hereby grants to You a perpetual, -# worldwide, non-exclusive, no-charge, royalty-free, irrevocable -# (except as stated in this section) patent license to make, have made, -# use, offer to sell, sell, import, and otherwise transfer the Work, -# where such license applies only to those patent claims licensable -# by such Contributor that are necessarily infringed by their -# Contribution(s) alone or by combination of their Contribution(s) -# with the Work to which such Contribution(s) was submitted. If You -# institute patent litigation against any entity (including a -# cross-claim or counterclaim in a lawsuit) alleging that the Work -# or a Contribution incorporated within the Work constitutes direct -# or contributory patent infringement, then any patent licenses -# granted to You under this License for that Work shall terminate -# as of the date such litigation is filed. -# -# 4. Redistribution. You may reproduce and distribute copies of the -# Work or Derivative Works thereof in any medium, with or without -# modifications, and in Source or Object form, provided that You -# meet the following conditions: -# -# (a) You must give any other recipients of the Work or -# Derivative Works a copy of this License; and -# -# (b) You must cause any modified files to carry prominent notices -# stating that You changed the files; and -# -# (c) You must retain, in the Source form of any Derivative Works -# that You distribute, all copyright, patent, trademark, and -# attribution notices from the Source form of the Work, -# excluding those notices that do not pertain to any part of -# the Derivative Works; and -# -# (d) If the Work includes a "NOTICE" text file as part of its -# distribution, then any Derivative Works that You distribute must -# include a readable copy of the attribution notices contained -# within such NOTICE file, excluding those notices that do not -# pertain to any part of the Derivative Works, in at least one -# of the following places: within a NOTICE text file distributed -# as part of the Derivative Works; within the Source form or -# documentation, if provided along with the Derivative Works; or, -# within a display generated by the Derivative Works, if and -# wherever such third-party notices normally appear. The contents -# of the NOTICE file are for informational purposes only and -# do not modify the License. You may add Your own attribution -# notices within Derivative Works that You distribute, alongside -# or as an addendum to the NOTICE text from the Work, provided -# that such additional attribution notices cannot be construed -# as modifying the License. -# -# You may add Your own copyright statement to Your modifications and -# may provide additional or different license terms and conditions -# for use, reproduction, or distribution of Your modifications, or -# for any such Derivative Works as a whole, provided Your use, -# reproduction, and distribution of the Work otherwise complies with -# the conditions stated in this License. -# -# 5. Submission of Contributions. Unless You explicitly state otherwise, -# any Contribution intentionally submitted for inclusion in the Work -# by You to the Licensor shall be under the terms and conditions of -# this License, without any additional terms or conditions. -# Notwithstanding the above, nothing herein shall supersede or modify -# the terms of any separate license agreement you may have executed -# with Licensor regarding such Contributions. -# -# 6. Trademarks. This License does not grant permission to use the trade -# names, trademarks, service marks, or product names of the Licensor, -# except as required for reasonable and customary use in describing the -# origin of the Work and reproducing the content of the NOTICE file. -# -# 7. Disclaimer of Warranty. Unless required by applicable law or -# agreed to in writing, Licensor provides the Work (and each -# Contributor provides its Contributions) on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied, including, without limitation, any warranties or conditions -# of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A -# PARTICULAR PURPOSE. You are solely responsible for determining the -# appropriateness of using or redistributing the Work and assume any -# risks associated with Your exercise of permissions under this License. -# -# 8. Limitation of Liability. In no event and under no legal theory, -# whether in tort (including negligence), contract, or otherwise, -# unless required by applicable law (such as deliberate and grossly -# negligent acts) or agreed to in writing, shall any Contributor be -# liable to You for damages, including any direct, indirect, special, -# incidental, or consequential damages of any character arising as a -# result of this License or out of the use or inability to use the -# Work (including but not limited to damages for loss of goodwill, -# work stoppage, computer failure or malfunction, or any and all -# other commercial damages or losses), even if such Contributor -# has been advised of the possibility of such damages. -# -# 9. Accepting Warranty or Additional Liability. While redistributing -# the Work or Derivative Works thereof, You may choose to offer, -# and charge a fee for, acceptance of support, warranty, indemnity, -# or other liability obligations and/or rights consistent with this -# License. However, in accepting such obligations, You may act only -# on Your own behalf and on Your sole responsibility, not on behalf -# of any other Contributor, and only if You agree to indemnify, -# defend, and hold each Contributor harmless for any liability -# incurred by, or claims asserted against, such Contributor by reason -# of your accepting any such warranty or additional liability. -# -# END OF TERMS AND CONDITIONS -# -# APPENDIX: How to apply the Apache License to your work. -# -# To apply the Apache License to your work, attach the following -# boilerplate notice, with the fields enclosed by brackets "[]" -# replaced with your own identifying information. (Don't include -# the brackets!) The text should be enclosed in the appropriate -# comment syntax for the file format. We also recommend that a -# file or class name and description of purpose be included on the -# same "printed page" as the copyright notice for easier -# identification within third-party archives. -# -# Copyright [yyyy] [name of copyright owner] -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/CMake/FindPCRE.cmake b/CMake/FindPCRE.cmake deleted file mode 100644 index dbbd60ada..000000000 --- a/CMake/FindPCRE.cmake +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2007-2009 LuaDist. -# Created by Peter Kapec -# Redistribution and use of this file is allowed according to the terms of the MIT license. -# For details see the COPYRIGHT file distributed with LuaDist. -# Note: -# Searching headers and libraries is very simple and is NOT as powerful as scripts -# distributed with CMake, because LuaDist defines directories to search for. -# Everyone is encouraged to contact the author with improvements. Maybe this file -# becomes part of CMake distribution sometimes. - -# - Find pcre -# Find the native PCRE headers and libraries. -# -# PCRE_INCLUDE_DIRS - where to find pcre.h, etc. -# PCRE_LIBRARIES - List of libraries when using pcre. -# PCRE_FOUND - True if pcre found. - -# Look for the header file. -FIND_PATH(PCRE_INCLUDE_DIR NAMES pcre.h) - -# Look for the library. -FIND_LIBRARY(PCRE_LIBRARY NAMES pcre) - -# Handle the QUIETLY and REQUIRED arguments and set PCRE_FOUND to TRUE if all listed variables are TRUE. -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY PCRE_INCLUDE_DIR) - -# Copy the results to the output variables. -IF(PCRE_FOUND) - SET(PCRE_LIBRARIES ${PCRE_LIBRARY}) - SET(PCRE_INCLUDE_DIRS ${PCRE_INCLUDE_DIR}) -ELSE(PCRE_FOUND) - SET(PCRE_LIBRARIES) - SET(PCRE_INCLUDE_DIRS) -ENDIF(PCRE_FOUND) - -MARK_AS_ADVANCED(PCRE_INCLUDE_DIRS PCRE_LIBRARIES) diff --git a/CMake/FindPango.cmake b/CMake/FindPango.cmake deleted file mode 100644 index eb296d755..000000000 --- a/CMake/FindPango.cmake +++ /dev/null @@ -1,42 +0,0 @@ -# - Try to find the pango library -# Once done this will define -# -# PANGO_FOUND - system has pango -# PANGO_INCLUDE_DIRS - the pango include directory -# PANGO_LIBRARIES - Link these to use pango -# -# Define PANGO_MIN_VERSION for which version desired. -# - -find_package(PkgConfig) - -if(Pango_FIND_REQUIRED) - set(_pkgconfig_REQUIRED "REQUIRED") -else(Pango_FIND_REQUIRED) - set(_pkgconfig_REQUIRED "") -endif(Pango_FIND_REQUIRED) - -if(PANGO_MIN_VERSION) - pkg_check_modules(PANGO ${_pkgconfig_REQUIRED} "pango>=${PANGO_MIN_VERSION}" "pangocairo>=${PANGO_MIN_VERSION}") -else(PANGO_MIN_VERSION) - pkg_check_modules(PANGO ${_pkgconfig_REQUIRED} pango pangocairo) -endif(PANGO_MIN_VERSION) - -if(NOT PANGO_FOUND AND NOT PKG_CONFIG_FOUND) - find_path(PANGO_INCLUDE_DIRS pango.h) - find_library(PANGO_LIBRARIES pango pangocairo) -else(NOT PANGO_FOUND AND NOT PKG_CONFIG_FOUND) - # Make paths absolute https://stackoverflow.com/a/35476270 - # Important on FreeBSD because /usr/local/lib is not on /usr/bin/ld's default path - set(PANGO_LIBS_ABSOLUTE) - foreach(lib ${PANGO_LIBRARIES}) - set(var_name PANGO_${lib}_ABS) - find_library(${var_name} ${lib} ${PANGO_LIBRARY_DIRS}) - list(APPEND PANGO_LIBS_ABSOLUTE ${${var_name}}) - endforeach() - set(PANGO_LIBRARIES ${PANGO_LIBS_ABSOLUTE}) -endif(NOT PANGO_FOUND AND NOT PKG_CONFIG_FOUND) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(PANGO DEFAULT_MSG PANGO_LIBRARIES PANGO_INCLUDE_DIRS) -mark_as_advanced(PANGO_LIBRARIES PANGO_INCLUDE_DIRS) diff --git a/CMake/FindWLC.cmake b/CMake/FindWLC.cmake deleted file mode 100644 index 15b26ce75..000000000 --- a/CMake/FindWLC.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# - Find wlc -# Find the wlc libraries -# -# This module defines the following variables: -# WLC_FOUND - True if wlc is found -# WLC_LIBRARIES - wlc libraries -# WLC_INCLUDE_DIRS - wlc include directories -# WLC_DEFINITIONS - Compiler switches required for using wlc -# - -find_package(PkgConfig) -pkg_check_modules(PC_WLC QUIET wlc) -find_path(WLC_INCLUDE_DIRS NAMES wlc/wlc.h HINTS ${PC_WLC_INCLUDE_DIRS}) -find_library(WLC_LIBRARIES NAMES wlc HINTS ${PC_WLC_LIBRARY_DIRS}) - -set(WLC_DEFINITIONS ${PC_WLC_CFLAGS_OTHER}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(wlc DEFAULT_MSG WLC_LIBRARIES WLC_INCLUDE_DIRS) -mark_as_advanced(WLC_LIBRARIES WLC_INCLUDE_DIRS) diff --git a/CMake/FindWayland.cmake b/CMake/FindWayland.cmake deleted file mode 100644 index 69130fe01..000000000 --- a/CMake/FindWayland.cmake +++ /dev/null @@ -1,67 +0,0 @@ -# Try to find Wayland on a Unix system -# -# This will define: -# -# WAYLAND_FOUND - True if Wayland is found -# WAYLAND_LIBRARIES - Link these to use Wayland -# WAYLAND_INCLUDE_DIR - Include directory for Wayland -# WAYLAND_DEFINITIONS - Compiler flags for using Wayland -# -# In addition the following more fine grained variables will be defined: -# -# WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES -# WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES -# WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES -# WAYLAND_CURSOR_FOUND WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES -# -# Copyright (c) 2013 Martin Gräßlin -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - -IF (NOT WIN32) - IF (WAYLAND_INCLUDE_DIR AND WAYLAND_LIBRARIES) - # In the cache already - SET(WAYLAND_FIND_QUIETLY TRUE) - ENDIF () - - # Use pkg-config to get the directories and then use these values - # in the FIND_PATH() and FIND_LIBRARY() calls - FIND_PACKAGE(PkgConfig) - PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor) - - SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS}) - - FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) - FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) - FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) - FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) - - FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) - FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) - FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) - FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) - - set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR}) - - set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES}) - - list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR) - - include(FindPackageHandleStandardArgs) - - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR) - - MARK_AS_ADVANCED( - WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES - WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES - WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES - WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES - WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES - ) - -ENDIF () diff --git a/CMake/FindWlroots.cmake b/CMake/FindWlroots.cmake deleted file mode 100644 index 0e349d3ac..000000000 --- a/CMake/FindWlroots.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# - Find wlroots -# Find the wlroots libraries -# -# This module defines the following variables: -# WLR_FOUND - True if wlroots is found -# WLR_LIBRARIES - wlroots libraries -# WLR_INCLUDE_DIRS - wlroots include directories -# WLR_DEFINITIONS - Compiler switches required for using wlroots -# - -find_package(PkgConfig) -pkg_check_modules(PC_WLR QUIET wlroots) -find_path(WLR_INCLUDE_DIRS NAMES wlr/config.h HINTS ${PC_WLR_INCLUDE_DIRS}) -find_library(WLR_LIBRARIES NAMES wlroots HINTS ${PC_WLR_LIBRARY_DIRS}) - -set(WLR_DEFINITIONS ${PC_WLR_CFLAGS_OTHER}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(wlr DEFAULT_MSG WLR_LIBRARIES WLR_INCLUDE_DIRS) -mark_as_advanced(WLR_LIBRARIES WLR_INCLUDE_DIRS) diff --git a/CMake/FindXKBCommon.cmake b/CMake/FindXKBCommon.cmake deleted file mode 100644 index 30ac503a6..000000000 --- a/CMake/FindXKBCommon.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# - Find XKBCommon -# Once done, this will define -# -# XKBCOMMON_FOUND - System has XKBCommon -# XKBCOMMON_INCLUDE_DIRS - The XKBCommon include directories -# XKBCOMMON_LIBRARIES - The libraries needed to use XKBCommon -# XKBCOMMON_DEFINITIONS - Compiler switches required for using XKBCommon - -find_package(PkgConfig) -pkg_check_modules(PC_XKBCOMMON QUIET xkbcommon) -find_path(XKBCOMMON_INCLUDE_DIRS NAMES xkbcommon/xkbcommon.h HINTS ${PC_XKBCOMMON_INCLUDE_DIRS}) -find_library(XKBCOMMON_LIBRARIES NAMES xkbcommon HINTS ${PC_XKBCOMMON_LIBRARY_DIRS}) - -set(XKBCOMMON_DEFINITIONS ${PC_XKBCOMMON_CFLAGS_OTHER}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(XKBCOMMON DEFAULT_MSG XKBCOMMON_LIBRARIES XKBCOMMON_INCLUDE_DIRS) -mark_as_advanced(XKBCOMMON_LIBRARIES XKBCOMMON_INCLUDE_DIRS) - diff --git a/CMake/Manpage.cmake b/CMake/Manpage.cmake deleted file mode 100644 index bbd6f2dcc..000000000 --- a/CMake/Manpage.cmake +++ /dev/null @@ -1,33 +0,0 @@ -find_package(A2X) - -if (A2X_FOUND) - add_custom_target(man ALL) - - function(add_manpage name section) - add_custom_command( - OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name}.${section} - COMMAND ${A2X_COMMAND} - --no-xmllint - --doctype manpage - --format manpage - -D ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - ${CMAKE_CURRENT_SOURCE_DIR}/${name}.${section}.txt - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.${section}.txt - COMMENT Generating manpage for ${name}.${section} - ) - - add_custom_target(man-${name}.${section} - DEPENDS - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name}.${section} - ) - add_dependencies(man - man-${name}.${section} - ) - - install( - FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name}.${section} - DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man${section} - COMPONENT documentation - ) - endfunction() -endif() diff --git a/CMake/Wayland.cmake b/CMake/Wayland.cmake deleted file mode 100644 index f93496678..000000000 --- a/CMake/Wayland.cmake +++ /dev/null @@ -1,77 +0,0 @@ -#============================================================================= -# Copyright (C) 2012-2013 Pier Luigi Fiorini -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# * Neither the name of Pier Luigi Fiorini nor the names of his -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#============================================================================= - -find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) - -# wayland_add_protocol_client(outfiles inputfile basename) -function(WAYLAND_ADD_PROTOCOL_CLIENT _sources _protocol _basename) - if(NOT WAYLAND_SCANNER_EXECUTABLE) - message(FATAL "The wayland-scanner executable has not been found on your system. You must install it.") - endif() - - get_filename_component(_infile ${_protocol} ABSOLUTE) - set(_client_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-client-protocol.h") - set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-client-protocol.c") - - add_custom_command(OUTPUT "${_client_header}" - COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header < ${_infile} > ${_client_header} - DEPENDS ${_infile} VERBATIM) - - add_custom_command(OUTPUT "${_code}" - COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code < ${_infile} > ${_code} - DEPENDS ${_infile} VERBATIM) - - list(APPEND ${_sources} "${_client_header}" "${_code}") - set(${_sources} ${${_sources}} PARENT_SCOPE) -endfunction() - -# wayland_add_protocol_server(outfiles inputfile basename) -function(WAYLAND_ADD_PROTOCOL_SERVER _sources _protocol _basename) - if(NOT WAYLAND_SCANNER_EXECUTABLE) - message(FATAL "The wayland-scanner executable has not been found on your system. You must install it.") - endif() - - get_filename_component(_infile ${_protocol} ABSOLUTE) - set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-server-protocol.h") - set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-server-protocol.c") - - add_custom_command(OUTPUT "${_server_header}" - COMMAND ${WAYLAND_SCANNER_EXECUTABLE} server-header < ${_infile} > ${_server_header} - DEPENDS ${_infile} VERBATIM) - - add_custom_command(OUTPUT "${_code}" - COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code < ${_infile} > ${_code} - DEPENDS ${_infile} VERBATIM) - - list(APPEND ${_sources} "${_server_header}" "${_code}") - set(${_sources} ${${_sources}} PARENT_SCOPE) -endfunction() diff --git a/README.md b/README.md index 215cee4f6..cfe513462 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ channel or shoot an email to sir@cmpwn.com for advice. Install dependencies: -* cmake +* meson * [wlroots](https://github.com/swaywm/wlroots) * wayland * xwayland @@ -78,11 +78,9 @@ _\*\*\*Only required for tray support_ Run these commands: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install On systems with logind, you need to set a few caps on the binary: diff --git a/protocols/CMakeLists.txt b/protocols/CMakeLists.txt deleted file mode 100644 index 8d8e58adc..000000000 --- a/protocols/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -include(Wayland) - -WAYLAND_ADD_PROTOCOL_CLIENT(proto-client-xdg-shell - xdg-shell.xml - xdg-shell -) -WAYLAND_ADD_PROTOCOL_CLIENT(proto-client-desktop-shell - desktop-shell.xml - desktop-shell -) -WAYLAND_ADD_PROTOCOL_SERVER(proto-server-desktop-shell - desktop-shell.xml - desktop-shell -) - -WAYLAND_ADD_PROTOCOL_CLIENT(proto-client-swaylock - swaylock.xml - swaylock -) -WAYLAND_ADD_PROTOCOL_SERVER(proto-server-swaylock - swaylock.xml - swaylock -) - -WAYLAND_ADD_PROTOCOL_SERVER(proto-server-gamma-control - gamma-control.xml - gamma-control -) - -WAYLAND_ADD_PROTOCOL_SERVER(proto-server-server-decoration - server-decoration.xml - server-decoration -) - -add_library(sway-protocols STATIC - ${proto-client-xdg-shell} - ${proto-client-desktop-shell} - ${proto-server-desktop-shell} - ${proto-client-swaylock} - ${proto-server-swaylock} - ${proto-server-gamma-control} - ${proto-server-server-decoration} - ) - -set(PROTOCOLS_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/protocols PARENT_SCOPE) -INCLUDE_DIRECTORIES(${WAYLAND_INCLUDE_DIR} ${XKBCOMMON_INCLUDE_DIRS}) diff --git a/swaybar/CMakeLists.txt b/swaybar/CMakeLists.txt deleted file mode 100644 index 48ededddb..000000000 --- a/swaybar/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -include_directories( - ${PROTOCOLS_INCLUDE_DIRS} - ${WAYLAND_INCLUDE_DIR} - ${CAIRO_INCLUDE_DIRS} - ${PANGO_INCLUDE_DIRS} - ${JSONC_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} - ${DBUS_INCLUDE_DIRS} -) -if (ENABLE_TRAY) - file(GLOB tray - tray/*.c - ) -endif() - -add_executable(swaybar - main.c - config.c - render.c - bar.c - status_line.c - ipc.c - event_loop.c - ${tray} -) - -target_link_libraries(swaybar - sway-common - sway-wayland - ${WAYLAND_CLIENT_LIBRARIES} - ${WAYLAND_CURSOR_LIBRARIES} - ${CAIRO_LIBRARIES} - ${PANGO_LIBRARIES} - ${JSONC_LIBRARIES} - ${DBUS_LIBRARIES} -) - -if (WITH_GDK_PIXBUF) - include_directories( - ${GDK_PIXBUF_INCLUDE_DIRS} - ) -endif() - -target_link_libraries(swaybar rt) - -install( - TARGETS swaybar - RUNTIME - DESTINATION bin - COMPONENT runtime -) diff --git a/swaybg/CMakeLists.txt b/swaybg/CMakeLists.txt deleted file mode 100644 index f8cad4049..000000000 --- a/swaybg/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -include_directories( - ${PROTOCOLS_INCLUDE_DIRS} - ${WAYLAND_INCLUDE_DIR} - ${CAIRO_INCLUDE_DIRS} - ${PANGO_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} -) - -add_executable(swaybg - main.c -) - -target_link_libraries(swaybg - sway-common - sway-wayland - ${WAYLAND_CLIENT_LIBRARIES} - ${WAYLAND_CURSOR_LIBRARIES} - ${CAIRO_LIBRARIES} - ${PANGO_LIBRARIES} - m -) - -if (WITH_GDK_PIXBUF) - include_directories( - ${GDK_PIXBUF_INCLUDE_DIRS} - ) - target_link_libraries(swaybg - ${GDK_PIXBUF_LIBRARIES} - ) -endif() - -install( - TARGETS swaybg - RUNTIME - DESTINATION bin - COMPONENT runtime -) diff --git a/swaygrab/CMakeLists.txt b/swaygrab/CMakeLists.txt deleted file mode 100644 index 42806caed..000000000 --- a/swaygrab/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -include_directories( - ${JSONC_INCLUDE_DIRS} - ${WLC_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} -) - -add_executable(swaygrab - main.c - json.c -) - -target_link_libraries(swaygrab - sway-common - ${JSONC_LIBRARIES} - rt - m -) - -install( - TARGETS swaygrab - RUNTIME - DESTINATION bin - COMPONENT runtime -) - -if (A2X_FOUND) - add_manpage(swaygrab 1) -endif() diff --git a/swaylock/CMakeLists.txt b/swaylock/CMakeLists.txt deleted file mode 100644 index 90b54a727..000000000 --- a/swaylock/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -include_directories( - ${PROTOCOLS_INCLUDE_DIRS} - ${WAYLAND_INCLUDE_DIR} - ${CAIRO_INCLUDE_DIRS} - ${PANGO_INCLUDE_DIRS} - ${PAM_INCLUDE_DIRS} - ${JSONC_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} -) - -add_executable(swaylock - main.c -) - -target_link_libraries(swaylock - sway-common - sway-wayland - ${WAYLAND_CLIENT_LIBRARIES} - ${WAYLAND_CURSOR_LIBRARIES} - ${CAIRO_LIBRARIES} - ${PANGO_LIBRARIES} - ${PAM_LIBRARIES} - ${JSONC_LIBRARIES} - m -) - -if (WITH_GDK_PIXBUF) - include_directories( - ${GDK_PIXBUF_INCLUDE_DIRS} - ) - target_link_libraries(swaylock - ${GDK_PIXBUF_LIBRARIES} - ) -endif() - -install( - TARGETS swaylock - RUNTIME - DESTINATION bin - COMPONENT runtime -) - -install( - FILES ${CMAKE_CURRENT_SOURCE_DIR}/pam/swaylock - DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d/ - COMPONENT data -) - -if (A2X_FOUND) - add_manpage(swaylock 1) -endif() diff --git a/wayland/CMakeLists.txt b/wayland/CMakeLists.txt deleted file mode 100644 index 91fd7fff8..000000000 --- a/wayland/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -include_directories( - ${PROTOCOLS_INCLUDE_DIRS} - ${PANGO_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} - ${WAYLAND_INCLUDE_DIR} - ${EPOLLSHIM_INCLUDE_DIRS} -) - -add_library(sway-wayland STATIC - buffers.c - pango.c - registry.c - window.c - cairo.c - ) - -target_link_libraries(sway-wayland - sway-common - sway-protocols - ${PANGO_LIBRARIES} - ${XKBCOMMON_LIBRARIES} - ${EPOLLSHIM_LIBRARIES} - ) - -if (WITH_GDK_PIXBUF) - include_directories( - ${GDK_PIXBUF_INCLUDE_DIRS} - ) - target_link_libraries(sway-wayland - ${GDK_PIXBUF_LIBRARIES} - ) -endif() From da0dd16ffaaa047ca83e3feaf0f785cc4ff8d273 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 1 Dec 2017 05:22:49 -0500 Subject: [PATCH 039/522] update readmes for meson --- README.de.md | 10 ++++------ README.el.md | 10 ++++------ README.fr.md | 10 ++++------ README.it.md | 10 ++++------ README.ja.md | 10 ++++------ README.pt.md | 10 ++++------ README.ru.md | 10 ++++------ README.uk.md | 10 ++++------ 8 files changed, 32 insertions(+), 48 deletions(-) diff --git a/README.de.md b/README.de.md index 701cc34fc..47084ad34 100644 --- a/README.de.md +++ b/README.de.md @@ -52,7 +52,7 @@ schau im IRC-Channel vorbei oder schreibe eine e-Mail an sir@cmpwn.com (nur engl Abhängigkeiten: -* cmake +* meson * [wlc](https://github.com/Cloudef/wlc) * wayland * xwayland @@ -74,11 +74,9 @@ _\*\*Nur erforderlich für swaylock_ Führe diese Befehle aus: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install In Systemen mit logind musst du `sway` einige Capabilities geben: diff --git a/README.el.md b/README.el.md index df39364fe..dd1889e43 100644 --- a/README.el.md +++ b/README.el.md @@ -45,7 +45,7 @@ To username μου στο Freenode είναι kon14 και θα με βρείτ Εγκατάσταση εξαρτήσεων: -* cmake +* meson * [wlc](https://github.com/Cloudef/wlc) * wayland * xwayland @@ -67,11 +67,9 @@ _\*\*Απαιτείται μόνο για swaylock_ Εκτελέστε αυτές τις εντολές: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install Σε συστήματα με logind, χρειάζεται να ορίσετε μερικά δικαιώματα caps στο εκτελέσιμο αρχείο: diff --git a/README.fr.md b/README.fr.md index 47b6c4101..5baee7a8e 100644 --- a/README.fr.md +++ b/README.fr.md @@ -47,7 +47,7 @@ IRC ou envoyez un e-mail à sir@cmpwn.com (en anglais seulement) pour des consei Installez les dépendances : -* cmake +* meson * [wlc](https://github.com/Cloudef/wlc) * wayland * xwayland @@ -69,11 +69,9 @@ _\*\*Uniquement requis pour swaylock_ Exécutez ces commandes : - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install Sur les systèmes avec logind, vous devez définir quelques caps sur le binaire : diff --git a/README.it.md b/README.it.md index f5e0d8e2d..af3444050 100644 --- a/README.it.md +++ b/README.it.md @@ -48,7 +48,7 @@ a sir@cmpwn.com. Installa queste dipendenze: -* cmake +* meson * [wlc](https://github.com/Cloudef/wlc) * wayland * xwayland @@ -70,11 +70,9 @@ _\*\*Richiesto solo per swaylock_ Esegui questi comandi: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install Per i sistemi con logind, devi impostare un paio di caps sull'eseguibile: diff --git a/README.ja.md b/README.ja.md index 2e8f9bfbc..cf89971cd 100644 --- a/README.ja.md +++ b/README.ja.md @@ -38,7 +38,7 @@ Swayは沢山のディストリビューションで提供されています。" 次の依存パッケージをインストールしてください: -* cmake +* meson * [wlc](https://github.com/Cloudef/wlc) * wayland * xwayland @@ -60,11 +60,9 @@ _\*\*swaylockでのみ必要です_ 次のコマンドを実行してください: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install logindを使用しているシステムでは、バイナリにいくつかのケーパビリティを設定する必要があります: diff --git a/README.pt.md b/README.pt.md index b5ca132f2..ff51ac2c1 100644 --- a/README.pt.md +++ b/README.pt.md @@ -54,7 +54,7 @@ visite o canal no IRC ou mande um email para sir@cmpwn.com (*em inglês*). Antes de iniciar a compilação, instale as dependências: -* cmake +* meson * [wlc](https://github.com/Cloudef/wlc) * wayland * xwayland @@ -76,11 +76,9 @@ _\*\*Dependência apenas de swaylock_ Para compilar, execute estes comandos: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install Em sistemas com logind, configure as seguintes capacidades para o arquivo binário: diff --git a/README.ru.md b/README.ru.md index 4035b0fc9..12890d2d0 100644 --- a/README.ru.md +++ b/README.ru.md @@ -47,7 +47,7 @@ Sway доступен во многих дистрибутивах и наход Установите следующие пакеты: -* cmake +* meson * [wlc](https://github.com/Cloudef/wlc) * wayland * xwayland @@ -69,11 +69,9 @@ _\*\*Требуется только для swaylock_ Выполните следующие команды: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install Если у вас logind: diff --git a/README.uk.md b/README.uk.md index 2e107afc5..37a33e4cf 100644 --- a/README.uk.md +++ b/README.uk.md @@ -54,7 +54,7 @@ Sway доступний у багатьох дистрибутивах Linux (а Встановіть залежності: -* cmake +* meson * [wlc](https://github.com/Cloudef/wlc) * wayland * xwayland @@ -76,11 +76,9 @@ _\*\*Лише для swaylock_ Виконайте ці команди: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. - make - sudo make install + meson build + ninja -C build + sudo ninja -C build install На системах **з** logind, варто встановити декілька можливостей (caps) на виконуваний файл sway: From 08954a0910efd712b211f8c13583020959188d2d Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 1 Dec 2017 05:23:53 -0500 Subject: [PATCH 040/522] update hacking for meson --- HACKING.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/HACKING.md b/HACKING.md index cf18dbb04..3600db242 100644 --- a/HACKING.md +++ b/HACKING.md @@ -22,14 +22,3 @@ assertion fails. Outside of the compositor (swaymsg, swaybar, etc), using `assert.h` is permitted. - -## Building against a local wlc - -1. Build wlc as described [here](https://github.com/Cloudef/wlc#building) -2. Inside your sway source folder, tell `cmake` to use your local version of wlc: - -```bash -cmake \ - -DWLC_LIBRARIES=path/to/wlc/target/src/libwlc.so \ - -DWLC_INCLUDE_DIRS=path/to/wlc/include . -``` From 0f7a7f4084487d846100119b13b26a63ffe9b437 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 1 Dec 2017 05:42:12 -0500 Subject: [PATCH 041/522] meson dont warn on unused param --- meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meson.build b/meson.build index 05d92a914..695e237e7 100644 --- a/meson.build +++ b/meson.build @@ -9,6 +9,8 @@ project( ], ) +add_project_arguments('-Wno-unused-parameter', language: 'c') + cc = meson.get_compiler('c') is_freebsd = host_machine.system().startswith('freebsd') From 3546412fc9fb9a51b4316070eff4991c14594127 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 1 Dec 2017 05:43:08 -0500 Subject: [PATCH 042/522] update travis --- .build.yml | 21 +++++++++------------ .travis.yml | 26 ++++++++++---------------- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/.build.yml b/.build.yml index 3717d6990..a2f855e94 100644 --- a/.build.yml +++ b/.build.yml @@ -1,7 +1,7 @@ # vim: ft=yaml ts=2 sw=2 et : image: archlinux packages: - - cmake + - meson - wlc-git - xorg-server-xwayland - xcb-util-image @@ -9,25 +9,22 @@ packages: - pango - cairo - wayland + - wayland-protocols - gdk-pixbuf2 - - meson + - libinput + - libxkbcommon sources: - https://git.sr.ht/~sircmpwn/sway - https://git.sr.ht/~sircmpwn/wlroots tasks: - wlroots: | cd wlroots - mkdir build - cd build - meson --prefix=/usr .. - ninja - sudo ninja install + meson --prefix=/usr build + ninja -C build + sudo ninja -C build install - setup: | cd sway - mkdir build - cd build - cmake .. + meson build - build: | cd sway - cd build - make + ninja -C build diff --git a/.travis.yml b/.travis.yml index bc1ee45b8..db7177188 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,35 +7,29 @@ compiler: - clang env: - - BUILD_TYPE=Release - - BUILD_TYPE=Debug - - BUILD_TYPE=ASAN + - BUILD_TYPE=release + - BUILD_TYPE=debug arch: packages: - - cmake + - meson + - ninja - xorg-server-xwayland - json-c - wayland + - wayland-protocols - xcb-util-image - pango - cairo - gdk-pixbuf2 - - wlc-git - libcap - - meson + - libinput + - libxkbcommon script: - git clone https://github.com/swaywm/wlroots - - cd wlroots - - mkdir build - - cd build - - meson --prefix=/usr .. - - sudo ninja install - - cd ../.. - - cmake . - - make - - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . - - make + - 'cd wlroots && meson --prefix=/usr build && ninja -C build && sudo ninja -C build install' + - meson build --buildtype=$BUILD_TYPE + - ninja -C build script: - "curl -s https://raw.githubusercontent.com/mikkeloscar/arch-travis/master/arch-travis.sh | bash" From 31e44c01b454ca2938e856c0f07dce2f9a665be3 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 1 Dec 2017 07:15:34 -0500 Subject: [PATCH 043/522] send callbacks with send_frame_done --- sway/desktop/output.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 169b044b4..6b9822c1f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -72,12 +72,7 @@ static void output_frame_view(swayc_t *view, void *data) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - struct wlr_frame_callback *cb, *cnext; - wl_list_for_each_safe(cb, cnext, - &surface->current->frame_callback_list, link) { - wl_callback_send_done(cb->resource, timespec_to_msec(&now)); - wl_resource_destroy(cb->resource); - } + wlr_surface_send_frame_done(surface, &now); } static void output_frame_notify(struct wl_listener *listener, void *data) { From 7152075681ffd2199119075eca68072bc364d519 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 2 Dec 2017 07:49:23 -0500 Subject: [PATCH 044/522] log env after ipc init --- sway/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/main.c b/sway/main.c index c65d175b2..bc1073094 100644 --- a/sway/main.c +++ b/sway/main.c @@ -366,7 +366,6 @@ int main(int argc, char **argv) { log_kernel(); log_distro(); - log_env(); detect_proprietary(); detect_raspi(); @@ -387,6 +386,7 @@ int main(int argc, char **argv) { init_layout(); ipc_init(&server); + log_env(); //if (validate) { // bool valid = load_main_config(config_path, false); From 421f49fe034cc8a48348ba57af8fdf3f98adb62c Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 3 Dec 2017 08:33:52 -0500 Subject: [PATCH 045/522] basic get_tree --- include/sway/ipc-json.h | 3 ++ sway/ipc-json.c | 91 +++++++++++++++++++++++++++++++++++++++++ sway/ipc-server.c | 10 +++++ 3 files changed, 104 insertions(+) diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index 5bfddcba9..9986c399f 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -1,7 +1,10 @@ #ifndef _SWAY_IPC_JSON_H #define _SWAY_IPC_JSON_H #include +#include "sway/container.h" json_object *ipc_json_get_version(); +json_object *ipc_json_describe_container_recursive(swayc_t *c); + #endif diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 6fcb91fa4..2e774a964 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1,6 +1,11 @@ #include #include +#include +#include "log.h" #include "sway/ipc-json.h" +#include "sway/container.h" +#include +#include json_object *ipc_json_get_version() { int major = 0, minor = 0, patch = 0; @@ -16,3 +21,89 @@ json_object *ipc_json_get_version() { return version; } + +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)); + json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); + json_object_object_add(rect, "width", json_object_new_int((int32_t)c->width)); + json_object_object_add(rect, "height", json_object_new_int((int32_t)c->height)); + + return rect; +} + +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")); +} + +static void ipc_json_describe_output(swayc_t *output, json_object *object) { + json_object_object_add(object, "type", json_object_new_string("output")); + json_object_object_add(object, "current_workspace", + (output->focused) ? json_object_new_string(output->focused->name) : NULL); +} + +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)); + json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL); + json_object_object_add(object, "type", json_object_new_string("workspace")); +} + +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(swayc_t *c) { + if (!(sway_assert(c, "Container must not be null."))) { + return NULL; + } + + json_object *object = json_object_new_object(); + + json_object_object_add(object, "id", json_object_new_int((int)c->id)); + json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); + json_object_object_add(object, "rect", ipc_json_create_rect(c)); + + switch (c->type) { + case C_ROOT: + ipc_json_describe_root(c, object); + break; + + case C_OUTPUT: + ipc_json_describe_output(c, object); + break; + + case C_CONTAINER: + case C_VIEW: + ipc_json_describe_view(c, object); + break; + + case C_WORKSPACE: + ipc_json_describe_workspace(c, object); + break; + + case C_TYPES: + default: + break; + } + + return object; +} + +json_object *ipc_json_describe_container_recursive(swayc_t *c) { + json_object *object = ipc_json_describe_container(c); + int i; + + json_object *children = json_object_new_array(); + if (c->type != C_VIEW && c->children) { + for (i = 0; i < c->children->length; ++i) { + json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); + } + } + json_object_object_add(object, "nodes", children); + + return object; +} diff --git a/sway/ipc-server.c b/sway/ipc-server.c index f3a6469ba..71f8dddd6 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -343,6 +343,16 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_TREE: + { + json_object *tree = + ipc_json_describe_container_recursive(&root_container); + const char *json_string = json_object_to_json_string(tree); + ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); + json_object_put(tree); + goto exit_cleanup; + } + case IPC_GET_VERSION: { json_object *version = ipc_json_get_version(); From 9220225f1df384085b0fe80089b06d5ba1f290de Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 3 Dec 2017 08:42:47 -0500 Subject: [PATCH 046/522] remove unused timespec_to_msec --- sway/desktop/output.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6b9822c1f..7eb48bdf0 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -13,10 +13,6 @@ #include "sway/server.h" #include "sway/view.h" -static inline int64_t timespec_to_msec(const struct timespec *a) { - return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; -} - static void output_frame_view(swayc_t *view, void *data) { struct sway_output *output = data; struct wlr_output *wlr_output = output->wlr_output; From 59db38ce17e04b19c25e06f0fd3622b2adace99f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 3 Dec 2017 10:49:13 -0500 Subject: [PATCH 047/522] sway wl_shell --- include/sway/server.h | 1 + include/sway/view.h | 5 +++-- sway/desktop/wl_shell.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 sway/desktop/wl_shell.c diff --git a/include/sway/server.h b/include/sway/server.h index b0684d15d..1901e39f6 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -42,5 +42,6 @@ void output_add_notify(struct wl_listener *listener, void *data); void output_remove_notify(struct wl_listener *listener, void *data); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); +void handle_wl_shell_surface(struct wl_listener *listener, void *data); #endif diff --git a/include/sway/view.h b/include/sway/view.h index 2707ca787..77d451e55 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -29,9 +29,8 @@ enum sway_view_type { enum sway_view_prop { VIEW_PROP_TITLE, - VIEW_PROP_CLASS, - VIEW_PROP_INSTANCE, VIEW_PROP_APP_ID, + VIEW_PROP_INSTANCE, }; /** @@ -46,10 +45,12 @@ struct sway_view { union { struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; + struct wlr_wl_shell_surface *wlr_wl_shell_surface; }; union { struct sway_xdg_surface_v6 *sway_xdg_surface_v6; + struct sway_wl_shell_surface *sway_wl_shell_surface; }; struct { diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c new file mode 100644 index 000000000..8bfa605eb --- /dev/null +++ b/sway/desktop/wl_shell.c @@ -0,0 +1,30 @@ +#define _POSIX_C_SOURCE 199309L +#include +#include +#include +#include +#include "sway/container.h" +#include "sway/layout.h" +#include "sway/server.h" +#include "sway/view.h" +#include "log.h" + +static bool assert_wl_shell(struct sway_view *view) { + return sway_assert(view->type == SWAY_WL_SHELL_VIEW, + "Expecting wl_shell view!"); +} + +static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { + if (!assert_wl_shell(view)) { + return NULL; + } + switch (prop) { + case VIEW_PROP_TITLE: + return view->wlr_wl_shell_surface->title; + case VIEW_PROP_APP_ID: + return view->wlr_wl_shell_surface->class; + default: + return NULL; + } +} + From 802e7392f89a1e401a3953099ac5d477a461e469 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 3 Dec 2017 11:01:44 -0500 Subject: [PATCH 048/522] use "size" instead of "dimensions" --- include/sway/view.h | 2 +- sway/desktop/xdg_shell_v6.c | 4 ++-- sway/sway.5.txt | 23 +++++++++++------------ sway/tree/layout.c | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/include/sway/view.h b/include/sway/view.h index 2707ca787..cf2e6f66d 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -55,7 +55,7 @@ struct sway_view { struct { const char *(*get_prop)(struct sway_view *view, enum sway_view_prop prop); - void (*set_dimensions)(struct sway_view *view, + void (*set_size)(struct sway_view *view, int width, int height); } iface; }; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 45e443fcf..2545d1a68 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -28,7 +28,7 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } } -static void set_dimensions(struct sway_view *view, int width, int height) { +static void set_size(struct sway_view *view, int width, int height) { if (!assert_xdg(view)) { return; } @@ -86,7 +86,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { } sway_view->type = SWAY_XDG_SHELL_V6_VIEW; sway_view->iface.get_prop = get_prop; - sway_view->iface.set_dimensions = set_dimensions; + sway_view->iface.set_size = set_size; 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/sway.5.txt b/sway/sway.5.txt index 750254c8f..2a4ef2056 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -126,22 +126,21 @@ They are expected to be used with **bindsym** or at runtime through **swaymsg**( **resize** [] [px|ppt]:: Resizes the currently focused container or view by _amount_. _amount_ is - optional: the default value is 10 (either px or ppt depending on the view - type). The [px|ppt] parameter is optional. _px_ specifies that _amount_ refers - to pixels; _ppt_ specifies that _amount_ refers to percentage points of the - current dimension. Floating views use px dimensions by default (but can use - ppt if specified); tiled views use ppt dimensions by default (but can use px - if specified). + optional: the default value is 10 (either px or ppt depending on the view type). + The [px|ppt] parameter is optional. _px_ specifies that _amount_ refers to pixels; + _ppt_ specifies that _amount_ refers to percentage points of the current + size. Floating views use px by default (but can use ppt if specified); tiled + views use ppt by default (but can use px if specified). **resize set** [px] [px]:: Sets the width and height of the currently focused container to _width_ pixels and _height_ pixels. The [px] parameters are optional and have no effect. This - command only accepts pixel dimensions. + command only accepts a size in pixels. **resize set** [px] [ [px]]:: Sets the _width_ and/or _height_ of the currently focused container to _amount_. The [px] parameters are optional and have no effect. This command - only accepts pixel dimensions. + only accepts a size in pixels. **scratchpad show**:: Shows a window from the scratchpad. Repeatedly using this command will cycle @@ -254,14 +253,14 @@ The default colors are: *restart* is executed. **floating_maximum_size** x :: - Specifies the maximum dimensions of floating windows. - Uses the container dimensions as default. - -1 x -1 will remove any restriction on dimensions. + Specifies the maximum size of floating windows. + Uses the container size as default. + -1 x -1 will remove any restriction on size. 0 x 0 has the same behavior as not setting any value. If in conflict, this option has precedence over floating_minimum_size. **floating_minimum_size** x :: - Specifies the minimum dimensions of floating windows. + Specifies the minimum size of floating windows. Default parameters are 75 x 50. -1 and 0 are invalid parameters, default will be used instead. diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ea7bb8bbf..2d442f2a4 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -155,7 +155,7 @@ void arrange_windows(swayc_t *container, double width, double height) { { container->width = width; container->height = height; - container->sway_view->iface.set_dimensions(container->sway_view, + container->sway_view->iface.set_size(container->sway_view, container->width, container->height); sway_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", container->width, container->height, From 8239067da42545a59dbb43b941f69470d501f544 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 3 Dec 2017 14:21:26 -0500 Subject: [PATCH 049/522] basic wl-shell --- include/sway/server.h | 3 ++ include/sway/view.h | 12 ++++++ sway/desktop/wl_shell.c | 85 +++++++++++++++++++++++++++++++++++++++++ sway/meson.build | 1 + sway/server.c | 6 +++ 5 files changed, 107 insertions(+) diff --git a/include/sway/server.h b/include/sway/server.h index 1901e39f6..bfdb7b8a0 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -30,6 +30,9 @@ struct sway_server { struct wlr_xdg_shell_v6 *xdg_shell_v6; struct wl_listener xdg_shell_v6_surface; + + struct wlr_wl_shell *wl_shell; + struct wl_listener wl_shell_surface; }; struct sway_server server; diff --git a/include/sway/view.h b/include/sway/view.h index 77d451e55..22f5ccf9b 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -19,6 +19,18 @@ struct sway_xdg_surface_v6 { 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, diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 8bfa605eb..3a349425f 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -28,3 +28,88 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } } +static void set_dimensions(struct sway_view *view, int width, int height) { + if (!assert_wl_shell(view)) { + return; + } + view->sway_wl_shell_surface->pending_width = width; + view->sway_wl_shell_surface->pending_height = height; + wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); +} + +static void handle_commit(struct wl_listener *listener, void *data) { + struct sway_wl_shell_surface *sway_surface = + wl_container_of(listener, sway_surface, commit); + struct sway_view *view = sway_surface->view; + sway_log(L_DEBUG, "wl_shell surface commit %dx%d", + sway_surface->pending_width, sway_surface->pending_height); + // NOTE: We intentionally discard the view's desired width here + // TODO: Let floating views do whatever + view->width = sway_surface->pending_width; + view->height = sway_surface->pending_height; +} + +static void handle_destroy(struct wl_listener *listener, void *data) { + struct sway_wl_shell_surface *sway_surface = + 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); + free(sway_surface->view); + free(sway_surface); + arrange_windows(parent, -1, -1); +} + +void handle_wl_shell_surface(struct wl_listener *listener, void *data) { + struct sway_server *server = wl_container_of( + listener, server, wl_shell_surface); + struct wlr_wl_shell_surface *shell_surface = data; + + if (shell_surface->state != WLR_WL_SHELL_SURFACE_STATE_TOPLEVEL) { + // TODO: transient and popups should be floating + return; + } + + sway_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", + shell_surface->title, shell_surface->class); + wlr_wl_shell_surface_ping(shell_surface); + + struct sway_wl_shell_surface *sway_surface = + calloc(1, sizeof(struct sway_wl_shell_surface)); + if (!sway_assert(sway_surface, "Failed to allocate surface!")) { + return; + } + + struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); + if (!sway_assert(sway_view, "Failed to allocate view!")) { + return; + } + sway_view->type = SWAY_WL_SHELL_VIEW; + sway_view->iface.get_prop = get_prop; + sway_view->iface.set_dimensions = set_dimensions; + sway_view->wlr_wl_shell_surface = shell_surface; + sway_view->sway_wl_shell_surface = sway_surface; + sway_view->surface = shell_surface->surface; + sway_surface->view = sway_view; + + // TODO: + // - Wire up listeners + // - Handle popups + // - Look up pid and open on appropriate workspace + // - Set new view to maximized so it behaves nicely + // - Criteria + + sway_surface->commit.notify = handle_commit; + wl_signal_add(&shell_surface->events.commit, &sway_surface->commit); + sway_surface->destroy.notify = handle_destroy; + wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); + + // TODO: actual focus semantics + swayc_t *parent = root_container.children->items[0]; + parent = parent->children->items[0]; // workspace + + swayc_t *cont = new_view(parent, sway_view); + sway_view->swayc = cont; + + arrange_windows(cont->parent, -1, -1); +} diff --git a/sway/meson.build b/sway/meson.build index cf2aa9137..dd3570bfb 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -6,6 +6,7 @@ sway_sources = files( 'ipc-json.c', 'ipc-server.c', 'desktop/output.c', + 'desktop/wl_shell.c', 'desktop/xdg_shell_v6.c', 'tree/container.c', 'tree/layout.c', diff --git a/sway/server.c b/sway/server.c index 6e66bc3ca..bf5c37eb3 100644 --- a/sway/server.c +++ b/sway/server.c @@ -7,6 +7,7 @@ #include #include #include +#include // TODO WLR: make Xwayland optional #include #include "sway/server.h" @@ -40,6 +41,11 @@ bool server_init(struct sway_server *server) { &server->xdg_shell_v6_surface); server->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface; + server->wl_shell = wlr_wl_shell_create(server->wl_display); + wl_signal_add(&server->wl_shell->events.new_surface, + &server->wl_shell_surface); + server->wl_shell_surface.notify = handle_wl_shell_surface; + server->socket = wl_display_add_socket_auto(server->wl_display); if (!sway_assert(server->socket, "Unable to open wayland socket")) { wlr_backend_destroy(server->backend); From 6a694853e5b65ab44b1b83572cc0f1c0ad8da960 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 3 Dec 2017 14:23:23 -0500 Subject: [PATCH 050/522] wl-shell: dimensions to size --- sway/desktop/wl_shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 3a349425f..e7b42fce7 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -28,7 +28,7 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } } -static void set_dimensions(struct sway_view *view, int width, int height) { +static void set_size(struct sway_view *view, int width, int height) { if (!assert_wl_shell(view)) { return; } @@ -86,7 +86,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { } sway_view->type = SWAY_WL_SHELL_VIEW; sway_view->iface.get_prop = get_prop; - sway_view->iface.set_dimensions = set_dimensions; + sway_view->iface.set_size = set_size; sway_view->wlr_wl_shell_surface = shell_surface; sway_view->sway_wl_shell_surface = sway_surface; sway_view->surface = shell_surface->surface; From 9afcfd44c425691180a96d4e0d6673e5ac96dcce Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 3 Dec 2017 17:00:17 -0500 Subject: [PATCH 051/522] wl-shell: class instead of app_id --- include/sway/view.h | 1 + sway/desktop/wl_shell.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/sway/view.h b/include/sway/view.h index f87a8d5bb..7aa04794a 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -42,6 +42,7 @@ enum sway_view_type { enum sway_view_prop { VIEW_PROP_TITLE, VIEW_PROP_APP_ID, + VIEW_PROP_CLASS, VIEW_PROP_INSTANCE, }; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index e7b42fce7..9641b9113 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -21,7 +21,7 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { switch (prop) { case VIEW_PROP_TITLE: return view->wlr_wl_shell_surface->title; - case VIEW_PROP_APP_ID: + case VIEW_PROP_CLASS: return view->wlr_wl_shell_surface->class; default: return NULL; From 1870f116ba355fd02c8cc235fe262ccb0a03976b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 4 Dec 2017 06:19:36 -0500 Subject: [PATCH 052/522] xwayland shell --- include/sway/server.h | 4 ++ include/sway/view.h | 16 +++++ sway/desktop/xwayland.c | 134 ++++++++++++++++++++++++++++++++++++++++ sway/meson.build | 1 + sway/server.c | 7 +++ 5 files changed, 162 insertions(+) create mode 100644 sway/desktop/xwayland.c diff --git a/include/sway/server.h b/include/sway/server.h index b0684d15d..30b15e758 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -30,6 +30,9 @@ struct sway_server { struct wlr_xdg_shell_v6 *xdg_shell_v6; struct wl_listener xdg_shell_v6_surface; + + struct wlr_xwayland *xwayland; + struct wl_listener xwayland_surface; }; struct sway_server server; @@ -42,5 +45,6 @@ void output_add_notify(struct wl_listener *listener, void *data); void output_remove_notify(struct wl_listener *listener, void *data); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); +void handle_xwayland_surface(struct wl_listener *listener, void *data); #endif diff --git a/include/sway/view.h b/include/sway/view.h index cf2e6f66d..2d9b4ef53 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -3,6 +3,7 @@ #include #include #include +#include struct sway_container; struct sway_view; @@ -19,6 +20,19 @@ struct sway_xdg_surface_v6 { 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 destroy; + + int pending_width, pending_height; +}; + enum sway_view_type { SWAY_WL_SHELL_VIEW, SWAY_XDG_SHELL_V6_VIEW, @@ -46,10 +60,12 @@ struct sway_view { union { struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; + struct wlr_xwayland_surface *wlr_xwayland_surface; }; union { struct sway_xdg_surface_v6 *sway_xdg_surface_v6; + struct sway_xwayland_surface *sway_xwayland_surface; }; struct { diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c new file mode 100644 index 000000000..04ec118d0 --- /dev/null +++ b/sway/desktop/xwayland.c @@ -0,0 +1,134 @@ +#define _POSIX_C_SOURCE 199309L +#include +#include +#include +#include +#include "sway/container.h" +#include "sway/layout.h" +#include "sway/server.h" +#include "sway/view.h" +#include "log.h" + + static bool assert_xwayland(struct sway_view *view) { + return sway_assert(view->type == SWAY_XWAYLAND_VIEW, + "Expected xwayland view!"); + } + +static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { + if (!assert_xwayland(view)) { + return NULL; + } + switch (prop) { + case VIEW_PROP_TITLE: + return view->wlr_xwayland_surface->title; + case VIEW_PROP_CLASS: + return view->wlr_xwayland_surface->class; + default: + return NULL; + } +} + +static void set_size(struct sway_view *view, int width, int height) { + if (!assert_xwayland(view)) { + return; + } + view->sway_xwayland_surface->pending_width = width; + view->sway_xwayland_surface->pending_height = height; + + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; + wlr_xwayland_surface_configure(xsurface, view->swayc->x, view->swayc->y, + width, height); +} + +static void handle_commit(struct wl_listener *listener, void *data) { + struct sway_xwayland_surface *sway_surface = + wl_container_of(listener, sway_surface, commit); + struct sway_view *view = sway_surface->view; + sway_log(L_DEBUG, "xwayland surface commit %dx%d", + sway_surface->pending_width, sway_surface->pending_height); + // NOTE: We intentionally discard the view's desired width here + // TODO: Let floating views do whatever + view->width = sway_surface->pending_width; + view->height = sway_surface->pending_height; +} + +static void handle_destroy(struct wl_listener *listener, void *data) { + struct sway_xwayland_surface *sway_surface = + wl_container_of(listener, sway_surface, destroy); + wl_list_remove(&sway_surface->commit.link); + wl_list_remove(&sway_surface->destroy.link); + wl_list_remove(&sway_surface->request_configure.link); + swayc_t *parent = destroy_view(sway_surface->view->swayc); + free(sway_surface->view); + free(sway_surface); + arrange_windows(parent, -1, -1); +} + +static void handle_configure_request(struct wl_listener *listener, void *data) { + struct sway_xwayland_surface *sway_surface = + wl_container_of(listener, sway_surface, request_configure); + struct wlr_xwayland_surface_configure_event *ev = data; + struct sway_view *view = sway_surface->view; + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; + // TODO: floating windows are allowed to move around like this, but make + // sure tiling windows always stay in place. + wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, + ev->width, ev->height); +} + +void handle_xwayland_surface(struct wl_listener *listener, void *data) { + struct sway_server *server = wl_container_of( + listener, server, xwayland_surface); + struct wlr_xwayland_surface *xsurface = data; + + if (xsurface->override_redirect) { + // TODO: floating popups + return; + } + + sway_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", + xsurface->title, xsurface->class); + + struct sway_xwayland_surface *sway_surface = + calloc(1, sizeof(struct sway_xwayland_surface)); + if (!sway_assert(sway_surface, "Failed to allocate surface!")) { + return; + } + + struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); + if (!sway_assert(sway_view, "Failed to allocate view!")) { + return; + } + sway_view->type = SWAY_XWAYLAND_VIEW; + sway_view->iface.get_prop = get_prop; + sway_view->iface.set_size = set_size; + sway_view->wlr_xwayland_surface = xsurface; + sway_view->sway_xwayland_surface = sway_surface; + // TODO remove from the tree when the surface goes away (unmapped) + sway_view->surface = xsurface->surface; + sway_surface->view = sway_view; + + // TODO: + // - Wire up listeners + // - Handle popups + // - Look up pid and open on appropriate workspace + // - Set new view to maximized so it behaves nicely + // - Criteria + + sway_surface->commit.notify = handle_commit; + wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); + sway_surface->destroy.notify = handle_destroy; + wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); + sway_surface->request_configure.notify = handle_configure_request; + wl_signal_add(&xsurface->events.request_configure, + &sway_surface->request_configure); + + // TODO: actual focus semantics + swayc_t *parent = root_container.children->items[0]; + parent = parent->children->items[0]; // workspace + + swayc_t *cont = new_view(parent, sway_view); + sway_view->swayc = cont; + + arrange_windows(cont->parent, -1, -1); +} diff --git a/sway/meson.build b/sway/meson.build index cf2aa9137..e8e9013f0 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -7,6 +7,7 @@ sway_sources = files( 'ipc-server.c', 'desktop/output.c', 'desktop/xdg_shell_v6.c', + 'desktop/xwayland.c', 'tree/container.c', 'tree/layout.c', 'tree/workspace.c', diff --git a/sway/server.c b/sway/server.c index 6e66bc3ca..2694cea01 100644 --- a/sway/server.c +++ b/sway/server.c @@ -40,6 +40,13 @@ bool server_init(struct sway_server *server) { &server->xdg_shell_v6_surface); server->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface; + // TODO make xwayland optional + server->xwayland = + wlr_xwayland_create(server->wl_display, server->compositor); + wl_signal_add(&server->xwayland->events.new_surface, + &server->xwayland_surface); + server->xwayland_surface.notify = handle_xwayland_surface; + server->socket = wl_display_add_socket_auto(server->wl_display); if (!sway_assert(server->socket, "Unable to open wayland socket")) { wlr_backend_destroy(server->backend); From 514c819ff98d72880c5b7e0beb7bd9ca866bc1ad Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 4 Dec 2017 22:43:49 +0100 Subject: [PATCH 053/522] Add exec and exec_always commands --- sway/commands.c | 2 + sway/commands/exec.c | 16 +++++++ sway/commands/exec_always.c | 85 +++++++++++++++++++++++++++++++++++++ sway/meson.build | 2 + 4 files changed, 105 insertions(+) create mode 100644 sway/commands/exec.c create mode 100644 sway/commands/exec_always.c diff --git a/sway/commands.c b/sway/commands.c index 94a45253c..5fdcdbb6e 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -90,6 +90,8 @@ struct cmd_results *add_color(const char *name, char *buffer, const char *color) /* Keep alphabetized */ static struct cmd_handler handlers[] = { + { "exec", cmd_exec }, + { "exec_always", cmd_exec_always }, { "exit", cmd_exit }, }; diff --git a/sway/commands/exec.c b/sway/commands/exec.c new file mode 100644 index 000000000..dd71500a7 --- /dev/null +++ b/sway/commands/exec.c @@ -0,0 +1,16 @@ +#include +#include "sway/commands.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->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 new file mode 100644 index 000000000..0a252e7b3 --- /dev/null +++ b/sway/commands/exec_always.c @@ -0,0 +1,85 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include "sway/commands.h" +#include "sway/workspace.h" +#include "sway/container.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 ((error = checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0))) { + return error; + } + + char *tmp = NULL; + if (strcmp((char*)*argv, "--no-startup-id") == 0) { + sway_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); + if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) { + return error; + } + + tmp = join_args(argv + 1, argc - 1); + } else { + tmp = join_args(argv, argc); + } + + // Put argument into cmd array + char cmd[4096]; + strncpy(cmd, tmp, sizeof(cmd)); + cmd[sizeof(cmd) - 1] = 0; + free(tmp); + sway_log(L_DEBUG, "Executing %s", cmd); + + int fd[2]; + if (pipe(fd) != 0) { + sway_log(L_ERROR, "Unable to create pipe for fork"); + } + + pid_t pid; + pid_t *child = malloc(sizeof(pid_t)); // malloc'd so that Linux can avoid copying the process space + if (!child) { + return cmd_results_new(CMD_FAILURE, "exec_always", "Unable to allocate child pid"); + } + // Fork process + if ((pid = fork()) == 0) { + // Fork child process again + setsid(); + if ((*child = fork()) == 0) { + execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); + // Not reached + } + close(fd[0]); + ssize_t s = 0; + while ((size_t)s < sizeof(pid_t)) { + s += write(fd[1], ((uint8_t *)child) + s, sizeof(pid_t) - s); + } + close(fd[1]); + _exit(0); // Close child process + } else if (pid < 0) { + free(child); + return cmd_results_new(CMD_FAILURE, "exec_always", "fork() failed"); + } + close(fd[1]); // close write + ssize_t s = 0; + while ((size_t)s < sizeof(pid_t)) { + s += read(fd[0], ((uint8_t *)child) + s, sizeof(pid_t) - s); + } + close(fd[0]); + // cleanup child process + wait(0); + if (*child > 0) { + sway_log(L_DEBUG, "Child process created with pid %d", *child); + // TODO: add PID to active workspace + } else { + free(child); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index 9f92f5d19..b224f15f6 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -3,6 +3,8 @@ sway_sources = files( 'server.c', 'commands.c', 'commands/exit.c', + 'commands/exec.c', + 'commands/exec_always.c', 'ipc-json.c', 'ipc-server.c', 'desktop/output.c', From 90f7f1a0e61fa20ed1b74b9df057aa70abc791ed Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 5 Dec 2017 10:40:55 +0100 Subject: [PATCH 054/522] 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 diff --git a/include/sway/commands.h b/include/sway/commands.h index df5c68596..b1f0423d8 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 000000000..56b4e6371 --- /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 695e237e7..8e7b98ed9 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 5fdcdbb6e..176381299 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 dd71500a7..fbbc49410 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 0a252e7b3..9527a4872 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 d294e344a..4bb6a97be 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 000000000..475e8b044 --- /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 bc1073094..bc843591d 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 b224f15f6..84f481378 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 000000000..cc0d3f661 --- /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; +} From 8bdf3b1b0275d53cee8538777f12461603b0a751 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 5 Dec 2017 11:02:31 -0500 Subject: [PATCH 055/522] view set position --- include/sway/view.h | 2 ++ sway/desktop/wl_shell.c | 9 +++++++++ sway/desktop/xdg_shell_v6.c | 9 +++++++++ sway/desktop/xwayland.c | 33 ++++++++++++++++++++++++++++++++- sway/tree/container.c | 5 +++++ sway/tree/layout.c | 6 ++---- 6 files changed, 59 insertions(+), 5 deletions(-) diff --git a/include/sway/view.h b/include/sway/view.h index 83ac82855..18e964f35 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -87,6 +87,8 @@ struct sway_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); } iface; }; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 9641b9113..b2e026ef7 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -37,6 +37,14 @@ static void set_size(struct sway_view *view, int width, int height) { wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); } +static void set_position(struct sway_view *view, double ox, double oy) { + if (!assert_wl_shell(view)) { + return; + } + view->swayc->x = ox; + view->swayc->y = oy; +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_wl_shell_surface *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -87,6 +95,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { sway_view->type = SWAY_WL_SHELL_VIEW; sway_view->iface.get_prop = get_prop; sway_view->iface.set_size = set_size; + sway_view->iface.set_position = set_position; 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 2545d1a68..37e39f37a 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -37,6 +37,14 @@ static void set_size(struct sway_view *view, int width, int height) { wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); } +static void set_position(struct sway_view *view, double ox, double oy) { + if (!assert_xdg(view)) { + return; + } + view->swayc->x = ox; + view->swayc->y = oy; +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xdg_surface_v6 *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -87,6 +95,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_view->type = SWAY_XDG_SHELL_V6_VIEW; sway_view->iface.get_prop = get_prop; sway_view->iface.set_size = set_size; + sway_view->iface.set_position = set_position; 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 04ec118d0..266a5869d 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -3,14 +3,17 @@ #include #include #include +#include +#include #include "sway/container.h" #include "sway/layout.h" #include "sway/server.h" #include "sway/view.h" +#include "sway/output.h" #include "log.h" static bool assert_xwayland(struct sway_view *view) { - return sway_assert(view->type == SWAY_XWAYLAND_VIEW, + return sway_assert(view->type == SWAY_XWAYLAND_VIEW && view->wlr_xwayland_surface, "Expected xwayland view!"); } @@ -40,6 +43,33 @@ static void set_size(struct sway_view *view, int width, int height) { width, height); } +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); + if (!sway_assert(output, "view must be within tree to set position")) { + return; + } + swayc_t *root = swayc_parent_by_type(output, C_ROOT); + if (!sway_assert(root, "output must be within tree to set position")) { + return; + } + struct wlr_output_layout *layout = root->output_layout; + struct wlr_output_layout_output *loutput = + wlr_output_layout_get(layout, output->sway_output->wlr_output); + if (!sway_assert(loutput, "output must be within layout to set position")) { + return; + } + + view->swayc->x = ox; + view->swayc->y = oy; + + wlr_xwayland_surface_configure(view->wlr_xwayland_surface, + ox + loutput->x, oy + loutput->y, + view->width, view->height); +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -102,6 +132,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { sway_view->type = SWAY_XWAYLAND_VIEW; sway_view->iface.get_prop = get_prop; sway_view->iface.set_size = set_size; + sway_view->iface.set_position = set_position; sway_view->wlr_xwayland_surface = xsurface; sway_view->sway_xwayland_surface = sway_surface; // TODO remove from the tree when the surface goes away (unmapped) diff --git a/sway/tree/container.c b/sway/tree/container.c index c7bce38a7..e205fbcf4 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "sway/container.h" #include "sway/layout.h" #include "sway/output.h" @@ -53,6 +54,10 @@ swayc_t *new_output(struct sway_output *sway_output) { 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); + add_child(&root_container, output); // Create workspace diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 2d442f2a4..cb39a361a 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -215,8 +215,7 @@ static void apply_horiz_layout(swayc_t *container, sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); - child->x = child_x; - child->y = y; + child->sway_view->iface.set_position(child->sway_view, child_x, y); if (i == end - 1) { double remaining_width = x + width - child_x; @@ -266,8 +265,7 @@ void apply_vert_layout(swayc_t *container, sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); - child->x = x; - child->y = child_y; + child->sway_view->iface.set_position(child->sway_view, x, child_y); if (i == end - 1) { double remaining_height = y + height - child_y; From 7e81d304a3121e92f78527dcf1327e991b0089ac Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 5 Dec 2017 18:21:48 +0100 Subject: [PATCH 056/522] Remove wlc includes --- include/sway/config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 56b4e6371..7de85ab7c 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; }; /** From 9aeda824779d3174db01b6445fa349def031a035 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 5 Dec 2017 18:47:57 +0100 Subject: [PATCH 057/522] Add include command --- sway/commands.c | 1 + sway/commands/include.c | 15 +++++++ sway/config.c | 89 +++++++++++++++++++++++++++++++++++++++++ sway/meson.build | 1 + 4 files changed, 106 insertions(+) create mode 100644 sway/commands/include.c diff --git a/sway/commands.c b/sway/commands.c index 176381299..05a66a7f4 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 }, + { "include", cmd_include }, }; static int handler_compare(const void *_a, const void *_b) { diff --git a/sway/commands/include.c b/sway/commands/include.c new file mode 100644 index 000000000..1ba9a10d2 --- /dev/null +++ b/sway/commands/include.c @@ -0,0 +1,15 @@ +#include "sway/commands.h" +#include "sway/config.h" + +struct cmd_results *cmd_include(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "include", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!load_include_configs(argv[0], config)) { + return cmd_results_new(CMD_INVALID, "include", "Failed to include sub configuration file: %s", argv[0]); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 475e8b044..61131845b 100644 --- a/sway/config.c +++ b/sway/config.c @@ -311,6 +311,95 @@ bool load_main_config(const char *file, bool is_active) { return success; } +static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { + // save parent config + const char *parent_config = config->current_config; + + char *full_path = strdup(path); + int len = strlen(path); + if (len >= 1 && path[0] != '/') { + len = len + strlen(parent_dir) + 2; + full_path = malloc(len * sizeof(char)); + if (!full_path) { + sway_log(L_ERROR, "Unable to allocate full path to included config"); + return false; + } + snprintf(full_path, len, "%s/%s", parent_dir, path); + } + + char *real_path = realpath(full_path, NULL); + free(full_path); + + if (real_path == NULL) { + sway_log(L_DEBUG, "%s not found.", path); + return false; + } + + // check if config has already been included + int j; + for (j = 0; j < config->config_chain->length; ++j) { + char *old_path = config->config_chain->items[j]; + if (strcmp(real_path, old_path) == 0) { + sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path); + free(real_path); + return false; + } + } + + config->current_config = real_path; + list_add(config->config_chain, real_path); + int index = config->config_chain->length - 1; + + if (!load_config(real_path, config)) { + free(real_path); + config->current_config = parent_config; + list_del(config->config_chain, index); + return false; + } + + // restore current_config + config->current_config = parent_config; + return true; +} + +bool load_include_configs(const char *path, struct sway_config *config) { + char *wd = getcwd(NULL, 0); + char *parent_path = strdup(config->current_config); + const char *parent_dir = dirname(parent_path); + + if (chdir(parent_dir) < 0) { + free(parent_path); + free(wd); + return false; + } + + wordexp_t p; + + if (wordexp(path, &p, 0) < 0) { + free(parent_path); + free(wd); + return false; + } + + char **w = p.we_wordv; + size_t i; + for (i = 0; i < p.we_wordc; ++i) { + load_include_config(w[i], parent_dir, config); + } + free(parent_path); + wordfree(&p); + + // restore wd + if (chdir(wd) < 0) { + free(wd); + sway_log(L_ERROR, "failed to restore working directory"); + return false; + } + + free(wd); + 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/meson.build b/sway/meson.build index 84f481378..ab863e873 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -5,6 +5,7 @@ sway_sources = files( 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', + 'commands/include.c', 'config.c', 'ipc-json.c', 'ipc-server.c', From aaae59026ff3751190b93277ac6d7566e373c892 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 6 Dec 2017 12:36:06 +0100 Subject: [PATCH 058/522] 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 diff --git a/include/sway/config.h b/include/sway/config.h index 7de85ab7c..1b49c5c95 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 08a98ed95..e3f84fc64 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 176381299..961cb8676 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 000000000..c964bef71 --- /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 000000000..02e18e59a --- /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 bc843591d..8952f9973 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 84f481378..5ae7fbb3a 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 e205fbcf4..7720718fc 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; From 68ae989ceef0a144988c0a55b13aaacf514b957d Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 6 Dec 2017 12:57:13 +0100 Subject: [PATCH 059/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 1b49c5c95..231356f25 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 c964bef71..bbf8efc34 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 02e18e59a..4ed2c5311 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 7720718fc..ba305efa2 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); From 47f268d8fa83a08cd5c07f2ce50c2ce8b93126de Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 6 Dec 2017 07:34:33 -0500 Subject: [PATCH 060/522] view activate --- include/sway/view.h | 1 + sway/desktop/wl_shell.c | 5 +++++ sway/desktop/xdg_shell_v6.c | 11 +++++++++++ sway/desktop/xwayland.c | 9 +++++++++ 4 files changed, 26 insertions(+) diff --git a/include/sway/view.h b/include/sway/view.h index 18e964f35..900bd296f 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -89,6 +89,7 @@ struct sway_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); } iface; }; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index b2e026ef7..3f5a358ab 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -45,6 +45,10 @@ static void set_position(struct sway_view *view, double ox, double oy) { view->swayc->y = oy; } +static void set_activated(struct sway_view *view, bool activated) { + // no way to activate wl_shell +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_wl_shell_surface *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -96,6 +100,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { sway_view->iface.get_prop = get_prop; sway_view->iface.set_size = set_size; sway_view->iface.set_position = set_position; + sway_view->iface.set_activated = set_activated; 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 37e39f37a..2435c2565 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -45,6 +45,16 @@ static void set_position(struct sway_view *view, double ox, double oy) { view->swayc->y = oy; } +static void set_activated(struct sway_view *view, bool activated) { + 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_set_activated(surface, activated); + } +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xdg_surface_v6 *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -96,6 +106,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_view->iface.get_prop = get_prop; sway_view->iface.set_size = set_size; sway_view->iface.set_position = set_position; + sway_view->iface.set_activated = set_activated; 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 266a5869d..65c7e1ec3 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -70,6 +70,14 @@ static void set_position(struct sway_view *view, double ox, double oy) { view->width, view->height); } +static void set_activated(struct sway_view *view, bool activated) { + if (!assert_xwayland(view)) { + return; + } + struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; + wlr_xwayland_surface_activate(surface, activated); +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -133,6 +141,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { sway_view->iface.get_prop = get_prop; sway_view->iface.set_size = set_size; sway_view->iface.set_position = set_position; + sway_view->iface.set_activated = set_activated; sway_view->wlr_xwayland_surface = xsurface; sway_view->sway_xwayland_surface = sway_surface; // TODO remove from the tree when the surface goes away (unmapped) From 338a0399f8d7c0ebe9cbb989945d8fd646d8d407 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 6 Dec 2017 08:28:46 -0500 Subject: [PATCH 061/522] input skeleton --- include/sway/input.h | 18 ++++++++++++++++++ meson.build | 1 + sway/meson.build | 2 ++ sway/server.c | 4 ++++ 4 files changed, 25 insertions(+) create mode 100644 include/sway/input.h diff --git a/include/sway/input.h b/include/sway/input.h new file mode 100644 index 000000000..21ed61c5f --- /dev/null +++ b/include/sway/input.h @@ -0,0 +1,18 @@ +#ifndef _SWAY_INPUT_H +#define _SWAY_INPUT_H +#include +#include "sway/server.h" +#include "config.h" +#include "list.h" + +struct sway_input { + list_t *input_devices; +}; + +struct input_config *new_input_config(const char* identifier); + +char* libinput_dev_unique_id(struct libinput_device *dev); + +struct sway_input *sway_input_create(struct sway_server *server); + +#endif diff --git a/meson.build b/meson.build index 8e7b98ed9..029aea46b 100644 --- a/meson.build +++ b/meson.build @@ -29,6 +29,7 @@ xkbcommon = dependency('xkbcommon') pango = dependency('pango') pixman = dependency('pixman-1') libcap = dependency('libcap') +libinput = dependency('libinput') math = cc.find_library('m') git = find_program('git', required: false) a2x = find_program('a2x', required: false) diff --git a/sway/meson.build b/sway/meson.build index 84f481378..8631b9c3c 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -2,6 +2,7 @@ sway_sources = files( 'main.c', 'server.c', 'commands.c', + 'input/input.c', 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', @@ -25,6 +26,7 @@ sway_deps = [ wlroots, libcap, math, + libinput, ] executable( diff --git a/sway/server.c b/sway/server.c index 024d84291..3873e6254 100644 --- a/sway/server.c +++ b/sway/server.c @@ -11,6 +11,7 @@ // TODO WLR: make Xwayland optional #include #include "sway/server.h" +#include "sway/input.h" #include "log.h" bool server_init(struct sway_server *server) { @@ -58,6 +59,9 @@ bool server_init(struct sway_server *server) { wlr_backend_destroy(server->backend); return false; } + + server->input = sway_input_create(server); + return true; } From 7c5d8c553cbf5e93538346c904f2c2e42af66c7c Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 6 Dec 2017 19:16:12 +0100 Subject: [PATCH 062/522] Simplify free calls, use wlr_output_set_scale --- sway/config/output.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index 4ed2c5311..4a0a5cc9a 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -25,9 +25,7 @@ void output_config_defaults(struct output_config *oc) { void merge_output_config(struct output_config *dst, struct output_config *src) { if (src->name) { - if (dst->name) { - free(dst->name); - } + free(dst->name); dst->name = strdup(src->name); } if (src->enabled != -1) { @@ -55,15 +53,11 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { dst->transform = src->transform; } if (src->background) { - if (dst->background) { - free(dst->background); - } + free(dst->background); dst->background = strdup(src->background); } if (src->background_option) { - if (dst->background_option) { - free(dst->background_option); - } + free(dst->background_option); dst->background_option = strdup(src->background_option); } } @@ -103,7 +97,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { } if (oc && oc->scale > 0) { sway_log(L_DEBUG, "Set %s scale to %d", oc->name, oc->scale); - wlr_output->scale = oc->scale; + wlr_output_set_scale(wlr_output, oc->scale); } if (oc && oc->transform >= 0) { sway_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); From 41dd29161249dd6b6c3288a2d4cf63763f40ce14 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 6 Dec 2017 19:23:43 +0100 Subject: [PATCH 063/522] Use wlr_output_layout_get_box --- sway/tree/container.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index ba305efa2..ec3311a0b 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -26,27 +26,10 @@ 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; + struct wlr_box *box = + wlr_output_layout_get_box(root_container.output_layout, NULL); + root_container.width = box->width; + root_container.height = box->height; } static swayc_t *new_swayc(enum swayc_types type) { From 8764dc26c634379ca5b5c2c4fc26cf8be9adf027 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 6 Dec 2017 19:45:43 +0100 Subject: [PATCH 064/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 231356f25..4dd8e94c5 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 bbf8efc34..11da0ff67 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 4a0a5cc9a..26798503a 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 ec3311a0b..d9bed7d87 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; } From 21ce20885a6a6e9e7178778513b09fea9354c603 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 7 Dec 2017 07:31:49 -0500 Subject: [PATCH 065/522] rename input to input-manager --- include/sway/{input.h => input-manager.h} | 5 +++-- include/sway/server.h | 2 +- sway/input/{input.c => input-manager.c} | 8 +++++--- sway/meson.build | 2 +- sway/server.c | 4 ++-- 5 files changed, 12 insertions(+), 9 deletions(-) rename include/sway/{input.h => input-manager.h} (71%) rename sway/input/{input.c => input-manager.c} (89%) diff --git a/include/sway/input.h b/include/sway/input-manager.h similarity index 71% rename from include/sway/input.h rename to include/sway/input-manager.h index 21ed61c5f..a3662f7b3 100644 --- a/include/sway/input.h +++ b/include/sway/input-manager.h @@ -5,7 +5,7 @@ #include "config.h" #include "list.h" -struct sway_input { +struct sway_input_manager { list_t *input_devices; }; @@ -13,6 +13,7 @@ struct input_config *new_input_config(const char* identifier); char* libinput_dev_unique_id(struct libinput_device *dev); -struct sway_input *sway_input_create(struct sway_server *server); +struct sway_input_manager *sway_input_manager_create( + struct sway_server *server); #endif diff --git a/include/sway/server.h b/include/sway/server.h index 3fa72e848..76a054764 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -22,7 +22,7 @@ struct sway_server { struct wlr_compositor *compositor; struct wlr_data_device_manager *data_device_manager; - struct sway_input *input; + struct sway_input_manager *input; struct wl_listener output_add; struct wl_listener output_remove; diff --git a/sway/input/input.c b/sway/input/input-manager.c similarity index 89% rename from sway/input/input.c rename to sway/input/input-manager.c index 02b4995ed..285a68b88 100644 --- a/sway/input/input.c +++ b/sway/input/input-manager.c @@ -6,15 +6,17 @@ #include #include #include "sway/config.h" -#include "sway/input.h" +#include "sway/input-manager.h" #include "sway/server.h" #include "list.h" #include "log.h" struct input_config *current_input_config = NULL; -struct sway_input *sway_input_create(struct sway_server *server) { - struct sway_input *input = calloc(1, sizeof(struct sway_input)); +struct sway_input_manager *sway_input_manager_create( + struct sway_server *server) { + struct sway_input_manager *input = + calloc(1, sizeof(struct sway_input_manager)); if (!input) { return NULL; } diff --git a/sway/meson.build b/sway/meson.build index 8631b9c3c..b5cdbbf26 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -2,7 +2,7 @@ sway_sources = files( 'main.c', 'server.c', 'commands.c', - 'input/input.c', + 'input/input-manager.c', 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', diff --git a/sway/server.c b/sway/server.c index 3873e6254..174beac6f 100644 --- a/sway/server.c +++ b/sway/server.c @@ -11,7 +11,7 @@ // TODO WLR: make Xwayland optional #include #include "sway/server.h" -#include "sway/input.h" +#include "sway/input-manager.h" #include "log.h" bool server_init(struct sway_server *server) { @@ -60,7 +60,7 @@ bool server_init(struct sway_server *server) { return false; } - server->input = sway_input_create(server); + server->input = sway_input_manager_create(server); return true; } From f6f63f60d6c7f9602dd1c07b45eb45a97e5b6f5a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 7 Dec 2017 09:58:32 -0500 Subject: [PATCH 066/522] basic input manager and seat --- include/sway/input-manager.h | 9 ++++-- include/sway/seat.h | 20 +++++++++++++ sway/input/input-manager.c | 54 ++++++++++++++++++++++++++++++++++++ sway/input/seat.c | 24 ++++++++++++++++ sway/meson.build | 1 + 5 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 include/sway/seat.h create mode 100644 sway/input/seat.c diff --git a/include/sway/input-manager.h b/include/sway/input-manager.h index a3662f7b3..4c01a0435 100644 --- a/include/sway/input-manager.h +++ b/include/sway/input-manager.h @@ -1,12 +1,15 @@ -#ifndef _SWAY_INPUT_H -#define _SWAY_INPUT_H +#ifndef _SWAY_INPUT_MANAGER_H +#define _SWAY_INPUT_MANAGER_H #include #include "sway/server.h" #include "config.h" #include "list.h" struct sway_input_manager { - list_t *input_devices; + struct wl_listener input_add; + struct wl_listener input_remove; + struct sway_server *server; + list_t *seats; }; struct input_config *new_input_config(const char* identifier); diff --git a/include/sway/seat.h b/include/sway/seat.h new file mode 100644 index 000000000..a2b8fe51c --- /dev/null +++ b/include/sway/seat.h @@ -0,0 +1,20 @@ +#ifndef _SWAY_SEAT_H +#define _SWAY_SEAT_H + +#include +#include "sway/input-manager.h" + +struct sway_seat { + struct wlr_seat *seat; +}; + +struct sway_seat *sway_seat_create(struct wl_display *display, + const char *seat_name); + +void sway_seat_add_device(struct sway_seat *seat, + struct wlr_input_device *device); + +void sway_seat_remove_device(struct sway_seat *seat, + struct wlr_input_device *device); + +#endif diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 285a68b88..b5ab8cc16 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -7,12 +7,52 @@ #include #include "sway/config.h" #include "sway/input-manager.h" +#include "sway/seat.h" #include "sway/server.h" #include "list.h" #include "log.h" +static const char *default_seat = "seat0"; + 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]; + if (strcmp(seat->seat->name, seat_name) == 0) { + return seat; + } + } + + seat = sway_seat_create(input->server->wl_display, seat_name); + list_add(input->seats, seat); + + return seat; +} + +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; + + // TODO device configuration + struct sway_seat *seat = input_manager_get_seat(input, default_seat); + sway_seat_add_device(seat, device); +} + +static void input_remove_notify(struct wl_listener *listener, void *data) { + struct sway_input_manager *input = + 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_manager *sway_input_manager_create( struct sway_server *server) { struct sway_input_manager *input = @@ -20,6 +60,20 @@ struct sway_input_manager *sway_input_manager_create( if (!input) { return NULL; } + // XXX probably don't need the full server + input->server = server; + + input->seats = create_list(); + + // create the default seat + input_manager_get_seat(input, default_seat); + + input->input_add.notify = input_add_notify; + wl_signal_add(&server->backend->events.input_add, &input->input_add); + + input->input_remove.notify = input_remove_notify; + wl_signal_add(&server->backend->events.input_remove, &input->input_remove); + return input; } diff --git a/sway/input/seat.c b/sway/input/seat.c new file mode 100644 index 000000000..f41b6dba8 --- /dev/null +++ b/sway/input/seat.c @@ -0,0 +1,24 @@ +#define _XOPEN_SOURCE 700 +#include "sway/seat.h" +#include "sway/input-manager.h" +#include "log.h" + +struct sway_seat *sway_seat_create(struct wl_display *display, + const char *seat_name) { + struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); + if (!seat) { + return NULL; + } + seat->seat = wlr_seat_create(display, seat_name); + return seat; +} + +void sway_seat_add_device(struct sway_seat *seat, + struct wlr_input_device *device) { + sway_log(L_DEBUG, "input add: %s", device->name); +} + +void sway_seat_remove_device(struct sway_seat *seat, + struct wlr_input_device *device) { + sway_log(L_DEBUG, "input remove: %s", device->name); +} diff --git a/sway/meson.build b/sway/meson.build index b5cdbbf26..cea565d60 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -3,6 +3,7 @@ sway_sources = files( 'server.c', 'commands.c', 'input/input-manager.c', + 'input/seat.c', 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', From ec7fc42a00db8c230ca1a050f0a1f7badc697fa5 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 8 Dec 2017 07:22:26 -0500 Subject: [PATCH 067/522] sway cursor --- include/sway/cursor.h | 26 +++++++++ include/sway/seat.h | 1 + sway/input/cursor.c | 128 ++++++++++++++++++++++++++++++++++++++++++ sway/input/seat.c | 52 +++++++++++++++++ sway/meson.build | 1 + 5 files changed, 208 insertions(+) create mode 100644 include/sway/cursor.h create mode 100644 sway/input/cursor.c diff --git a/include/sway/cursor.h b/include/sway/cursor.h new file mode 100644 index 000000000..647bc8f10 --- /dev/null +++ b/include/sway/cursor.h @@ -0,0 +1,26 @@ +#ifndef _SWAY_CURSOR_H +#define _SWAY_CURSOR_H + +#include "sway/seat.h" + +struct sway_cursor { + struct wlr_cursor *cursor; + + struct wl_listener motion; + struct wl_listener motion_absolute; + struct wl_listener button; + struct wl_listener axis; + + struct wl_listener touch_down; + struct wl_listener touch_up; + struct wl_listener touch_motion; + + struct wl_listener tool_axis; + struct wl_listener tool_tip; + + struct wl_listener request_set_cursor; +}; + +struct sway_cursor *sway_cursor_create(struct sway_seat *seat); + +#endif diff --git a/include/sway/seat.h b/include/sway/seat.h index a2b8fe51c..2f8ca72e1 100644 --- a/include/sway/seat.h +++ b/include/sway/seat.h @@ -6,6 +6,7 @@ struct sway_seat { struct wlr_seat *seat; + struct sway_cursor *cursor; }; struct sway_seat *sway_seat_create(struct wl_display *display, diff --git a/sway/input/cursor.c b/sway/input/cursor.c new file mode 100644 index 000000000..819007d56 --- /dev/null +++ b/sway/input/cursor.c @@ -0,0 +1,128 @@ +#define _XOPEN_SOURCE 700 +#include +#include "sway/cursor.h" +#include "log.h" + +static void handle_cursor_motion(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, motion); + struct wlr_event_pointer_motion *event = data; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +static void handle_cursor_motion_absolute(struct wl_listener *listener, + void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, motion_absolute); + struct wlr_event_pointer_motion_absolute *event = data; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +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; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +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; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +static void handle_touch_down(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, touch_down); + struct wlr_event_touch_down *event = data; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +static void handle_touch_up(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, touch_up); + struct wlr_event_touch_up *event = data; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +static void handle_touch_motion(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, touch_motion); + struct wlr_event_touch_motion *event = data; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +static void handle_tool_axis(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, tool_axis); + struct wlr_event_tablet_tool_axis *event = data; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +static void handle_tool_tip(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, tool_tip); + struct wlr_event_tablet_tool_tip *event = data; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +static void handle_request_set_cursor(struct wl_listener *listener, + void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, request_set_cursor); + struct wlr_seat_pointer_request_set_cursor_event *event = data; + sway_log(L_DEBUG, "TODO: handle event: %p", event); +} + +struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { + struct sway_cursor *cursor = calloc(1, sizeof(struct sway_cursor)); + if (!sway_assert(cursor, "could not allocate sway cursor")) { + return NULL; + } + + struct wlr_cursor *wlr_cursor = wlr_cursor_create(); + if (!sway_assert(wlr_cursor, "could not allocate wlr cursor")) { + free(cursor); + return NULL; + } + + // input events + wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); + cursor->motion.notify = handle_cursor_motion; + + wl_signal_add(&wlr_cursor->events.motion_absolute, + &cursor->motion_absolute); + cursor->motion_absolute.notify = handle_cursor_motion_absolute; + + wl_signal_add(&wlr_cursor->events.button, &cursor->button); + cursor->button.notify = handle_cursor_button; + + wl_signal_add(&wlr_cursor->events.axis, &cursor->axis); + cursor->axis.notify = handle_cursor_axis; + + wl_signal_add(&wlr_cursor->events.touch_down, &cursor->touch_down); + cursor->touch_down.notify = handle_touch_down; + + wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); + cursor->touch_up.notify = handle_touch_up; + + wl_signal_add(&wlr_cursor->events.touch_motion, + &cursor->touch_motion); + cursor->touch_motion.notify = handle_touch_motion; + + wl_signal_add(&wlr_cursor->events.tablet_tool_axis, + &cursor->tool_axis); + cursor->tool_axis.notify = handle_tool_axis; + + 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, + &cursor->request_set_cursor); + cursor->request_set_cursor.notify = handle_request_set_cursor; + + cursor->cursor = wlr_cursor; + + return cursor; +} diff --git a/sway/input/seat.c b/sway/input/seat.c index f41b6dba8..459b2ee2f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,5 +1,7 @@ #define _XOPEN_SOURCE 700 +#include #include "sway/seat.h" +#include "sway/cursor.h" #include "sway/input-manager.h" #include "log.h" @@ -9,16 +11,66 @@ struct sway_seat *sway_seat_create(struct wl_display *display, if (!seat) { return NULL; } + seat->seat = wlr_seat_create(display, seat_name); + if (!sway_assert(seat->seat, "could not allocate seat")) { + return NULL; + } + + seat->cursor = sway_cursor_create(seat); + if (!seat->cursor) { + wlr_seat_destroy(seat->seat); + free(seat); + return NULL; + } + + wlr_seat_set_capabilities(seat->seat, + WL_SEAT_CAPABILITY_KEYBOARD | + WL_SEAT_CAPABILITY_POINTER | + WL_SEAT_CAPABILITY_TOUCH); + return seat; } +static void seat_add_pointer(struct sway_seat *seat, + struct wlr_input_device *device) { + // TODO pointer configuration + wlr_cursor_attach_input_device(seat->cursor->cursor, device); +} + 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) { + case WLR_INPUT_DEVICE_POINTER: + seat_add_pointer(seat, device); + break; + case WLR_INPUT_DEVICE_KEYBOARD: + 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"); + break; + } +} + +static void seat_remove_pointer(struct sway_seat *seat, + struct wlr_input_device *device) { + // TODO } 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) { + case WLR_INPUT_DEVICE_POINTER: + seat_remove_pointer(seat, device); + break; + case WLR_INPUT_DEVICE_KEYBOARD: + 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; + } } diff --git a/sway/meson.build b/sway/meson.build index cea565d60..059204b28 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -4,6 +4,7 @@ sway_sources = files( 'commands.c', 'input/input-manager.c', 'input/seat.c', + 'input/cursor.c', 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', From d76e745b738281fb98834fd5dee78f2a21727d80 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 8 Dec 2017 08:07:47 -0500 Subject: [PATCH 068/522] input include directory --- include/sway/{ => input}/cursor.h | 2 +- include/sway/{ => input}/input-manager.h | 2 +- include/sway/{ => input}/seat.h | 2 +- sway/input/cursor.c | 2 +- sway/input/input-manager.c | 4 ++-- sway/input/seat.c | 6 +++--- sway/server.c | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) rename include/sway/{ => input}/cursor.h (94%) rename include/sway/{ => input}/input-manager.h (95%) rename include/sway/{ => input}/seat.h (91%) diff --git a/include/sway/cursor.h b/include/sway/input/cursor.h similarity index 94% rename from include/sway/cursor.h rename to include/sway/input/cursor.h index 647bc8f10..91421964a 100644 --- a/include/sway/cursor.h +++ b/include/sway/input/cursor.h @@ -1,7 +1,7 @@ #ifndef _SWAY_CURSOR_H #define _SWAY_CURSOR_H -#include "sway/seat.h" +#include "sway/input/seat.h" struct sway_cursor { struct wlr_cursor *cursor; diff --git a/include/sway/input-manager.h b/include/sway/input/input-manager.h similarity index 95% rename from include/sway/input-manager.h rename to include/sway/input/input-manager.h index 4c01a0435..5dc75ba76 100644 --- a/include/sway/input-manager.h +++ b/include/sway/input/input-manager.h @@ -2,7 +2,7 @@ #define _SWAY_INPUT_MANAGER_H #include #include "sway/server.h" -#include "config.h" +#include "sway/config.h" #include "list.h" struct sway_input_manager { diff --git a/include/sway/seat.h b/include/sway/input/seat.h similarity index 91% rename from include/sway/seat.h rename to include/sway/input/seat.h index 2f8ca72e1..a84b7efd0 100644 --- a/include/sway/seat.h +++ b/include/sway/input/seat.h @@ -2,7 +2,7 @@ #define _SWAY_SEAT_H #include -#include "sway/input-manager.h" +#include "sway/input/input-manager.h" struct sway_seat { struct wlr_seat *seat; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 819007d56..85b7865d7 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1,6 +1,6 @@ #define _XOPEN_SOURCE 700 #include -#include "sway/cursor.h" +#include "sway/input/cursor.h" #include "log.h" static void handle_cursor_motion(struct wl_listener *listener, void *data) { diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index b5ab8cc16..4f52e59a9 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -6,8 +6,8 @@ #include #include #include "sway/config.h" -#include "sway/input-manager.h" -#include "sway/seat.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/server.h" #include "list.h" #include "log.h" diff --git a/sway/input/seat.c b/sway/input/seat.c index 459b2ee2f..1a2b728c7 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,8 +1,8 @@ #define _XOPEN_SOURCE 700 #include -#include "sway/seat.h" -#include "sway/cursor.h" -#include "sway/input-manager.h" +#include "sway/input/seat.h" +#include "sway/input/cursor.h" +#include "sway/input/input-manager.h" #include "log.h" struct sway_seat *sway_seat_create(struct wl_display *display, diff --git a/sway/server.c b/sway/server.c index 174beac6f..7b9a5e8e5 100644 --- a/sway/server.c +++ b/sway/server.c @@ -11,7 +11,7 @@ // TODO WLR: make Xwayland optional #include #include "sway/server.h" -#include "sway/input-manager.h" +#include "sway/input/input-manager.h" #include "log.h" bool server_init(struct sway_server *server) { From 4a14aa9ad99a6f316024e110332a0b482e231543 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 9 Dec 2017 15:48:52 +0100 Subject: [PATCH 069/522] Remove output from layout --- sway/commands/output.c | 2 +- sway/config/output.c | 3 ++- sway/tree/container.c | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sway/commands/output.c b/sway/commands/output.c index 11da0ff67..be78358a6 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -227,7 +227,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { 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. + // 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]; diff --git a/sway/config/output.c b/sway/config/output.c index 26798503a..027a79cef 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -91,12 +91,13 @@ static void set_mode(struct wlr_output *output, int width, int height, 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.output_layout, wlr_output); 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); } diff --git a/sway/tree/container.c b/sway/tree/container.c index d9bed7d87..e4c27d614 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -8,6 +8,7 @@ #include "sway/container.h" #include "sway/layout.h" #include "sway/output.h" +#include "sway/server.h" #include "sway/view.h" #include "sway/workspace.h" #include "log.h" @@ -172,6 +173,7 @@ 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 @@ -190,9 +192,11 @@ swayc_t *destroy_output(swayc_t *output) { 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; } From 7c67bea942d44b93cf03c3223067d2668905a3c0 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 9 Dec 2017 11:51:28 -0500 Subject: [PATCH 070/522] sway xcursor manager --- include/sway/input/cursor.h | 1 + include/sway/input/seat.h | 2 ++ sway/input/seat.c | 38 +++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 91421964a..aa873f46b 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -5,6 +5,7 @@ struct sway_cursor { struct wlr_cursor *cursor; + struct wlr_xcursor_manager *xcursor_manager; struct wl_listener motion; struct wl_listener motion_absolute; diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index a84b7efd0..f7f8a1bbf 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -18,4 +18,6 @@ void sway_seat_add_device(struct sway_seat *seat, void sway_seat_remove_device(struct sway_seat *seat, struct wlr_input_device *device); +void sway_seat_configure_xcursor(struct sway_seat *seat); + #endif diff --git a/sway/input/seat.c b/sway/input/seat.c index 1a2b728c7..1fd659800 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,8 +1,10 @@ #define _XOPEN_SOURCE 700 #include +#include #include "sway/input/seat.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" +#include "sway/output.h" #include "log.h" struct sway_seat *sway_seat_create(struct wl_display *display, @@ -29,6 +31,8 @@ struct sway_seat *sway_seat_create(struct wl_display *display, WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH); + sway_seat_configure_xcursor(seat); + return seat; } @@ -74,3 +78,37 @@ void sway_seat_remove_device(struct sway_seat *seat, break; } } + +void sway_seat_configure_xcursor(struct sway_seat *seat) { + // TODO configure theme and size + const char *cursor_theme = "default"; + + if (seat->cursor->xcursor_manager) { + wlr_xcursor_manager_destroy(seat->cursor->xcursor_manager); + } + + seat->cursor->xcursor_manager = + wlr_xcursor_manager_create(NULL, 24); + if (sway_assert(seat->cursor->xcursor_manager, + "Cannot create XCursor manager for theme %s", cursor_theme)) { + return; + } + + for (int i = 0; i < root_container.children->length; ++i) { + swayc_t *output_container = root_container.children->items[i]; + struct wlr_output *output = + output_container->sway_output->wlr_output; + bool result = + wlr_xcursor_manager_load(seat->cursor->xcursor_manager, + output->scale); + + sway_assert(result, + "Cannot load xcursor theme for output '%s' with scale %d", + output->name, output->scale); + } + + wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, + "left_ptr", seat->cursor->cursor); + wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, + seat->cursor->cursor->y); +} From 9333a7eb5329073aecfaf776c8ee0572c7dff67c Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 9 Dec 2017 14:06:00 -0500 Subject: [PATCH 071/522] working xcursor --- sway/desktop/output.c | 7 +++++++ sway/input/cursor.c | 8 +++++++- sway/input/seat.c | 18 ++++++++---------- sway/main.c | 3 ++- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 7eb48bdf0..d2003834a 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -12,6 +12,8 @@ #include "sway/output.h" #include "sway/server.h" #include "sway/view.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" static void output_frame_view(swayc_t *view, void *data) { struct sway_output *output = data; @@ -120,6 +122,11 @@ 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); + } + arrange_windows(output->swayc, -1, -1); } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 85b7865d7..4f0344bef 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1,5 +1,6 @@ #define _XOPEN_SOURCE 700 #include +#include #include "sway/input/cursor.h" #include "log.h" @@ -7,7 +8,10 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); struct wlr_event_pointer_motion *event = data; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + sway_log(L_DEBUG, "TODO: handle cursor motion event: dx=%f, dy=%f", event->delta_x, event->delta_y); + wlr_cursor_move(cursor->cursor, event->device, event->delta_x, event->delta_y); + sway_log(L_DEBUG, "TODO: new x=%f, y=%f", cursor->cursor->x, cursor->cursor->y); + wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, "left_ptr", cursor->cursor); } static void handle_cursor_motion_absolute(struct wl_listener *listener, @@ -87,6 +91,8 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { return NULL; } + wlr_cursor_attach_output_layout(wlr_cursor, root_container.output_layout); + // input events wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); cursor->motion.notify = handle_cursor_motion; diff --git a/sway/input/seat.c b/sway/input/seat.c index 1fd659800..5aed1f68f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -83,15 +83,13 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { // TODO configure theme and size const char *cursor_theme = "default"; - if (seat->cursor->xcursor_manager) { - wlr_xcursor_manager_destroy(seat->cursor->xcursor_manager); - } - - seat->cursor->xcursor_manager = - wlr_xcursor_manager_create(NULL, 24); - if (sway_assert(seat->cursor->xcursor_manager, - "Cannot create XCursor manager for theme %s", cursor_theme)) { - return; + if (!seat->cursor->xcursor_manager) { + 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)) { + return; + } } for (int i = 0; i < root_container.children->length; ++i) { @@ -102,7 +100,7 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { wlr_xcursor_manager_load(seat->cursor->xcursor_manager, output->scale); - sway_assert(result, + sway_assert(!result, "Cannot load xcursor theme for output '%s' with scale %d", output->name, output->scale); } diff --git a/sway/main.c b/sway/main.c index bc843591d..363f4d96c 100644 --- a/sway/main.c +++ b/sway/main.c @@ -381,11 +381,12 @@ int main(int argc, char **argv) { sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); + init_layout(); + if (!server_init(&server)) { return 1; } - init_layout(); ipc_init(&server); log_env(); From e69b052a6d88b1c24d5e48ad086480ee04c07c81 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 10 Dec 2017 08:48:44 -0500 Subject: [PATCH 072/522] working pointer motion --- include/sway/container.h | 4 +++ include/sway/input/cursor.h | 3 ++ sway/desktop/output.c | 30 ++++++++++++++----- sway/input/cursor.c | 42 ++++++++++++++++++++++---- sway/tree/container.c | 60 +++++++++++++++++++++++++++++++++++++ 5 files changed, 126 insertions(+), 13 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index 08a98ed95..0e1cc8a38 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "list.h" typedef struct sway_container swayc_t; @@ -136,4 +137,7 @@ swayc_t *destroy_view(swayc_t *view); 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); + #endif diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index aa873f46b..cc529de67 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -4,9 +4,12 @@ #include "sway/input/seat.h" struct sway_cursor { + struct sway_seat *seat; struct wlr_cursor *cursor; struct wlr_xcursor_manager *xcursor_manager; + double x, y; + struct wl_listener motion; struct wl_listener motion_absolute; struct wl_listener button; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index d2003834a..0e7f7060b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -25,8 +25,8 @@ static void output_frame_view(swayc_t *view, void *data) { } // TODO // - Deal with wlr_output_layout - int width = sway_view->width; - int height = sway_view->height; + int width = sway_view->surface->current->width; + int height = sway_view->surface->current->height; int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; double ox = view->x, oy = view->y; @@ -40,19 +40,33 @@ static void output_frame_view(swayc_t *view, void *data) { // return; //} + // if the shell specifies window geometry, make the top left corner of the + // window in the top left corner of the container to avoid arbitrarily + // sized gaps based on the attached buffer size + int window_offset_x = 0; + int window_offset_y = 0; + + if (view->sway_view->type == SWAY_XDG_SHELL_V6_VIEW) { + window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x; + window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y; + } + // TODO double rotation = 0; float matrix[16]; float translate_origin[16]; wlr_matrix_translate(&translate_origin, - (int)ox + render_width / 2, (int)oy + render_height / 2, 0); + (int)ox + render_width / 2 - window_offset_x, + (int)oy + render_height / 2 - window_offset_y, + 0); float rotate[16]; wlr_matrix_rotate(&rotate, rotation); float translate_center[16]; - wlr_matrix_translate(&translate_center, -render_width / 2, + wlr_matrix_translate(&translate_center, + -render_width / 2, -render_height / 2, 0); float scale[16]; @@ -122,10 +136,10 @@ 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); - } + for (int i = 0; i < server->input->seats->length; ++i) { + struct sway_seat *seat = server->input->seats->items[i]; + sway_seat_configure_xcursor(seat); + } arrange_windows(output->swayc, -1, -1); } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 4f0344bef..059f907da 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -2,16 +2,44 @@ #include #include #include "sway/input/cursor.h" +#include "sway/view.h" +#include "list.h" #include "log.h" +static void cursor_update_position(struct sway_cursor *cursor) { + double x = cursor->cursor->x; + double y = cursor->cursor->y; + + wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, + "left_ptr", cursor->cursor); + + cursor->x = x; + cursor->y = y; +} + +static void cursor_send_pointer_motion(struct sway_cursor *cursor, + uint32_t time) { + struct wlr_seat *seat = cursor->seat->seat; + struct wlr_surface *surface = NULL; + double sx, sy; + swayc_t *swayc = + swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + if (swayc) { + wlr_seat_pointer_enter(seat, surface, sx, sy); + wlr_seat_pointer_notify_motion(seat, time, sx, sy); + } else { + wlr_seat_pointer_clear_focus(seat); + } +} + static void handle_cursor_motion(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); struct wlr_event_pointer_motion *event = data; - sway_log(L_DEBUG, "TODO: handle cursor motion event: dx=%f, dy=%f", event->delta_x, event->delta_y); - wlr_cursor_move(cursor->cursor, event->device, event->delta_x, event->delta_y); - sway_log(L_DEBUG, "TODO: new x=%f, y=%f", cursor->cursor->x, cursor->cursor->y); - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, "left_ptr", cursor->cursor); + wlr_cursor_move(cursor->cursor, event->device, + event->delta_x, event->delta_y); + cursor_update_position(cursor); + cursor_send_pointer_motion(cursor, event->time_msec); } static void handle_cursor_motion_absolute(struct wl_listener *listener, @@ -19,7 +47,10 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, struct sway_cursor *cursor = wl_container_of(listener, cursor, motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + wlr_cursor_warp_absolute(cursor->cursor, event->device, + event->x_mm / event->width_mm, event->y_mm / event->height_mm); + cursor_update_position(cursor); + cursor_send_pointer_motion(cursor, event->time_msec); } static void handle_cursor_button(struct wl_listener *listener, void *data) { @@ -91,6 +122,7 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { return NULL; } + cursor->seat = seat; wlr_cursor_attach_output_layout(wlr_cursor, root_container.output_layout); // input events diff --git a/sway/tree/container.c b/sway/tree/container.c index e205fbcf4..321ef8b15 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "sway/container.h" #include "sway/layout.h" #include "sway/output.h" @@ -168,3 +169,62 @@ swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { } while (container && container->type != type); return container; } + +swayc_t *swayc_at(swayc_t *parent, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + list_t *queue = create_list(); + list_add(queue, parent); + + 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; + swayc_t *soutput = swayc_parent_by_type(swayc, C_OUTPUT); + struct wlr_box *output_box = + wlr_output_layout_get_box(root_container.output_layout, + soutput->sway_output->wlr_output); + double ox = lx - output_box->x; + double oy = ly - output_box->y; + double view_sx = ox - swayc->x; + double view_sy = oy - swayc->y; + int width = swayc->sway_view->surface->current->width; + int height = swayc->sway_view->surface->current->height; + + // TODO popups and subsurfaces + switch (sview->type) { + case SWAY_WL_SHELL_VIEW: + break; + case SWAY_XDG_SHELL_V6_VIEW: + // the top left corner of the sway container is the + // coordinate of the top left corner of the window geometry + view_sx += sview->wlr_xdg_surface_v6->geometry->x; + view_sy += sview->wlr_xdg_surface_v6->geometry->y; + break; + case SWAY_XWAYLAND_VIEW: + break; + default: + break; + } + + if (view_sx > 0 && view_sx < width && + view_sy > 0 && view_sy < height && + pixman_region32_contains_point( + &sview->surface->current->input, + view_sx, view_sy, NULL)) { + *sx = view_sx; + *sy = view_sy; + *surface = swayc->sway_view->surface; + list_free(queue); + return swayc; + } + } else { + list_cat(queue, swayc->children); + } + } + + list_free(queue); + + return NULL; +} From 5f644d78fc77f48c7f7d839f7c2e318b51c2c6d7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 10 Dec 2017 10:08:16 -0500 Subject: [PATCH 073/522] button and axis events --- sway/input/cursor.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 059f907da..5f2d650e6 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -25,7 +25,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, swayc_t *swayc = swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); if (swayc) { - wlr_seat_pointer_enter(seat, surface, sx, sy); + wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); } else { wlr_seat_pointer_clear_focus(seat); @@ -57,49 +57,51 @@ 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; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + wlr_seat_pointer_notify_button(cursor->seat->seat, event->time_msec, + event->button, event->state); } 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; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + wlr_seat_pointer_notify_axis(cursor->seat->seat, event->time_msec, + event->orientation, event->delta); } static void handle_touch_down(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); struct wlr_event_touch_down *event = data; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + sway_log(L_DEBUG, "TODO: handle touch down event: %p", event); } static void handle_touch_up(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); struct wlr_event_touch_up *event = data; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + sway_log(L_DEBUG, "TODO: handle touch up event: %p", event); } static void handle_touch_motion(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_motion); struct wlr_event_touch_motion *event = data; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + sway_log(L_DEBUG, "TODO: handle touch motion event: %p", event); } static void handle_tool_axis(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); struct wlr_event_tablet_tool_axis *event = data; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + sway_log(L_DEBUG, "TODO: handle tool axis event: %p", event); } static void handle_tool_tip(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); struct wlr_event_tablet_tool_tip *event = data; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + sway_log(L_DEBUG, "TODO: handle tool tip event: %p", event); } static void handle_request_set_cursor(struct wl_listener *listener, @@ -107,7 +109,7 @@ static void handle_request_set_cursor(struct wl_listener *listener, struct sway_cursor *cursor = wl_container_of(listener, cursor, request_set_cursor); struct wlr_seat_pointer_request_set_cursor_event *event = data; - sway_log(L_DEBUG, "TODO: handle event: %p", event); + sway_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); } struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { From 21626e8153490bf155e812644454fe9610491ffd Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 10 Dec 2017 11:11:47 -0500 Subject: [PATCH 074/522] seat focus on button press --- include/sway/container.h | 4 +++ include/sway/input/input-manager.h | 3 ++ include/sway/input/seat.h | 8 +++++- sway/input/cursor.c | 15 ++++++++++ sway/input/input-manager.c | 14 +++++++++- sway/input/seat.c | 44 ++++++++++++++++++++++++++++-- sway/tree/container.c | 6 ++++ 7 files changed, 90 insertions(+), 4 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index 0e1cc8a38..f13745ee4 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -124,6 +124,10 @@ struct sway_container { * 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, diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 5dc75ba76..9548c1703 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -19,4 +19,7 @@ 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, + swayc_t *container); + #endif diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index f7f8a1bbf..964c0f7ba 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -7,9 +7,13 @@ struct sway_seat { struct wlr_seat *seat; struct sway_cursor *cursor; + struct sway_input_manager *input; + swayc_t *focus; + + struct wl_listener focus_destroy; }; -struct sway_seat *sway_seat_create(struct wl_display *display, +struct sway_seat *sway_seat_create(struct sway_input_manager *input, const char *seat_name); void sway_seat_add_device(struct sway_seat *seat, @@ -20,4 +24,6 @@ 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); + #endif diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 5f2d650e6..217c2ddb6 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1,4 +1,9 @@ #define _XOPEN_SOURCE 700 +#ifdef __linux__ +#include +#elif __FreeBSD__ +#include +#endif #include #include #include "sway/input/cursor.h" @@ -57,6 +62,16 @@ 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; + swayc_t *swayc = + swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + + sway_seat_set_focus(cursor->seat, swayc); + } + wlr_seat_pointer_notify_button(cursor->seat->seat, event->time_msec, event->button, event->state); } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 4f52e59a9..ca80f2678 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -27,7 +27,7 @@ static struct sway_seat *input_manager_get_seat( } } - seat = sway_seat_create(input->server->wl_display, seat_name); + seat = sway_seat_create(input, seat_name); list_add(input->seats, seat); return seat; @@ -131,3 +131,15 @@ char *libinput_dev_unique_id(struct libinput_device *device) { free(name); return identifier; } + +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; + } + } + + return false; +} diff --git a/sway/input/seat.c b/sway/input/seat.c index 5aed1f68f..94f547ccc 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -5,16 +5,17 @@ #include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/output.h" +#include "sway/view.h" #include "log.h" -struct sway_seat *sway_seat_create(struct wl_display *display, +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)); if (!seat) { return NULL; } - seat->seat = wlr_seat_create(display, seat_name); + seat->seat = wlr_seat_create(input->server->wl_display, seat_name); if (!sway_assert(seat->seat, "could not allocate seat")) { return NULL; } @@ -26,6 +27,8 @@ struct sway_seat *sway_seat_create(struct wl_display *display, return NULL; } + seat->input = input; + wlr_seat_set_capabilities(seat->seat, WL_SEAT_CAPABILITY_KEYBOARD | WL_SEAT_CAPABILITY_POINTER | @@ -110,3 +113,40 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, seat->cursor->cursor->y); } + +static void handle_focus_destroy(struct wl_listener *listener, void *data) { + struct sway_seat *seat = wl_container_of(listener, seat, focus_destroy); + //swayc_t *container = data; + + // TODO set new focus based on the state of the tree + sway_seat_set_focus(seat, NULL); +} + +void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { + swayc_t *last_focus = seat->focus; + + if (last_focus == container) { + return; + } + + if (last_focus) { + wl_list_remove(&seat->focus_destroy.link); + } + + if (container) { + struct sway_view *view = container->sway_view; + view->iface.set_activated(view, true); + wl_signal_add(&container->events.destroy, &seat->focus_destroy); + seat->focus_destroy.notify = handle_focus_destroy; + // TODO give keyboard focus + } + + seat->focus = container; + + if (last_focus && + !sway_input_manager_swayc_has_focus(seat->input, last_focus)) { + struct sway_view *view = last_focus->sway_view; + view->iface.set_activated(view, false); + + } +} diff --git a/sway/tree/container.c b/sway/tree/container.c index 321ef8b15..78c8625f6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -40,6 +40,9 @@ static swayc_t *new_swayc(enum swayc_types type) { if (type != C_VIEW) { c->children = create_list(); } + + wl_signal_init(&c->events.destroy); + return c; } @@ -119,6 +122,9 @@ 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 From 6339c4f161a80cc00a8e57f402ca45c5dbc86937 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 10 Dec 2017 13:28:04 -0500 Subject: [PATCH 075/522] remove pointer device --- sway/input/seat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 94f547ccc..b3d366819 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -63,7 +63,7 @@ void sway_seat_add_device(struct sway_seat *seat, static void seat_remove_pointer(struct sway_seat *seat, struct wlr_input_device *device) { - // TODO + wlr_cursor_detach_input_device(seat->cursor->cursor, device); } void sway_seat_remove_device(struct sway_seat *seat, From 609f63934ab3eb925741450aa7f78db1c11bdd37 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 10 Dec 2017 13:59:04 -0500 Subject: [PATCH 076/522] basic keyboard --- include/sway/input/keyboard.h | 13 ++++++++ include/sway/input/seat.h | 2 ++ sway/input/keyboard.c | 57 +++++++++++++++++++++++++++++++++++ sway/input/seat.c | 14 ++++++++- sway/meson.build | 2 ++ 5 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 include/sway/input/keyboard.h create mode 100644 sway/input/keyboard.c diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h new file mode 100644 index 000000000..2e04065c8 --- /dev/null +++ b/include/sway/input/keyboard.h @@ -0,0 +1,13 @@ +#include "sway/input/seat.h" + +struct sway_keyboard { + struct sway_seat *seat; + struct wlr_input_device *device; + struct wl_list link; // sway_seat::keyboards + + struct wl_listener keyboard_key; + struct wl_listener keyboard_modifiers; +}; + +struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, + struct wlr_input_device *device); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 964c0f7ba..a0c6ab072 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -10,6 +10,8 @@ struct sway_seat { struct sway_input_manager *input; swayc_t *focus; + struct wl_list keyboards; + struct wl_listener focus_destroy; }; diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c new file mode 100644 index 000000000..59f81e62b --- /dev/null +++ b/sway/input/keyboard.c @@ -0,0 +1,57 @@ +#include "sway/input/seat.h" +#include "sway/input/keyboard.h" +#include "log.h" + +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_keyboard_notify_key(keyboard->seat->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_seat_keyboard_notify_modifiers(keyboard->seat->seat); +} + +struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, + struct wlr_input_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; + + // TODO keyboard config + 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 xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!sway_assert(context, "cannot create XKB context")) { + return NULL; + } + + wlr_keyboard_set_keymap(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); + keyboard->keyboard_key.notify = handle_keyboard_key; + + wl_signal_add(&device->keyboard->events.modifiers, &keyboard->keyboard_modifiers); + keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; + + return keyboard; +} diff --git a/sway/input/seat.c b/sway/input/seat.c index b3d366819..0a5329c82 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -4,6 +4,7 @@ #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 "log.h" @@ -36,6 +37,8 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, sway_seat_configure_xcursor(seat); + wl_list_init(&seat->keyboards); + return seat; } @@ -45,6 +48,13 @@ static void seat_add_pointer(struct sway_seat *seat, wlr_cursor_attach_input_device(seat->cursor->cursor, device); } +static void seat_add_keyboard(struct sway_seat *seat, + struct wlr_input_device *device) { + struct sway_keyboard *keyboard = sway_keyboard_create(seat, device); + wl_list_insert(&seat->keyboards, &keyboard->link); + wlr_seat_set_keyboard(seat->seat, device); +} + void sway_seat_add_device(struct sway_seat *seat, struct wlr_input_device *device) { sway_log(L_DEBUG, "input add: %s", device->name); @@ -53,6 +63,8 @@ void sway_seat_add_device(struct sway_seat *seat, seat_add_pointer(seat, device); break; case WLR_INPUT_DEVICE_KEYBOARD: + seat_add_keyboard(seat, device); + break; case WLR_INPUT_DEVICE_TOUCH: case WLR_INPUT_DEVICE_TABLET_PAD: case WLR_INPUT_DEVICE_TABLET_TOOL: @@ -138,7 +150,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; - // TODO give keyboard focus + wlr_seat_keyboard_notify_enter(seat->seat, view->surface); } seat->focus = container; diff --git a/sway/meson.build b/sway/meson.build index 18955693c..79201f3a5 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -5,6 +5,7 @@ sway_sources = files( 'input/input-manager.c', 'input/seat.c', 'input/cursor.c', + 'input/keyboard.c', 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', @@ -30,6 +31,7 @@ sway_deps = [ libcap, math, libinput, + xkbcommon, ] executable( From 5e9ee32d63d7a02e65f05ee00295ef41e115b2eb Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 10 Dec 2017 15:13:27 -0500 Subject: [PATCH 077/522] set focus on new window --- sway/desktop/wl_shell.c | 7 +++++++ sway/desktop/xdg_shell_v6.c | 7 +++++++ sway/desktop/xwayland.c | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 3f5a358ab..3d3b1c444 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -7,6 +7,8 @@ #include "sway/layout.h" #include "sway/server.h" #include "sway/view.h" +#include "sway/input/seat.h" +#include "sway/input/input-manager.h" #include "log.h" static bool assert_wl_shell(struct sway_view *view) { @@ -126,4 +128,9 @@ void handle_wl_shell_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); + } } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 2435c2565..8ad6a5ec5 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -7,6 +7,8 @@ #include "sway/layout.h" #include "sway/server.h" #include "sway/view.h" +#include "sway/input/seat.h" +#include "sway/input/input-manager.h" #include "log.h" static bool assert_xdg(struct sway_view *view) { @@ -132,4 +134,9 @@ void handle_xdg_shell_v6_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); + } } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 65c7e1ec3..724c8a82a 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -10,6 +10,8 @@ #include "sway/server.h" #include "sway/view.h" #include "sway/output.h" +#include "sway/input/seat.h" +#include "sway/input/input-manager.h" #include "log.h" static bool assert_xwayland(struct sway_view *view) { @@ -171,4 +173,9 @@ 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); + } } From 4d449743c5c476f1891a64b31f00cb7d5dd1555b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 10 Dec 2017 15:37:17 -0500 Subject: [PATCH 078/522] keyboard remove --- include/sway/input/keyboard.h | 2 ++ sway/input/keyboard.c | 9 +++++++++ sway/input/seat.c | 31 +++++++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index 2e04065c8..19d40bdce 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h @@ -11,3 +11,5 @@ struct sway_keyboard { struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, struct wlr_input_device *device); + +void sway_keyboard_destroy(struct sway_keyboard *keyboard); diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 59f81e62b..31d254dfb 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -53,5 +53,14 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, wl_signal_add(&device->keyboard->events.modifiers, &keyboard->keyboard_modifiers); keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; + wl_list_insert(&seat->keyboards, &keyboard->link); + return keyboard; } + +void sway_keyboard_destroy(struct sway_keyboard *keyboard) { + wl_list_remove(&keyboard->keyboard_key.link); + wl_list_remove(&keyboard->keyboard_modifiers.link); + wl_list_remove(&keyboard->link); + free(keyboard); +} diff --git a/sway/input/seat.c b/sway/input/seat.c index 0a5329c82..7c827374e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -42,6 +42,18 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, return seat; } +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) { // TODO pointer configuration @@ -50,8 +62,13 @@ static void seat_add_pointer(struct sway_seat *seat, static void seat_add_keyboard(struct sway_seat *seat, struct wlr_input_device *device) { - struct sway_keyboard *keyboard = sway_keyboard_create(seat, device); - wl_list_insert(&seat->keyboards, &keyboard->link); + // 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); } @@ -73,6 +90,14 @@ void sway_seat_add_device(struct sway_seat *seat, } } +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); + } +} + static void seat_remove_pointer(struct sway_seat *seat, struct wlr_input_device *device) { wlr_cursor_detach_input_device(seat->cursor->cursor, device); @@ -86,6 +111,8 @@ void sway_seat_remove_device(struct sway_seat *seat, 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: From 9ae906cd3752fd16ea2c3e046e24abb8ec8462a2 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 10 Dec 2017 15:49:54 -0500 Subject: [PATCH 079/522] sway pointer --- include/sway/input/seat.h | 9 ++++++++- sway/input/seat.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index a0c6ab072..5455601ee 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -10,11 +10,18 @@ struct sway_seat { struct sway_input_manager *input; swayc_t *focus; - struct wl_list keyboards; + struct wl_list keyboards; // sway_keyboard::link + struct wl_list pointers; // sway_pointer::link struct wl_listener focus_destroy; }; +struct sway_pointer { + struct sway_seat *seat; + struct wlr_input_device *device; + struct wl_list link; +}; + struct sway_seat *sway_seat_create(struct sway_input_manager *input, const char *seat_name); diff --git a/sway/input/seat.c b/sway/input/seat.c index 7c827374e..9c17250da 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -42,6 +42,18 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, 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; @@ -57,6 +69,16 @@ static struct sway_keyboard *seat_keyboard_from_device(struct sway_seat *seat, static void seat_add_pointer(struct sway_seat *seat, struct wlr_input_device *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); } @@ -100,7 +122,13 @@ static void seat_remove_keyboard(struct sway_seat *seat, static void seat_remove_pointer(struct sway_seat *seat, struct wlr_input_device *device) { - wlr_cursor_detach_input_device(seat->cursor->cursor, 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); + } } void sway_seat_remove_device(struct sway_seat *seat, From 462a451328a1d6f0b17d34b431d6bf3dec87c1ba Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 11 Dec 2017 04:17:14 -0500 Subject: [PATCH 080/522] input config --- include/sway/commands.h | 4 ++ include/sway/input/input-manager.h | 2 + sway/commands.c | 90 ++++++++++++++++++-------- sway/commands/input.c | 55 ++++++++++++++++ sway/commands/input/accel_profile.c | 27 ++++++++ sway/commands/input/click_method.c | 30 +++++++++ sway/commands/input/drag_lock.c | 26 ++++++++ sway/commands/input/dwt.c | 26 ++++++++ sway/commands/input/events.c | 30 +++++++++ sway/commands/input/left_handed.c | 26 ++++++++ sway/commands/input/middle_emulation.c | 26 ++++++++ sway/commands/input/natural_scroll.c | 26 ++++++++ sway/commands/input/pointer_accel.c | 24 +++++++ sway/commands/input/scroll_method.c | 30 +++++++++ sway/commands/input/tap.c | 29 +++++++++ sway/config.c | 53 +++++++++++++++ sway/meson.build | 12 ++++ 17 files changed, 490 insertions(+), 26 deletions(-) create mode 100644 sway/commands/input.c create mode 100644 sway/commands/input/accel_profile.c create mode 100644 sway/commands/input/click_method.c create mode 100644 sway/commands/input/drag_lock.c create mode 100644 sway/commands/input/dwt.c create mode 100644 sway/commands/input/events.c create mode 100644 sway/commands/input/left_handed.c create mode 100644 sway/commands/input/middle_emulation.c create mode 100644 sway/commands/input/natural_scroll.c create mode 100644 sway/commands/input/pointer_accel.c create mode 100644 sway/commands/input/scroll_method.c create mode 100644 sway/commands/input/tap.c diff --git a/include/sway/commands.h b/include/sway/commands.h index b1f0423d8..138e3c292 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -1,6 +1,8 @@ #ifndef _SWAY_COMMANDS_H #define _SWAY_COMMANDS_H +#include "config.h" + /** * Indicates the result of a command's execution. */ @@ -39,6 +41,8 @@ enum expected_args { EXPECTED_EQUAL_TO }; +void input_cmd_apply(struct input_config *input); + struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val); diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 9548c1703..78bc161f4 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -5,6 +5,8 @@ #include "sway/config.h" #include "list.h" +extern struct input_config *current_input_config; + struct sway_input_manager { struct wl_listener input_add; struct wl_listener input_remove; diff --git a/sway/commands.c b/sway/commands.c index 05a66a7f4..7710c6ab8 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -9,6 +9,7 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/security.h" +#include "sway/input/input-manager.h" #include "stringop.h" #include "log.h" @@ -56,6 +57,44 @@ struct cmd_results *checkarg(int argc, const char *name, enum expected_args type return error; } +void input_cmd_apply(struct input_config *input) { + int i; + i = list_seq_find(config->input_configs, input_identifier_cmp, input->identifier); + if (i >= 0) { + // merge existing config + struct input_config *ic = config->input_configs->items[i]; + merge_input_config(ic, input); + free_input_config(input); + input = ic; + } else { + list_add(config->input_configs, input); + } + + current_input_config = input; + + if (input->identifier) { + // Try to find the input device and apply configuration now. If + // this is during startup then there will be no container and config + // will be applied during normal "new input" event from wlc. + /* 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; + } + } + */ + } +} + /** * Check and add color to buffer. * @@ -96,6 +135,7 @@ static struct cmd_handler handlers[] = { { "exec_always", cmd_exec_always }, { "exit", cmd_exit }, { "include", cmd_include }, + { "input", cmd_input }, }; static int handler_compare(const void *_a, const void *_b) { @@ -104,37 +144,35 @@ static int handler_compare(const void *_a, const void *_b) { return strcasecmp(a->command, b->command); } +static struct cmd_handler input_handlers[] = { + { "accel_profile", input_cmd_accel_profile }, + { "click_method", input_cmd_click_method }, + { "drag_lock", input_cmd_drag_lock }, + { "dwt", input_cmd_dwt }, + { "events", input_cmd_events }, + { "left_handed", input_cmd_left_handed }, + { "middle_emulation", input_cmd_middle_emulation }, + { "natural_scroll", input_cmd_natural_scroll }, + { "pointer_accel", input_cmd_pointer_accel }, + { "scroll_method", input_cmd_scroll_method }, + { "tap", input_cmd_tap }, +}; + static struct cmd_handler *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); - /* TODO - if (block == CMD_BLOCK_BAR) { - res = bsearch(&d, bar_handlers, - sizeof(bar_handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - } else if (block == CMD_BLOCK_BAR_COLORS){ - res = bsearch(&d, bar_colors_handlers, - sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - } else if (block == CMD_BLOCK_INPUT) { + + 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_IPC) { - res = bsearch(&d, ipc_handlers, - sizeof(ipc_handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - } else if (block == CMD_BLOCK_IPC_EVENTS) { - res = bsearch(&d, ipc_event_handlers, - sizeof(ipc_event_handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); + sizeof(input_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); } else { - */ res = bsearch(&d, handlers, - sizeof(handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - //} + sizeof(handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + } + return res; } @@ -238,8 +276,8 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) { 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 */ + // 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]); } diff --git a/sway/commands/input.c b/sway/commands/input.c new file mode 100644 index 000000000..5ca9c2e61 --- /dev/null +++ b/sway/commands/input.c @@ -0,0 +1,55 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *cmd_input(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { + return error; + } + + if (config->reading && strcmp("{", argv[1]) == 0) { + current_input_config = new_input_config(argv[0]); + sway_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); + return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); + } + + if (argc > 2) { + int argc_new = argc-2; + char **argv_new = argv+2; + + struct cmd_results *res; + current_input_config = new_input_config(argv[0]); + if (strcasecmp("accel_profile", argv[1]) == 0) { + res = input_cmd_accel_profile(argc_new, argv_new); + } else if (strcasecmp("click_method", argv[1]) == 0) { + res = input_cmd_click_method(argc_new, argv_new); + } else if (strcasecmp("drag_lock", argv[1]) == 0) { + res = input_cmd_drag_lock(argc_new, argv_new); + } else if (strcasecmp("dwt", argv[1]) == 0) { + res = input_cmd_dwt(argc_new, argv_new); + } else if (strcasecmp("events", argv[1]) == 0) { + res = input_cmd_events(argc_new, argv_new); + } else if (strcasecmp("left_handed", argv[1]) == 0) { + res = input_cmd_left_handed(argc_new, argv_new); + } else if (strcasecmp("middle_emulation", argv[1]) == 0) { + res = input_cmd_middle_emulation(argc_new, argv_new); + } else if (strcasecmp("natural_scroll", argv[1]) == 0) { + res = input_cmd_natural_scroll(argc_new, argv_new); + } else if (strcasecmp("pointer_accel", argv[1]) == 0) { + res = input_cmd_pointer_accel(argc_new, argv_new); + } else if (strcasecmp("scroll_method", argv[1]) == 0) { + res = input_cmd_scroll_method(argc_new, argv_new); + } else if (strcasecmp("tap", argv[1]) == 0) { + res = input_cmd_tap(argc_new, argv_new); + } else { + res = cmd_results_new(CMD_INVALID, "input ", "Unknown command %s", argv[1]); + } + current_input_config = NULL; + return res; + } + + return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); +} diff --git a/sway/commands/input/accel_profile.c b/sway/commands/input/accel_profile.c new file mode 100644 index 000000000..13ded4319 --- /dev/null +++ b/sway/commands/input/accel_profile.c @@ -0,0 +1,27 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_accel_profile(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "accel_profile", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "accel_profile", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "adaptive") == 0) { + new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; + } else if (strcasecmp(argv[0], "flat") == 0) { + new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; + } else { + return cmd_results_new(CMD_INVALID, "accel_profile", + "Expected 'accel_profile '"); + } + + input_cmd_apply(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 new file mode 100644 index 000000000..40f075ceb --- /dev/null +++ b/sway/commands/input/click_method.c @@ -0,0 +1,30 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_click_method(int argc, char **argv) { + sway_log(L_DEBUG, "click_method for device: %d %s", current_input_config==NULL, current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "click_method", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "click_method", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "none") == 0) { + new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE; + } else if (strcasecmp(argv[0], "button_areas") == 0) { + new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; + } else if (strcasecmp(argv[0], "clickfinger") == 0) { + new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; + } else { + return cmd_results_new(CMD_INVALID, "click_method", "Expected 'click_method +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_drag_lock(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "drag_lock", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "drag_lock", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; + } else { + return cmd_results_new(CMD_INVALID, "drag_lock", "Expected 'drag_lock '"); + } + + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/dwt.c b/sway/commands/input/dwt.c new file mode 100644 index 000000000..f3cbf2522 --- /dev/null +++ b/sway/commands/input/dwt.c @@ -0,0 +1,26 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_dwt(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "dwt", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "dwt", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->dwt = LIBINPUT_CONFIG_DWT_ENABLED; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED; + } else { + return cmd_results_new(CMD_INVALID, "dwt", "Expected 'dwt '"); + } + + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c new file mode 100644 index 000000000..4b2fdff5f --- /dev/null +++ b/sway/commands/input/events.c @@ -0,0 +1,30 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_events(int argc, char **argv) { + sway_log(L_DEBUG, "events for device: %s", current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "events", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; + } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) { + new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; + } else { + return cmd_results_new(CMD_INVALID, "events", "Expected 'events '"); + } + + input_cmd_apply(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 new file mode 100644 index 000000000..715df2a12 --- /dev/null +++ b/sway/commands/input/left_handed.c @@ -0,0 +1,26 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_left_handed(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "left_handed", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "left_handed", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->left_handed = 1; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->left_handed = 0; + } else { + return cmd_results_new(CMD_INVALID, "left_handed", "Expected 'left_handed '"); + } + + input_cmd_apply(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 new file mode 100644 index 000000000..d31ce9509 --- /dev/null +++ b/sway/commands/input/middle_emulation.c @@ -0,0 +1,26 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "middle_emulation", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "middle_emulation", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; + } else { + return cmd_results_new(CMD_INVALID, "middle_emulation", "Expected 'middle_emulation '"); + } + + input_cmd_apply(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 new file mode 100644 index 000000000..9d1dc506d --- /dev/null +++ b/sway/commands/input/natural_scroll.c @@ -0,0 +1,26 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "natural_scroll", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "natural_scoll", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->natural_scroll = 1; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->natural_scroll = 0; + } else { + return cmd_results_new(CMD_INVALID, "natural_scroll", "Expected 'natural_scroll '"); + } + + input_cmd_apply(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 new file mode 100644 index 000000000..87fb5cff7 --- /dev/null +++ b/sway/commands/input/pointer_accel.c @@ -0,0 +1,24 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "pointer_accel", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "pointer_accel", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + float pointer_accel = atof(argv[0]); + if (pointer_accel < -1 || pointer_accel > 1) { + return cmd_results_new(CMD_INVALID, "pointer_accel", "Input out of range [-1, 1]"); + } + new_config->pointer_accel = pointer_accel; + + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/scroll_method.c b/sway/commands/input/scroll_method.c new file mode 100644 index 000000000..98873938e --- /dev/null +++ b/sway/commands/input/scroll_method.c @@ -0,0 +1,30 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_scroll_method(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "scroll_method", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "scroll_method", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "none") == 0) { + new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + } else if (strcasecmp(argv[0], "two_finger") == 0) { + new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; + } else if (strcasecmp(argv[0], "edge") == 0) { + new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE; + } else if (strcasecmp(argv[0], "on_button_down") == 0) { + new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; + } else { + return cmd_results_new(CMD_INVALID, "scroll_method", "Expected 'scroll_method '"); + } + + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c new file mode 100644 index 000000000..1109466f4 --- /dev/null +++ b/sway/commands/input/tap.c @@ -0,0 +1,29 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +struct cmd_results *input_cmd_tap(int argc, char **argv) { + sway_log(L_DEBUG, "tap for device: %s", current_input_config->identifier); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "tap", EXPECTED_AT_LEAST, 1))) { + return error; + } + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "tap", "No input device defined."); + } + struct input_config *new_config = new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->tap = LIBINPUT_CONFIG_TAP_ENABLED; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED; + } else { + return cmd_results_new(CMD_INVALID, "tap", "Expected 'tap '"); + } + + sway_log(L_DEBUG, "apply-tap for device: %s", current_input_config->identifier); + input_cmd_apply(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 61131845b..ec8e89b4e 100644 --- a/sway/config.c +++ b/sway/config.c @@ -226,6 +226,59 @@ static int qstrcmp(const void* a, const void* b) { return strcmp(*((char**) a), *((char**) b)); } +void merge_input_config(struct input_config *dst, struct input_config *src) { + if (src->identifier) { + if (dst->identifier) { + free(dst->identifier); + } + dst->identifier = strdup(src->identifier); + } + if (src->accel_profile != INT_MIN) { + dst->accel_profile = src->accel_profile; + } + if (src->click_method != INT_MIN) { + dst->click_method = src->click_method; + } + if (src->drag_lock != INT_MIN) { + dst->drag_lock = src->drag_lock; + } + if (src->dwt != INT_MIN) { + dst->dwt = src->dwt; + } + if (src->middle_emulation != INT_MIN) { + dst->middle_emulation = src->middle_emulation; + } + if (src->natural_scroll != INT_MIN) { + dst->natural_scroll = src->natural_scroll; + } + if (src->pointer_accel != FLT_MIN) { + dst->pointer_accel = src->pointer_accel; + } + if (src->scroll_method != INT_MIN) { + dst->scroll_method = src->scroll_method; + } + if (src->send_events != INT_MIN) { + dst->send_events = src->send_events; + } + if (src->tap != INT_MIN) { + dst->tap = src->tap; + } +} + +void free_input_config(struct input_config *ic) { + if (!ic) { + return; + } + free(ic->identifier); + free(ic); +} + +int input_identifier_cmp(const void *item, const void *data) { + const struct input_config *ic = item; + const char *identifier = data; + return strcmp(ic->identifier, identifier); +} + bool load_main_config(const char *file, bool is_active) { char *path; if (file != NULL) { diff --git a/sway/meson.build b/sway/meson.build index 79201f3a5..aa3dd2a72 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -10,6 +10,18 @@ sway_sources = files( 'commands/exec.c', 'commands/exec_always.c', 'commands/include.c', + 'commands/input.c', + 'commands/input/accel_profile.c', + 'commands/input/click_method.c', + 'commands/input/drag_lock.c', + 'commands/input/dwt.c', + 'commands/input/events.c', + 'commands/input/left_handed.c', + 'commands/input/middle_emulation.c', + 'commands/input/natural_scroll.c', + 'commands/input/pointer_accel.c', + 'commands/input/scroll_method.c', + 'commands/input/tap.c', 'config.c', 'ipc-json.c', 'ipc-server.c', From 475a0132a99aa7c576a399fdee920aa3ecadeff9 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 11 Dec 2017 21:47:40 +0100 Subject: [PATCH 081/522] Use custom modes when output has no mode --- sway/config/output.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sway/config/output.c b/sway/config/output.c index 027a79cef..e6e680d3d 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -69,8 +69,14 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { 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); + if (wl_list_empty(&output->modes)) { + sway_log(L_DEBUG, "Assigning custom mode to %s", output->name); + wlr_output_set_custom_mode(output, width, height, mhz); + return; + } + + struct wlr_output_mode *mode, *best = NULL; wl_list_for_each(mode, &output->modes, link) { if (mode->width == width && mode->height == height) { if (mode->refresh == mhz) { @@ -99,6 +105,8 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { } if (oc && oc->width > 0 && oc->height > 0) { + sway_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, + oc->height, oc->refresh_rate); set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); } if (oc && oc->scale > 0) { From 163edc5a900fda58e006ed30e14ae10cc4aa13b3 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 12 Dec 2017 08:29:37 -0500 Subject: [PATCH 082/522] 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 | 227 ++++++++++++++++++----------- sway/input/keyboard.c | 18 +-- sway/input/seat.c | 104 ++++++------- sway/server.c | 2 +- 14 files changed, 258 insertions(+), 215 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 7de85ab7c..d80f5a39c 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 78bc161f4..7d7c463f3 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 19d40bdce..881805b49 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 5455601ee..bd94a357c 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 7710c6ab8..57f76ea9f 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 ec8e89b4e..7ae3c2a43 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 0e7f7060b..af067326f 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 3d3b1c444..df81d5bec 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 8ad6a5ec5..82775e2f5 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 724c8a82a..a7e84aa1e 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 ca80f2678..b7f5615c7 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -14,101 +14,27 @@ 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 seat; + return sway_seat_create(input, seat_name); } -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; - - // TODO device configuration - struct sway_seat *seat = input_manager_get_seat(input, default_seat); - sway_seat_add_device(seat, device); -} - -static void input_remove_notify(struct wl_listener *listener, void *data) { - struct sway_input_manager *input = - 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_manager *sway_input_manager_create( - struct sway_server *server) { - struct sway_input_manager *input = - calloc(1, sizeof(struct sway_input_manager)); - if (!input) { - return NULL; - } - // XXX probably don't need the full server - input->server = server; - - input->seats = create_list(); - - // create the default seat - input_manager_get_seat(input, default_seat); - - input->input_add.notify = input_add_notify; - wl_signal_add(&server->backend->events.input_add, &input->input_add); - - input->input_remove.notify = input_remove_notify; - wl_signal_add(&server->backend->events.input_remove, &input->input_remove); - - 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; - } - - 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; -} - -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)); +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) { @@ -132,10 +58,107 @@ char *libinput_dev_unique_id(struct libinput_device *device) { return identifier; } -bool sway_input_manager_swayc_has_focus(struct sway_input_manager *input, +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) { + struct sway_input_manager *input = + wl_container_of(listener, input, input_add); + struct wlr_input_device *device = data; + + 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, sway_device); +} + +static void input_remove_notify(struct wl_listener *listener, void *data) { + struct sway_input_manager *input = + wl_container_of(listener, input, input_remove); + struct wlr_input_device *device = data; + + 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( + struct sway_server *server) { + struct sway_input_manager *input = + calloc(1, sizeof(struct sway_input_manager)); + if (!input) { + return NULL; + } + // XXX probably don't need the full server + input->server = server; + + wl_list_init(&input->devices); + wl_list_init(&input->seats); + + // create the default seat + input_manager_get_seat(input, default_seat); + + input->input_add.notify = input_add_notify; + wl_signal_add(&server->backend->events.input_add, &input->input_add); + + input->input_remove.notify = input_remove_notify; + wl_signal_add(&server->backend->events.input_remove, &input->input_remove); + + return input; +} + +bool sway_input_manager_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]; + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { if (seat->focus == container) { return true; } @@ -143,3 +166,35 @@ bool sway_input_manager_swayc_has_focus(struct sway_input_manager *input, return false; } + +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); + } +} + +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; + } + + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + sway_seat_remove_device(seat, sway_device); + } + + seat = input_manager_get_seat(input, default_seat); + sway_seat_add_device(seat, sway_device); +} + +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); + } +} diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 31d254dfb..6a792c655 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 9c17250da..80c6424f2 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 7b9a5e8e5..32c8f03c5 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; } From 538903bc5ace56c1dab0f5287fb4d0bab78a0165 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 12 Dec 2017 09:02:30 -0500 Subject: [PATCH 083/522] config cleanup --- sway/commands/input/accel_profile.c | 6 +++-- sway/commands/input/click_method.c | 12 ++++++--- sway/commands/input/drag_lock.c | 9 ++++--- sway/commands/input/dwt.c | 6 +++-- sway/commands/input/events.c | 15 +++++++---- sway/commands/input/left_handed.c | 9 ++++--- sway/commands/input/middle_emulation.c | 12 ++++++--- sway/commands/input/natural_scroll.c | 9 ++++--- sway/commands/input/pointer_accel.c | 9 ++++--- sway/commands/input/scroll_method.c | 9 ++++--- sway/commands/input/tap.c | 9 ++++--- sway/config.c | 37 +++++++++++++++++--------- 12 files changed, 94 insertions(+), 48 deletions(-) diff --git a/sway/commands/input/accel_profile.c b/sway/commands/input/accel_profile.c index 13ded4319..9b5fb7a23 100644 --- a/sway/commands/input/accel_profile.c +++ b/sway/commands/input/accel_profile.c @@ -9,9 +9,11 @@ struct cmd_results *input_cmd_accel_profile(int argc, char **argv) { return error; } if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "accel_profile", "No input device defined."); + return cmd_results_new(CMD_FAILURE, "accel_profile", + "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "adaptive") == 0) { new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; diff --git a/sway/commands/input/click_method.c b/sway/commands/input/click_method.c index 40f075ceb..a0e3bddfc 100644 --- a/sway/commands/input/click_method.c +++ b/sway/commands/input/click_method.c @@ -5,15 +5,18 @@ #include "log.h" struct cmd_results *input_cmd_click_method(int argc, char **argv) { - sway_log(L_DEBUG, "click_method for device: %d %s", current_input_config==NULL, current_input_config->identifier); + sway_log(L_DEBUG, "click_method for device: %d %s", + current_input_config==NULL, current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "click_method", EXPECTED_AT_LEAST, 1))) { return error; } if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "click_method", "No input device defined."); + return cmd_results_new(CMD_FAILURE, "click_method", + "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "none") == 0) { new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE; @@ -22,7 +25,8 @@ struct cmd_results *input_cmd_click_method(int argc, char **argv) { } else if (strcasecmp(argv[0], "clickfinger") == 0) { new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; } else { - return cmd_results_new(CMD_INVALID, "click_method", "Expected 'click_method identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "enabled") == 0) { new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; } else if (strcasecmp(argv[0], "disabled") == 0) { new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; } else { - return cmd_results_new(CMD_INVALID, "drag_lock", "Expected 'drag_lock '"); + return cmd_results_new(CMD_INVALID, "drag_lock", + "Expected 'drag_lock '"); } input_cmd_apply(new_config); diff --git a/sway/commands/input/dwt.c b/sway/commands/input/dwt.c index f3cbf2522..0954575c1 100644 --- a/sway/commands/input/dwt.c +++ b/sway/commands/input/dwt.c @@ -11,14 +11,16 @@ struct cmd_results *input_cmd_dwt(int argc, char **argv) { if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "dwt", "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "enabled") == 0) { new_config->dwt = LIBINPUT_CONFIG_DWT_ENABLED; } else if (strcasecmp(argv[0], "disabled") == 0) { new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED; } else { - return cmd_results_new(CMD_INVALID, "dwt", "Expected 'dwt '"); + return cmd_results_new(CMD_INVALID, "dwt", + "Expected 'dwt '"); } input_cmd_apply(new_config); diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c index 4b2fdff5f..f44c0ec7c 100644 --- a/sway/commands/input/events.c +++ b/sway/commands/input/events.c @@ -5,24 +5,29 @@ #include "log.h" struct cmd_results *input_cmd_events(int argc, char **argv) { - sway_log(L_DEBUG, "events for device: %s", current_input_config->identifier); + sway_log(L_DEBUG, "events for device: %s", + current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { return error; } if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "events", "No input device defined."); + return cmd_results_new(CMD_FAILURE, "events", + "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "enabled") == 0) { new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; } else if (strcasecmp(argv[0], "disabled") == 0) { new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) { - new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; + new_config->send_events = + LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; } else { - return cmd_results_new(CMD_INVALID, "events", "Expected 'events '"); + return cmd_results_new(CMD_INVALID, "events", + "Expected 'events '"); } input_cmd_apply(new_config); diff --git a/sway/commands/input/left_handed.c b/sway/commands/input/left_handed.c index 715df2a12..dc8fcd562 100644 --- a/sway/commands/input/left_handed.c +++ b/sway/commands/input/left_handed.c @@ -9,16 +9,19 @@ struct cmd_results *input_cmd_left_handed(int argc, char **argv) { return error; } if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "left_handed", "No input device defined."); + return cmd_results_new(CMD_FAILURE, "left_handed", + "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "enabled") == 0) { new_config->left_handed = 1; } else if (strcasecmp(argv[0], "disabled") == 0) { new_config->left_handed = 0; } else { - return cmd_results_new(CMD_INVALID, "left_handed", "Expected 'left_handed '"); + return cmd_results_new(CMD_INVALID, "left_handed", + "Expected 'left_handed '"); } input_cmd_apply(new_config); diff --git a/sway/commands/input/middle_emulation.c b/sway/commands/input/middle_emulation.c index d31ce9509..e19964d81 100644 --- a/sway/commands/input/middle_emulation.c +++ b/sway/commands/input/middle_emulation.c @@ -9,16 +9,20 @@ struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) { return error; } if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "middle_emulation", "No input device defined."); + return cmd_results_new(CMD_FAILURE, "middle_emulation", + "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "enabled") == 0) { new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED; } else if (strcasecmp(argv[0], "disabled") == 0) { - new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; + new_config->middle_emulation = + LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; } else { - return cmd_results_new(CMD_INVALID, "middle_emulation", "Expected 'middle_emulation '"); + return cmd_results_new(CMD_INVALID, "middle_emulation", + "Expected 'middle_emulation '"); } input_cmd_apply(new_config); diff --git a/sway/commands/input/natural_scroll.c b/sway/commands/input/natural_scroll.c index 9d1dc506d..8272c5b38 100644 --- a/sway/commands/input/natural_scroll.c +++ b/sway/commands/input/natural_scroll.c @@ -9,16 +9,19 @@ struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) { return error; } if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "natural_scoll", "No input device defined."); + return cmd_results_new(CMD_FAILURE, "natural_scoll", + "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "enabled") == 0) { new_config->natural_scroll = 1; } else if (strcasecmp(argv[0], "disabled") == 0) { new_config->natural_scroll = 0; } else { - return cmd_results_new(CMD_INVALID, "natural_scroll", "Expected 'natural_scroll '"); + return cmd_results_new(CMD_INVALID, "natural_scroll", + "Expected 'natural_scroll '"); } input_cmd_apply(new_config); diff --git a/sway/commands/input/pointer_accel.c b/sway/commands/input/pointer_accel.c index 87fb5cff7..2c9db5bfb 100644 --- a/sway/commands/input/pointer_accel.c +++ b/sway/commands/input/pointer_accel.c @@ -9,13 +9,16 @@ struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { return error; } if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "pointer_accel", "No input device defined."); + return cmd_results_new(CMD_FAILURE, + "pointer_accel", "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); float pointer_accel = atof(argv[0]); if (pointer_accel < -1 || pointer_accel > 1) { - return cmd_results_new(CMD_INVALID, "pointer_accel", "Input out of range [-1, 1]"); + return cmd_results_new(CMD_INVALID, "pointer_accel", + "Input out of range [-1, 1]"); } new_config->pointer_accel = pointer_accel; diff --git a/sway/commands/input/scroll_method.c b/sway/commands/input/scroll_method.c index 98873938e..402771551 100644 --- a/sway/commands/input/scroll_method.c +++ b/sway/commands/input/scroll_method.c @@ -9,9 +9,11 @@ struct cmd_results *input_cmd_scroll_method(int argc, char **argv) { return error; } if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "scroll_method", "No input device defined."); + return cmd_results_new(CMD_FAILURE, "scroll_method", + "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "none") == 0) { new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; @@ -22,7 +24,8 @@ struct cmd_results *input_cmd_scroll_method(int argc, char **argv) { } else if (strcasecmp(argv[0], "on_button_down") == 0) { new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; } else { - return cmd_results_new(CMD_INVALID, "scroll_method", "Expected 'scroll_method '"); + return cmd_results_new(CMD_INVALID, "scroll_method", + "Expected 'scroll_method '"); } input_cmd_apply(new_config); diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c index 1109466f4..18a54087b 100644 --- a/sway/commands/input/tap.c +++ b/sway/commands/input/tap.c @@ -13,17 +13,20 @@ struct cmd_results *input_cmd_tap(int argc, char **argv) { if (!current_input_config) { return cmd_results_new(CMD_FAILURE, "tap", "No input device defined."); } - struct input_config *new_config = new_input_config(current_input_config->identifier); + struct input_config *new_config = + new_input_config(current_input_config->identifier); if (strcasecmp(argv[0], "enabled") == 0) { new_config->tap = LIBINPUT_CONFIG_TAP_ENABLED; } else if (strcasecmp(argv[0], "disabled") == 0) { new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED; } else { - return cmd_results_new(CMD_INVALID, "tap", "Expected 'tap '"); + return cmd_results_new(CMD_INVALID, "tap", + "Expected 'tap '"); } - sway_log(L_DEBUG, "apply-tap for device: %s", current_input_config->identifier); + sway_log(L_DEBUG, "apply-tap for device: %s", + current_input_config->identifier); input_cmd_apply(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/config.c b/sway/config.c index 7ae3c2a43..4bc74ee04 100644 --- a/sway/config.c +++ b/sway/config.c @@ -21,6 +21,7 @@ #include #endif #include +#include "sway/input/input-manager.h" #include "sway/commands.h" #include "sway/config.h" #include "sway/layout.h" @@ -48,7 +49,8 @@ static void config_defaults(struct sway_config *config) { if (!(config->cmd_queue = create_list())) goto cleanup; - if (!(config->current_mode = malloc(sizeof(struct sway_mode)))) 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; @@ -337,8 +339,9 @@ bool load_main_config(const char *file, bool is_active) { 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"); + 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/"; @@ -362,8 +365,12 @@ bool load_main_config(const char *file, bool is_active) { 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); + 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); @@ -392,7 +399,8 @@ bool load_main_config(const char *file, bool is_active) { return success; } -static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { +static bool load_include_config(const char *path, const char *parent_dir, + struct sway_config *config) { // save parent config const char *parent_config = config->current_config; @@ -402,7 +410,8 @@ static bool load_include_config(const char *path, const char *parent_dir, struct len = len + strlen(parent_dir) + 2; full_path = malloc(len * sizeof(char)); if (!full_path) { - sway_log(L_ERROR, "Unable to allocate full path to included config"); + sway_log(L_ERROR, + "Unable to allocate full path to included config"); return false; } snprintf(full_path, len, "%s/%s", parent_dir, path); @@ -421,7 +430,9 @@ static bool load_include_config(const char *path, const char *parent_dir, struct for (j = 0; j < config->config_chain->length; ++j) { char *old_path = config->config_chain->items[j]; if (strcmp(real_path, old_path) == 0) { - sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path); + sway_log(L_DEBUG, + "%s already included once, won't be included again.", + real_path); free(real_path); return false; } @@ -509,8 +520,8 @@ bool read_config(FILE *file, struct sway_config *config) { 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); + sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, + line, res->error, config->current_config); success = false; break; @@ -585,8 +596,7 @@ bool read_config(FILE *file, struct sway_config *config) { case CMD_BLOCK_INPUT: sway_log(L_DEBUG, "End of input block"); - // TODO: input - //current_input_config = NULL; + current_input_config = NULL; block = CMD_BLOCK_END; break; @@ -651,7 +661,8 @@ char *do_var_replacement(char *str) { char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); if (!newstr) { sway_log(L_ERROR, - "Unable to allocate replacement during variable expansion"); + "Unable to allocate replacement " + "during variable expansion"); break; } char *newptr = newstr; From c173d30b9203520c274f34eb72fc787aa33ca211 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 12 Dec 2017 10:55:20 -0500 Subject: [PATCH 084/522] 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 diff --git a/include/sway/commands.h b/include/sway/commands.h index 138e3c292..75340e036 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 d80f5a39c..9fcecfd65 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 57f76ea9f..6645436a1 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 000000000..9d86ac0ed --- /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 4bc74ee04..b77b8b4b6 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 b7f5615c7..b07a733ed 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 aa3dd2a72..fad1f88cf 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', From f3d880b0ec9eae246ef0d70dd67bed6d7488ab33 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 12 Dec 2017 19:40:17 +0100 Subject: [PATCH 085/522] Add scale and transform events to sway_output --- include/sway/output.h | 8 ++++++++ sway/config/output.c | 2 ++ sway/desktop/output.c | 32 +++++++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 895cb07d4..118693986 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -12,8 +12,16 @@ struct sway_output { struct sway_container *swayc; struct sway_server *server; struct timespec last_frame; + + struct { + struct wl_signal scale; + struct wl_signal transform; + } events; + struct wl_listener frame; struct wl_listener resolution; + struct wl_listener scale; + struct wl_listener transform; }; #endif diff --git a/sway/config/output.c b/sway/config/output.c index e6e680d3d..b06c7c0e9 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -112,10 +112,12 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { if (oc && oc->scale > 0) { sway_log(L_DEBUG, "Set %s scale to %d", oc->name, oc->scale); wlr_output_set_scale(wlr_output, oc->scale); + wl_signal_emit(&output->sway_output->events.scale, output->sway_output); } 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); + wl_signal_emit(&output->sway_output->events.transform, output->sway_output); } // Find position for it diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 7eb48bdf0..f44cda1a0 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -98,17 +98,40 @@ static void output_resolution_notify(struct wl_listener *listener, void *data) { arrange_windows(soutput->swayc, -1, -1); } +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); +} + +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); +} + void output_add_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_add); struct wlr_output *wlr_output = data; sway_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); struct sway_output *output = calloc(1, sizeof(struct sway_output)); + if (!output) { + return; + } output->wlr_output = wlr_output; output->server = server; - output->swayc = new_output(output); - if (wl_list_length(&wlr_output->modes) > 0) { + wl_signal_init(&output->events.scale); + wl_signal_init(&output->events.transform); + + output->swayc = new_output(output); + if (!output->swayc) { + free(output); + return; + } + + if (!wl_list_empty(&wlr_output->modes)) { struct wlr_output_mode *mode = NULL; mode = wl_container_of((&wlr_output->modes)->prev, mode, link); wlr_output_set_mode(wlr_output, mode); @@ -116,9 +139,12 @@ void output_add_notify(struct wl_listener *listener, void *data) { output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); - output->resolution.notify = output_resolution_notify; wl_signal_add(&wlr_output->events.resolution, &output->resolution); + output->scale.notify = output_scale_notify; + wl_signal_add(&output->events.scale, &output->scale); + output->transform.notify = output_transform_notify; + wl_signal_add(&output->events.transform, &output->transform); arrange_windows(output->swayc, -1, -1); } From c7abb77f2217cc4d5642ef1650f7fc75e1c1a9a4 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 12 Dec 2017 20:02:01 +0100 Subject: [PATCH 086/522] Listen to output layout change --- include/sway/container.h | 4 ++-- include/sway/layout.h | 8 ++++++++ sway/config/output.c | 17 ++++++++++------- sway/desktop/output.c | 12 ++++-------- sway/desktop/xwayland.c | 6 +++--- sway/tree/container.c | 9 --------- sway/tree/layout.c | 17 ++++++++++++++++- 7 files changed, 43 insertions(+), 30 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index e3f84fc64..b15e04285 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -57,9 +57,9 @@ enum swayc_border_types { B_NORMAL, /**< Normal border with title bar */ }; +struct sway_root; struct sway_output; struct sway_view; -struct wlr_output_layout; /** * Stores information about a container. @@ -69,7 +69,7 @@ struct wlr_output_layout; struct sway_container { union { // TODO: Encapsulate state for other node types as well like C_CONTAINER - struct wlr_output_layout *output_layout; // C_ROOT + struct sway_root *sway_root; // C_ROOT struct sway_output *sway_output; // C_OUTPUT struct sway_view *sway_view; // C_VIEW }; diff --git a/include/sway/layout.h b/include/sway/layout.h index f3b62b05e..bfd96a026 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h @@ -1,8 +1,16 @@ #ifndef _SWAY_LAYOUT_H #define _SWAY_LAYOUT_H +#include + struct sway_container; +struct sway_root { + struct wlr_output_layout *output_layout; + + struct wl_listener output_layout_change; +}; + void init_layout(void); void add_child(struct sway_container *parent, struct sway_container *child); struct sway_container *remove_child(struct sway_container *child); diff --git a/sway/config/output.c b/sway/config/output.c index b06c7c0e9..ed47a617c 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -99,7 +99,8 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { struct wlr_output *wlr_output = output->sway_output->wlr_output; if (oc && oc->enabled == 0) { - wlr_output_layout_remove(root_container.output_layout, wlr_output); + wlr_output_layout_remove(root_container.sway_root->output_layout, + wlr_output); destroy_output(output); return; } @@ -117,19 +118,21 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { 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); - wl_signal_emit(&output->sway_output->events.transform, output->sway_output); + wl_signal_emit(&output->sway_output->events.transform, + output->sway_output); } // 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); - wlr_output_layout_add(root_container.output_layout, wlr_output, oc->x, - oc->y); + wlr_output_layout_add(root_container.sway_root->output_layout, + wlr_output, oc->x, oc->y); } else { - wlr_output_layout_add_auto(root_container.output_layout, wlr_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.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; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index f44cda1a0..bcdaa7d2f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -72,8 +72,7 @@ static void output_frame_view(swayc_t *view, void *data) { } static void output_frame_notify(struct wl_listener *listener, void *data) { - struct sway_output *soutput = wl_container_of( - listener, soutput, frame); + struct sway_output *soutput = wl_container_of(listener, soutput, frame); struct wlr_output *wlr_output = data; struct sway_server *server = soutput->server; @@ -93,20 +92,17 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } static void output_resolution_notify(struct wl_listener *listener, void *data) { - struct sway_output *soutput = wl_container_of( - listener, soutput, resolution); + struct sway_output *soutput = wl_container_of(listener, soutput, resolution); arrange_windows(soutput->swayc, -1, -1); } static void output_scale_notify(struct wl_listener *listener, void *data) { - struct sway_output *soutput = wl_container_of( - listener, soutput, scale); + struct sway_output *soutput = wl_container_of(listener, soutput, scale); arrange_windows(soutput->swayc, -1, -1); } static void output_transform_notify(struct wl_listener *listener, void *data) { - struct sway_output *soutput = wl_container_of( - listener, soutput, transform); + struct sway_output *soutput = wl_container_of(listener, soutput, transform); arrange_windows(soutput->swayc, -1, -1); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 65c7e1ec3..e3799d2d1 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -55,7 +55,7 @@ static void set_position(struct sway_view *view, double ox, double oy) { if (!sway_assert(root, "output must be within tree to set position")) { return; } - struct wlr_output_layout *layout = root->output_layout; + struct wlr_output_layout *layout = root->sway_root->output_layout; struct wlr_output_layout_output *loutput = wlr_output_layout_get(layout, output->sway_output->wlr_output); if (!sway_assert(loutput, "output must be within layout to set position")) { @@ -147,14 +147,14 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { // TODO remove from the tree when the surface goes away (unmapped) sway_view->surface = xsurface->surface; sway_surface->view = sway_view; - + // TODO: // - Wire up listeners // - Handle popups // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria - + sway_surface->commit.notify = handle_commit; wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); sway_surface->destroy.notify = handle_destroy; diff --git a/sway/tree/container.c b/sway/tree/container.c index e4c27d614..f70bccdc6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -26,13 +26,6 @@ void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, } } -static void update_root_geometry() { - struct wlr_box *box = - wlr_output_layout_get_box(root_container.output_layout, NULL); - root_container.width = box->width; - root_container.height = box->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; @@ -94,7 +87,6 @@ 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; } @@ -195,7 +187,6 @@ swayc_t *destroy_output(swayc_t *output) { sway_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); free_swayc(output); - update_root_geometry(); return &root_container; } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index cb39a361a..fd17f8a5f 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -7,6 +7,7 @@ #include #include #include "sway/container.h" +#include "sway/layout.h" #include "sway/output.h" #include "sway/view.h" #include "list.h" @@ -14,13 +15,27 @@ swayc_t root_container; +static void output_layout_change_notify(struct wl_listener *listener, void *data) { + struct wlr_box *box = wlr_output_layout_get_box( + root_container.sway_root->output_layout, NULL); + root_container.width = box->width; + root_container.height = box->height; +} + void init_layout(void) { root_container.id = 0; // normally assigned in new_swayc() root_container.type = C_ROOT; root_container.layout = L_NONE; root_container.name = strdup("root"); root_container.children = create_list(); - root_container.output_layout = wlr_output_layout_create(); + + root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); + root_container.sway_root->output_layout = wlr_output_layout_create(); + + root_container.sway_root->output_layout_change.notify = + output_layout_change_notify; + wl_signal_add(&root_container.sway_root->output_layout->events.change, + &root_container.sway_root->output_layout_change); } void add_child(swayc_t *parent, swayc_t *child) { From d293c429424a9f96c3fc8143af457645326e7a0e Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 12 Dec 2017 21:09:51 +0100 Subject: [PATCH 087/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 4dd8e94c5..139d7800e 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 be78358a6..23792855c 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 ed47a617c..6371763f8 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 bcdaa7d2f..3fd49846b 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) { From a4619e98c462690f14baf5c0c72c25553e3c6d51 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 13 Dec 2017 15:52:18 +0100 Subject: [PATCH 088/522] Update output containers on output layout change --- include/sway/output.h | 8 -------- sway/config/output.c | 5 +---- sway/desktop/output.c | 47 +++++-------------------------------------- sway/tree/layout.c | 20 +++++++++++++++--- 4 files changed, 23 insertions(+), 57 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 118693986..7ca02d7b5 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -13,15 +13,7 @@ struct sway_output { struct sway_server *server; struct timespec last_frame; - struct { - struct wl_signal scale; - struct wl_signal transform; - } events; - struct wl_listener frame; - struct wl_listener resolution; - struct wl_listener scale; - struct wl_listener transform; }; #endif diff --git a/sway/config/output.c b/sway/config/output.c index 6371763f8..8d946386f 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -113,13 +113,10 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { if (oc && oc->scale > 0) { sway_log(L_DEBUG, "Set %s scale to %d", oc->name, oc->scale); wlr_output_set_scale(wlr_output, oc->scale); - wl_signal_emit(&output->sway_output->events.scale, output->sway_output); } 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); - wl_signal_emit(&output->sway_output->events.transform, - output->sway_output); + wlr_output_set_transform(wlr_output, oc->transform); } // Find position for it diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 3fd49846b..2177ad743 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -91,32 +91,6 @@ 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 *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 *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 *output = wl_container_of(listener, output, transform); - output_update_size(output); -} - void output_add_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_add); struct wlr_output *wlr_output = data; @@ -129,8 +103,11 @@ void output_add_notify(struct wl_listener *listener, void *data) { output->wlr_output = wlr_output; output->server = server; - wl_signal_init(&output->events.scale); - wl_signal_init(&output->events.transform); + if (!wl_list_empty(&wlr_output->modes)) { + struct wlr_output_mode *mode = + wl_container_of(wlr_output->modes.prev, mode, link); + wlr_output_set_mode(wlr_output, mode); + } output->swayc = new_output(output); if (!output->swayc) { @@ -138,22 +115,8 @@ void output_add_notify(struct wl_listener *listener, void *data) { return; } - if (!wl_list_empty(&wlr_output->modes)) { - struct wlr_output_mode *mode = NULL; - mode = wl_container_of((&wlr_output->modes)->prev, mode, link); - wlr_output_set_mode(wlr_output, mode); - } - output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); - output->resolution.notify = output_resolution_notify; - wl_signal_add(&wlr_output->events.resolution, &output->resolution); - output->scale.notify = output_scale_notify; - wl_signal_add(&output->events.scale, &output->scale); - output->transform.notify = output_transform_notify; - wl_signal_add(&output->events.transform, &output->transform); - - arrange_windows(output->swayc, -1, -1); } void output_remove_notify(struct wl_listener *listener, void *data) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index fd17f8a5f..65382231b 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -16,10 +16,24 @@ swayc_t root_container; static void output_layout_change_notify(struct wl_listener *listener, void *data) { - struct wlr_box *box = wlr_output_layout_get_box( + struct wlr_box *layout_box = wlr_output_layout_get_box( root_container.sway_root->output_layout, NULL); - root_container.width = box->width; - root_container.height = box->height; + 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_output *output = output_container->sway_output; + + struct wlr_box *output_box = wlr_output_layout_get_box( + root_container.sway_root->output_layout, output->wlr_output); + output_container->x = output_box->x; + output_container->y = output_box->y; + output_container->width = output_box->width; + output_container->height = output_box->height; + } + + arrange_windows(&root_container, -1, -1); } void init_layout(void) { From ec2fd6e5c0217ae58a03eca1e83d85f02c739643 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 13 Dec 2017 21:47:37 +0100 Subject: [PATCH 089/522] Handle output remove --- sway/desktop/output.c | 16 +++++++++++++++- sway/tree/layout.c | 6 ++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2177ad743..ad843b316 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -123,5 +123,19 @@ void output_remove_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_remove); struct wlr_output *wlr_output = data; sway_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); - // TODO + + swayc_t *output_container = NULL; + for (int i = 0 ; i < root_container.children->length; ++i) { + swayc_t *child = root_container.children->items[i]; + if (child->type == C_OUTPUT && + child->sway_output->wlr_output == wlr_output) { + output_container = child; + break; + } + } + if (!output_container) { + return; + } + + destroy_output(output_container); } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 65382231b..4bcf0e2fd 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -23,10 +23,16 @@ static void output_layout_change_notify(struct wl_listener *listener, void *data for (int i = 0 ; i < root_container.children->length; ++i) { swayc_t *output_container = root_container.children->items[i]; + if (output_container->type != C_OUTPUT) { + continue; + } struct sway_output *output = output_container->sway_output; struct wlr_box *output_box = wlr_output_layout_get_box( root_container.sway_root->output_layout, output->wlr_output); + if (!output_box) { + continue; + } output_container->x = output_box->x; output_container->y = output_box->y; output_container->width = output_box->width; From 4d389f8b6523af741761009effd4d6dd79156afe Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 14 Dec 2017 00:45:47 +0100 Subject: [PATCH 090/522] Replace refresh_rate and position by mode in output command --- sway/commands/output.c | 87 ++++++++++++++++++++++++++---------------- sway/config/output.c | 2 +- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/sway/commands/output.c b/sway/commands/output.c index 23792855c..daaacad7e 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -42,61 +42,84 @@ struct cmd_results *cmd_output(int argc, char **argv) { if (strcasecmp(command, "disable") == 0) { output->enabled = 0; - } else if (strcasecmp(command, "resolution") == 0 || strcasecmp(command, "res") == 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 resolution argument."); + error = cmd_results_new(CMD_INVALID, "output", + "Missing mode argument."); goto fail; } - char *res = argv[i]; - char *x = strchr(res, 'x'); + int width = -1, height = -1; - if (x != NULL) { + float refresh_rate = -1; + + char *end; + width = strtol(argv[i], &end, 10); + if (*end) { // 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)."); + 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 (legacy) + ++i; + 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; } - 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]); + output->refresh_rate = refresh_rate; } 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, ','); + char *pos = argv[i]; + char *c = strchr(pos, ','); int x = -1, y = -1; if (c != NULL) { // Format is 1234,4321 *c = '\0'; - x = atoi(res); + x = atoi(pos); y = atoi(c + 1); *c = ','; } else { // Format is 1234 4321 - x = atoi(res); + x = atoi(pos); if (++i >= argc) { error = cmd_results_new(CMD_INVALID, "output", "Missing position argument (y)."); goto fail; } - res = argv[i]; - y = atoi(res); + pos = argv[i]; + y = atoi(pos); } output->x = x; output->y = y; @@ -218,11 +241,11 @@ struct cmd_results *cmd_output(int argc, char **argv) { 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)", + sway_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " + "position %d,%d scale %d transform %d) (bg %s %s)", output->name, output->enabled, output->width, - output->height, output->x, output->y, output->scale, - output->transform, output->refresh_rate, + output->height, output->refresh_rate, output->x, output->y, + output->scale, output->transform, output->background, output->background_option); if (output->name) { diff --git a/sway/config/output.c b/sway/config/output.c index 8d946386f..dc9ee37c3 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -20,7 +20,7 @@ struct output_config *new_output_config() { return NULL; } oc->enabled = -1; - oc->width = oc->height -1; + oc->width = oc->height = -1; oc->refresh_rate = -1; oc->x = oc->y = -1; oc->scale = -1; From 9254c5a93f1a38612d5391e34e4fe3b6c9e433a7 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 14 Dec 2017 00:50:01 +0100 Subject: [PATCH 091/522] Fail if unknown output subcommand --- sway/commands/output.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sway/commands/output.c b/sway/commands/output.c index daaacad7e..16b711f19 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -192,7 +192,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { 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); + error = cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s).", src); goto fail; } free(src); @@ -213,7 +213,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { } } if (!src || access(src, F_OK) == -1) { - error = cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src); + error = cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s).", src); wordfree(&p); goto fail; } @@ -227,6 +227,9 @@ struct cmd_results *cmd_output(int argc, char **argv) { i += j; } + } else { + error = cmd_results_new(CMD_INVALID, "output", "Invalid output subcommand: %s.", command); + goto fail; } } From cba592b3d2c516cab9f4e8325037dfdf6e30cb9a Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 14 Dec 2017 02:23:33 +0100 Subject: [PATCH 092/522] Use strtol instead of atoi in output command --- sway/commands/output.c | 118 ++++++++++++++++++++++++++--------------- sway/tree/container.c | 2 - 2 files changed, 76 insertions(+), 44 deletions(-) diff --git a/sway/commands/output.c b/sway/commands/output.c index 16b711f19..d71e4d8d4 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -34,8 +34,6 @@ struct cmd_results *cmd_output(int argc, char **argv) { } output->name = strdup(name); - // TODO: atoi doesn't handle invalid numbers - int i; for (i = 1; i < argc; ++i) { const char *command = argv[i]; @@ -80,9 +78,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { } } } else { - // Format is 1234 4321 (legacy) - ++i; - if (i >= argc) { + // Format is 1234 4321 + if (++i >= argc) { error = cmd_results_new(CMD_INVALID, "output", "Missing mode argument (height)."); goto fail; @@ -97,41 +94,66 @@ struct cmd_results *cmd_output(int argc, char **argv) { output->width = width; output->height = height; output->refresh_rate = refresh_rate; - } else if (strcasecmp(command, "position") == 0 || strcasecmp(command, "pos") == 0) { + } else if (strcasecmp(command, "position") == 0 || + strcasecmp(command, "pos") == 0) { if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", "Missing position argument."); + error = cmd_results_new(CMD_INVALID, "output", + "Missing position argument."); goto fail; } - char *pos = argv[i]; - char *c = strchr(pos, ','); + int x = -1, y = -1; - if (c != NULL) { + + char *end; + x = strtol(argv[i], &end, 10); + if (*end) { // Format is 1234,4321 - *c = '\0'; - x = atoi(pos); - y = atoi(c + 1); - *c = ','; - } else { - // Format is 1234 4321 - x = atoi(pos); - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", "Missing position argument (y)."); + 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; } - pos = argv[i]; - y = atoi(pos); } + 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."); + error = cmd_results_new(CMD_INVALID, "output", + "Missing scale parameter."); + goto fail; + } + char *end; + output->scale = strtol(argv[i], &end, 10); + if (*end) { + error = cmd_results_new(CMD_INVALID, "output", + "Invalid scale."); 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."); + error = cmd_results_new(CMD_INVALID, "output", + "Missing transform parameter."); goto fail; } char *value = argv[i]; @@ -152,17 +174,21 @@ struct cmd_results *cmd_output(int argc, char **argv) { } 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."); + error = cmd_results_new(CMD_INVALID, "output", + "Invalid output transform."); goto fail; } - } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) { + } 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."); + 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`."); + error = cmd_results_new(CMD_INVALID, "output", + "Missing background scaling mode or `solid_color`."); goto fail; } if (strcasecmp(argv[i + 1], "solid_color") == 0) { @@ -175,7 +201,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { 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) { + 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; @@ -186,13 +213,15 @@ struct cmd_results *cmd_output(int argc, char **argv) { } } if (!valid) { - error = cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode."); + 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); + error = cmd_results_new(CMD_INVALID, "output", + "Invalid syntax (%s).", src); goto fail; } free(src); @@ -205,15 +234,18 @@ struct cmd_results *cmd_output(int argc, char **argv) { if (src) { sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); } else { - sway_log(L_ERROR, "Unable to allocate background source"); + sway_log(L_ERROR, + "Unable to allocate background source"); } free(conf); } else { - sway_log(L_ERROR, "Unable to allocate background source"); + 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); + error = cmd_results_new(CMD_INVALID, "output", + "Background file unreadable (%s).", src); wordfree(&p); goto fail; } @@ -228,7 +260,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { i += j; } } else { - error = cmd_results_new(CMD_INVALID, "output", "Invalid output subcommand: %s.", command); + error = cmd_results_new(CMD_INVALID, "output", + "Invalid output subcommand: %s.", command); goto fail; } } @@ -245,11 +278,10 @@ 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)", - output->name, output->enabled, output->width, - output->height, output->refresh_rate, output->x, output->y, - output->scale, output->transform, - output->background, output->background_option); + "position %d,%d scale %d 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); if (output->name) { // Try to find the output container and apply configuration now. If @@ -258,11 +290,13 @@ struct cmd_results *cmd_output(int argc, char **argv) { 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))) { + 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 + // Stop looking if the output config isn't applicable to all + // outputs break; } } diff --git a/sway/tree/container.c b/sway/tree/container.c index f70bccdc6..5df10bcb8 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -179,8 +179,6 @@ swayc_t *destroy_output(swayc_t *output) { 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); } } From 92fef27eaa0b52c9d37bdabff14ae21cd6660f46 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 14 Dec 2017 11:11:56 -0500 Subject: [PATCH 093/522] 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 | 181 ++++++++++++++++++----------- sway/meson.build | 3 +- 15 files changed, 543 insertions(+), 174 deletions(-) delete mode 100644 sway/commands/input/seat.c create mode 100644 sway/commands/seat.c create mode 100644 sway/commands/seat/attach.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 75340e036..ce74e1ed3 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 9fcecfd65..5df5d61e8 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 7d7c463f3..cdcffab64 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 881805b49..89cde3fa2 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 bd94a357c..db69f83ef 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 6645436a1..e003e06d0 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 9d86ac0ed..000000000 --- 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 000000000..4f9e259b3 --- /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 000000000..996c1bdac --- /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 b77b8b4b6..52633ad8d 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 217c2ddb6..3aa2d1bcc 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 b07a733ed..1950b6d91 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); } - 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); + 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); + } + } + } + + 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 6a792c655..53db32700 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 80c6424f2..1b25419bd 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_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; + } + + 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); + break; + case WLR_INPUT_DEVICE_KEYBOARD: + 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: configure other devices"); + break; + } } void sway_seat_add_device(struct sway_seat *seat, - struct sway_input_device *device) { - if (sway_seat_has_device(seat, device)) { + struct sway_input_device *input_device) { + if (sway_seat_get_device(seat, input_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; - case WLR_INPUT_DEVICE_KEYBOARD: - seat_add_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: add other devices"); - break; + 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; } - list_add(seat->devices, device); -} + seat_device->sway_seat = seat; + seat_device->input_device = input_device; + wl_list_insert(&seat->devices, &seat_device->link); -static void seat_remove_keyboard(struct sway_seat *seat, - struct sway_input_device *device) { - if (device && device->keyboard) { - sway_keyboard_destroy(device->keyboard); - } -} - -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); + 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)) { + 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); + + if (!seat_device) { return; } - 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; - } - - 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 fad1f88cf..ad8160eb5 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', From 9eecbb5d8a988a0dded57ead1982dd0121071454 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 15 Dec 2017 05:22:51 -0500 Subject: [PATCH 094/522] 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 diff --git a/include/sway/commands.h b/include/sway/commands.h index ce74e1ed3..61950d0d3 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 5df5d61e8..9bfda259e 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 e003e06d0..b8948fb72 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 000000000..9a9ce044d --- /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 000000000..14a50ffb4 --- /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 000000000..67eb5342c --- /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 000000000..3eda0bdd8 --- /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 000000000..c7f93ad42 --- /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 52633ad8d..4e34aa8c7 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 53db32700..2ab0206aa 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 363f4d96c..25032aa08 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 ad8160eb5..c81e1c2cf 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', From 030fcb64da90242718b7276a4c98cd0b2a346aad Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 15 Dec 2017 05:57:28 -0500 Subject: [PATCH 095/522] keyboard cleanup --- sway/input/keyboard.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 2ab0206aa..b9b571a67 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -10,10 +10,9 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { struct wlr_input_device *wlr_device = keyboard->seat_device->input_device->wlr_device; struct wlr_event_keyboard_key *event = data; - 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); + wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, + event->keycode, event->state); } static void handle_keyboard_modifiers(struct wl_listener *listener, @@ -23,7 +22,6 @@ static void handle_keyboard_modifiers(struct wl_listener *listener, 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); } @@ -50,6 +48,8 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { memset(&rules, 0, sizeof(rules)); struct input_config *input_config = keyboard->seat_device->input_device->config; + struct wlr_input_device *wlr_device = + keyboard->seat_device->input_device->wlr_device; if (input_config && input_config->xkb_layout) { rules.layout = input_config->xkb_layout; @@ -88,18 +88,16 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { 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); + wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); + wlr_keyboard_set_repeat_info(wlr_device->keyboard, 25, 600); xkb_context_unref(context); wl_list_remove(&keyboard->keyboard_key.link); - wl_signal_add( - &keyboard->seat_device->input_device->wlr_device->keyboard->events.key, - &keyboard->keyboard_key); + wl_signal_add(&wlr_device->keyboard->events.key, &keyboard->keyboard_key); keyboard->keyboard_key.notify = handle_keyboard_key; wl_list_remove(&keyboard->keyboard_modifiers.link); - wl_signal_add( - &keyboard->seat_device->input_device->wlr_device->keyboard->events.modifiers, + wl_signal_add( &wlr_device->keyboard->events.modifiers, &keyboard->keyboard_modifiers); keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; } From b3a0309f2612523450b2b960c81d1c4895880454 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 07:39:22 -0500 Subject: [PATCH 096/522] fix logging issue for new wlroots --- sway/input/seat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 1b25419bd..907c610ac 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -168,7 +168,7 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { output->scale); sway_assert(!result, - "Cannot load xcursor theme for output '%s' with scale %d", + "Cannot load xcursor theme for output '%s' with scale %f", output->name, output->scale); } From 2624f55f8decf7f1cc1dd64a3f72b130f7ef77e8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 08:19:33 -0500 Subject: [PATCH 097/522] input and seat command docs --- sway/sway-input.5.txt | 50 +++++++++++++++++++++++++++++++++++++++---- sway/sway.1.txt | 23 +------------------- sway/sway.5.txt | 7 +++++- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/sway/sway-input.5.txt b/sway/sway-input.5.txt index f0c8f87c1..d4652a828 100644 --- a/sway/sway-input.5.txt +++ b/sway/sway-input.5.txt @@ -1,5 +1,5 @@ ///// -vim:set ts=4 sw=4 tw=82 noet: +vim:set ft=asciidoc ts=4 sw=4 tw=82 noet: ///// sway-input (5) ============== @@ -11,12 +11,37 @@ sway-input - input configuration file and commands Description ----------- -Sway allows for configuration of libinput devices within the sway configuration file. +Sway allows for configuration of devices within the sway configuration file. sway-input commands must be used inside an _input { }_ block in the config. To obtain a list of available device identifiers, run **swaymsg -t get_inputs**. -Commands --------- +Input Commands +-------------- + +Keyboard Configuration +~~~~~~~~~~~~~~~~~~~~~~ + +For more information on these xkb configuration options, see +**xkeyboard-config**(7). + +**input** xkb_layout :: + Sets the layout of the keyboard like _us_ or _de_. + +**input** xkb_model :: + Sets the model of the keyboard. This has an influence for some extra keys your + keyboard might have. + +**input** xkb_options :: + Sets extra xkb configuration options for the keyboard. + +**input** xkb_rules :: + Sets files of rules to be used for keyboard mapping composition. + +**input** xkb_variant :: + Sets the variant of the keyboard like _dvorak_ or _colemak_. + +Libinput Configuration +~~~~~~~~~~~~~~~~~~~~~~ **input** accel_profile :: Sets the pointer acceleration profile for the specified input device. @@ -53,6 +78,23 @@ Commands **input** tap :: Enables or disables tap for specified input device. +Seat Configuration +------------------ + +Configure options for multiseat mode. sway-seat commands must be used inside a +_seat { }_ block in the config. + +A _seat_ is a collection of input devices that act independently of each other. +Seats are identified by name and the default seat is _seat0_ if no seats are +configured. Each seat has an independent keyboard focus and a separate cursor that +is controlled by the pointer devices of the seat. This is useful for multiple +people using the desktop at the same time with their own devices (each sitting in +their own "seat"). + +**seat** attach :: + Attach an input device to this seat by its input identifier. A special value + of _*_ will attach all devices to the seat. + See Also -------- diff --git a/sway/sway.1.txt b/sway/sway.1.txt index 14ab9f497..17fc13da2 100644 --- a/sway/sway.1.txt +++ b/sway/sway.1.txt @@ -1,5 +1,5 @@ ///// -vim:set ts=4 sw=4 tw=82 noet: +vim:set ft=asciidoc ts=4 sw=4 tw=82 noet: ///// :quotes.~: @@ -93,27 +93,6 @@ The following environment variables have an effect on sway: *SWAYSOCK*:: Specifies the path to the sway IPC socket. -*WLC_DRM_DEVICE*:: - Specifies the device to use in DRM mode. - -*WLC_SHM*:: - Set 1 to force EGL clients to use shared memory. - -*WLC_OUTPUTS*:: - Number of fake outputs to use when running in X11 mode. - -*WLC_XWAYLAND*:: - Set to 0 to disable Xwayland support. - -*WLC_LIBINPUT*:: - Set to 1 to force libinput (even in X11 mode). - -*WLC_REPEAT_DELAY*:: - Configures the keyboard repeat delay. - -*WLC_REPEAT_RATE*:: - Configures the keyboard repeat rate. - *XKB_DEFAULT_RULES*, *XKB_DEFAULT_MODEL*, *XKB_DEFAULT_LAYOUT*, *XKB_DEFAULT_VARIANT*, *XKB_DEFAULT_OPTIONS*:: Configures the xkb keyboard settings. See xkeyboard-config(7). diff --git a/sway/sway.5.txt b/sway/sway.5.txt index 2a4ef2056..afd3c9fad 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -312,7 +312,7 @@ The default colors are: **hide_edge_borders** :: Hide window borders adjacent to the screen edges. Default is _none_. -**input** :: +**input** :: Append _{_ to this command, the following lines will be commands to configure the named input device, and _}_ on its own line will close the block. + @@ -320,6 +320,11 @@ The default colors are: + See **sway-input**(5) for details. +**seat** :: + Append _{_ to this command, the following lines will be commands to configure + the named seat, and _}_ on its own line will close the block. + See **sway-input**(5) for details. + **kill**:: Kills (force-closes) the currently-focused container and all of its children. From d3d36047605e57e81d7452173a913a0c04cbcfc1 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 08:33:22 -0500 Subject: [PATCH 098/522] fix header includes --- include/sway/input/cursor.h | 4 ++-- include/sway/input/input-manager.h | 4 ++-- include/sway/input/keyboard.h | 5 +++++ include/sway/input/seat.h | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index cc529de67..2f70cf4b4 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -1,5 +1,5 @@ -#ifndef _SWAY_CURSOR_H -#define _SWAY_CURSOR_H +#ifndef _SWAY_INPUT_CURSOR_H +#define _SWAY_INPUT_CURSOR_H #include "sway/input/seat.h" diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index cdcffab64..53064eed2 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -1,5 +1,5 @@ -#ifndef _SWAY_INPUT_MANAGER_H -#define _SWAY_INPUT_MANAGER_H +#ifndef _SWAY_INPUT_INPUT_MANAGER_H +#define _SWAY_INPUT_INPUT_MANAGER_H #include #include "sway/server.h" #include "sway/config.h" diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index 89cde3fa2..0b0c15497 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h @@ -1,3 +1,6 @@ +#ifndef _SWAY_INPUT_KEYBOARD_H +#define _SWAY_INPUT_KEYBOARD_H + #include "sway/input/seat.h" struct sway_keyboard { @@ -16,3 +19,5 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, void sway_keyboard_configure(struct sway_keyboard *keyboard); void sway_keyboard_destroy(struct sway_keyboard *keyboard); + +#endif diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index db69f83ef..d703f94c5 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -1,5 +1,5 @@ -#ifndef _SWAY_SEAT_H -#define _SWAY_SEAT_H +#ifndef _SWAY_INPUT_SEAT_H +#define _SWAY_INPUT_SEAT_H #include #include "sway/input/input-manager.h" From f4a5a0ead4c8b155985c242db1fa5de5fa4807a0 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 11:25:59 -0500 Subject: [PATCH 099/522] put seat and input config in their own files --- sway/config.c | 222 -------------------------------------------- sway/config/input.c | 105 +++++++++++++++++++++ sway/config/seat.c | 127 +++++++++++++++++++++++++ sway/meson.build | 2 + 4 files changed, 234 insertions(+), 222 deletions(-) create mode 100644 sway/config/input.c create mode 100644 sway/config/seat.c diff --git a/sway/config.c b/sway/config.c index 4e34aa8c7..b591ae9e4 100644 --- a/sway/config.c +++ b/sway/config.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #ifdef __linux__ @@ -229,227 +228,6 @@ 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) { - free(dst->identifier); - dst->identifier = strdup(src->identifier); - } - if (src->accel_profile != INT_MIN) { - dst->accel_profile = src->accel_profile; - } - if (src->click_method != INT_MIN) { - dst->click_method = src->click_method; - } - if (src->drag_lock != INT_MIN) { - dst->drag_lock = src->drag_lock; - } - if (src->dwt != INT_MIN) { - dst->dwt = src->dwt; - } - if (src->middle_emulation != INT_MIN) { - dst->middle_emulation = src->middle_emulation; - } - if (src->natural_scroll != INT_MIN) { - dst->natural_scroll = src->natural_scroll; - } - if (src->pointer_accel != FLT_MIN) { - dst->pointer_accel = src->pointer_accel; - } - if (src->scroll_method != INT_MIN) { - dst->scroll_method = src->scroll_method; - } - if (src->send_events != INT_MIN) { - dst->send_events = src->send_events; - } - if (src->tap != INT_MIN) { - dst->tap = src->tap; - } - 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) { - if (!ic) { - return; - } - free(ic->identifier); - free(ic); -} - -int input_identifier_cmp(const void *item, const void *data) { - const struct input_config *ic = item; - const char *identifier = data; - return strcmp(ic->identifier, identifier); -} - -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) { diff --git a/sway/config/input.c b/sway/config/input.c new file mode 100644 index 000000000..6f8d31f75 --- /dev/null +++ b/sway/config/input.c @@ -0,0 +1,105 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include "sway/config.h" +#include "log.h" + +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) { + free(dst->identifier); + dst->identifier = strdup(src->identifier); + } + if (src->accel_profile != INT_MIN) { + dst->accel_profile = src->accel_profile; + } + if (src->click_method != INT_MIN) { + dst->click_method = src->click_method; + } + if (src->drag_lock != INT_MIN) { + dst->drag_lock = src->drag_lock; + } + if (src->dwt != INT_MIN) { + dst->dwt = src->dwt; + } + if (src->middle_emulation != INT_MIN) { + dst->middle_emulation = src->middle_emulation; + } + if (src->natural_scroll != INT_MIN) { + dst->natural_scroll = src->natural_scroll; + } + if (src->pointer_accel != FLT_MIN) { + dst->pointer_accel = src->pointer_accel; + } + if (src->scroll_method != INT_MIN) { + dst->scroll_method = src->scroll_method; + } + if (src->send_events != INT_MIN) { + dst->send_events = src->send_events; + } + if (src->tap != INT_MIN) { + dst->tap = src->tap; + } + 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) { + if (!ic) { + return; + } + free(ic->identifier); + free(ic); +} + +int input_identifier_cmp(const void *item, const void *data) { + const struct input_config *ic = item; + const char *identifier = data; + return strcmp(ic->identifier, identifier); +} diff --git a/sway/config/seat.c b/sway/config/seat.c new file mode 100644 index 000000000..3a2fdaa6f --- /dev/null +++ b/sway/config/seat.c @@ -0,0 +1,127 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include "sway/config.h" +#include "log.h" + +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; +} diff --git a/sway/meson.build b/sway/meson.build index c1f75b139..3d38c7c95 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -32,6 +32,8 @@ sway_sources = files( 'commands/output.c', 'config.c', 'config/output.c', + 'config/seat.c', + 'config/input.c', 'ipc-json.c', 'ipc-server.c', 'desktop/output.c', From f16aa3c0ad8328da0820e81c99a619835f36082f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 12:14:24 -0500 Subject: [PATCH 100/522] 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(-) diff --git a/include/sway/commands.h b/include/sway/commands.h index 61950d0d3..5008831d4 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 777fb5a87..eb642dc2d 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 7485f2f63..3fb1842de 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 9b5fb7a23..f72b7d482 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 a0e3bddfc..dcf64c1a2 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 0954575c1..8108a1100 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 f44c0ec7c..8a74c11ef 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 dc8fcd562..35740df34 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 e19964d81..7bc08ae6a 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 8272c5b38..a7dcdc2c1 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 2c9db5bfb..d2261a630 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 402771551..035262cf8 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 18a54087b..8547c0cd8 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 9a9ce044d..4470fb1dd 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 14a50ffb4..167ce2e7c 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 67eb5342c..180f40d52 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 3eda0bdd8..047e8c842 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 c7f93ad42..0e9984575 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 996c1bdac..80ec63ced 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); } From b8261ab24bbc8159deffadb78f5108a612d27534 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 12:40:58 -0500 Subject: [PATCH 101/522] expect exactly one xkb arg --- sway/commands/input/xkb_layout.c | 2 +- sway/commands/input/xkb_model.c | 2 +- sway/commands/input/xkb_options.c | 2 +- sway/commands/input/xkb_rules.c | 2 +- sway/commands/input/xkb_variant.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c index 4470fb1dd..4fc33e0bf 100644 --- a/sway/commands/input/xkb_layout.c +++ b/sway/commands/input/xkb_layout.c @@ -7,7 +7,7 @@ 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))) { + if ((error = checkarg(argc, "xkb_layout", EXPECTED_EQUAL_TO, 1))) { return error; } if (!current_input_config) { diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c index 167ce2e7c..338bd7de8 100644 --- a/sway/commands/input/xkb_model.c +++ b/sway/commands/input/xkb_model.c @@ -7,7 +7,7 @@ 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))) { + if ((error = checkarg(argc, "xkb_model", EXPECTED_EQUAL_TO, 1))) { return error; } if (!current_input_config) { diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c index 180f40d52..b24c33c11 100644 --- a/sway/commands/input/xkb_options.c +++ b/sway/commands/input/xkb_options.c @@ -7,7 +7,7 @@ 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))) { + if ((error = checkarg(argc, "xkb_options", EXPECTED_EQUAL_TO, 1))) { return error; } if (!current_input_config) { diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c index 047e8c842..def614e92 100644 --- a/sway/commands/input/xkb_rules.c +++ b/sway/commands/input/xkb_rules.c @@ -7,7 +7,7 @@ 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))) { + if ((error = checkarg(argc, "xkb_rules", EXPECTED_EQUAL_TO, 1))) { return error; } if (!current_input_config) { diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c index 0e9984575..cc135ccef 100644 --- a/sway/commands/input/xkb_variant.c +++ b/sway/commands/input/xkb_variant.c @@ -7,7 +7,7 @@ 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))) { + if ((error = checkarg(argc, "xkb_variant", EXPECTED_EQUAL_TO, 1))) { return error; } if (!current_input_config) { From 24e240642984a3b7ee2fba0828eb4375e901aafc Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 13:00:31 -0500 Subject: [PATCH 102/522] strip whitespace for device id --- sway/input/input-manager.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 1950b6d91..e45583665 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -9,6 +9,7 @@ #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/server.h" +#include "stringop.h" #include "list.h" #include "log.h" @@ -36,6 +37,7 @@ static char *get_device_identifier(struct wlr_input_device *device) { int vendor = device->vendor; int product = device->product; char *name = strdup(device->name); + name = strip_whitespace(name); char *p = name; for (; *p; ++p) { From b0ed1ad28d8c87a9ca0e5eacb1e7b840ed924117 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 13:16:58 -0500 Subject: [PATCH 103/522] device add/remove logging --- sway/input/input-manager.c | 6 ++++++ sway/input/seat.c | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index e45583665..34766ee6c 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -120,6 +120,9 @@ static void input_add_notify(struct wl_listener *listener, void *data) { input_device->identifier = get_device_identifier(device); wl_list_insert(&input->devices, &input_device->link); + sway_log(L_DEBUG, "adding device: '%s'", + input_device->identifier); + // find config for (int i = 0; i < config->input_configs->length; ++i) { struct input_config *input_config = config->input_configs->items[i]; @@ -157,6 +160,9 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { return; } + sway_log(L_DEBUG, "removing device: '%s'", + input_device->identifier); + struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { sway_seat_remove_device(seat, input_device); diff --git a/sway/input/seat.c b/sway/input/seat.c index 907c610ac..1e62efa18 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -125,6 +125,9 @@ void sway_seat_add_device(struct sway_seat *seat, return; } + sway_log(L_DEBUG, "adding device %s to seat %s", + input_device->identifier, seat->wlr_seat->name); + seat_device->sway_seat = seat; seat_device->input_device = input_device; wl_list_insert(&seat->devices, &seat_device->link); @@ -134,7 +137,6 @@ void sway_seat_add_device(struct sway_seat *seat, void sway_seat_remove_device(struct sway_seat *seat, 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); @@ -142,6 +144,9 @@ void sway_seat_remove_device(struct sway_seat *seat, return; } + sway_log(L_DEBUG, "removing device %s from seat %s", + input_device->identifier, seat->wlr_seat->name); + seat_device_destroy(seat_device); } From 9e4fc7253e5e82f443ae8e1a27ced12fb13f8a67 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 14:00:23 -0500 Subject: [PATCH 104/522] get device id correctly --- sway/input/input-manager.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 34766ee6c..6a49b13bb 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "sway/config.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -33,6 +34,13 @@ static struct sway_seat *input_manager_get_seat( return sway_seat_create(input, seat_name); } +static inline int strlen_num(int num) { + if (num == 0) { + return 2; + } + return (int)((ceil(log10(abs(num)))+2)); +} + static char *get_device_identifier(struct wlr_input_device *device) { int vendor = device->vendor; int product = device->product; @@ -46,9 +54,12 @@ static char *get_device_identifier(struct wlr_input_device *device) { } } - sway_log(L_DEBUG, "rewritten name %s", name); + int len = + (strlen(name) + + strlen_num(device->vendor) + + strlen_num(device->product) + + 3) * sizeof(char); - int len = strlen(name) + sizeof(char) * 6; char *identifier = malloc(len); if (!identifier) { sway_log(L_ERROR, "Unable to allocate unique input device name"); From 0256cd1473a574c2eb087f420f8356fee9e08aa7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 19:16:00 -0500 Subject: [PATCH 105/522] fix keyboard hotplugging --- include/sway/input/keyboard.h | 1 - sway/input/keyboard.c | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index 0b0c15497..d9251f4c3 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h @@ -5,7 +5,6 @@ struct sway_keyboard { struct sway_seat_device *seat_device; - struct wl_list link; // sway_seat::keyboards struct xkb_keymap *keymap; diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index b9b571a67..ce0df3c56 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -103,9 +103,10 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { } void sway_keyboard_destroy(struct sway_keyboard *keyboard) { - xkb_keymap_unref(keyboard->keymap); + if (!keyboard) { + return; + } wl_list_remove(&keyboard->keyboard_key.link); wl_list_remove(&keyboard->keyboard_modifiers.link); - wl_list_remove(&keyboard->link); free(keyboard); } From c41801b75e612b8bfb0e9e386a190b59141f7857 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 16 Dec 2017 20:06:58 -0500 Subject: [PATCH 106/522] set keyboard config at runtime --- sway/commands/input.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sway/commands/input.c b/sway/commands/input.c index 5ca9c2e61..dac028a73 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -44,6 +44,16 @@ struct cmd_results *cmd_input(int argc, char **argv) { res = input_cmd_scroll_method(argc_new, argv_new); } else if (strcasecmp("tap", argv[1]) == 0) { res = input_cmd_tap(argc_new, argv_new); + } else if (strcasecmp("xkb_layout", argv[1]) == 0) { + res = input_cmd_xkb_layout(argc_new, argv_new); + } else if (strcasecmp("xkb_model", argv[1]) == 0) { + res = input_cmd_xkb_model(argc_new, argv_new); + } else if (strcasecmp("xkb_options", argv[1]) == 0) { + res = input_cmd_xkb_options(argc_new, argv_new); + } else if (strcasecmp("xkb_rules", argv[1]) == 0) { + res = input_cmd_xkb_rules(argc_new, argv_new); + } else if (strcasecmp("xkb_variant", argv[1]) == 0) { + res = input_cmd_xkb_variant(argc_new, argv_new); } else { res = cmd_results_new(CMD_INVALID, "input ", "Unknown command %s", argv[1]); } From e27eff8a29abd74448322ae78baa99a489e43620 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 17 Dec 2017 08:30:20 -0500 Subject: [PATCH 107/522] send keyboard enter on keyboard configuration --- sway/input/input-manager.c | 2 ++ sway/input/seat.c | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 6a49b13bb..fa8e4b49c 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -145,6 +145,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { struct sway_seat *seat = NULL; if (!input_has_seat_configuration(input)) { + sway_log(L_DEBUG, "no seat configuration, using default seat"); seat = input_manager_get_seat(input, default_seat); sway_seat_add_device(seat, input_device); return; @@ -245,6 +246,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) { + 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); diff --git a/sway/input/seat.c b/sway/input/seat.c index 1e62efa18..8fe82b46d 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -68,6 +68,13 @@ static void seat_configure_keyboard(struct sway_seat *seat, sway_keyboard_create(seat, seat_device); } sway_keyboard_configure(seat_device->keyboard); + wlr_seat_set_keyboard(seat->wlr_seat, + seat_device->input_device->wlr_device); + if (seat->focus) { + // force notify reenter to pick up the new configuration + wlr_seat_keyboard_clear_focus(seat->wlr_seat); + wlr_seat_keyboard_notify_enter(seat->wlr_seat, seat->focus->sway_view->surface); + } } static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, @@ -101,8 +108,6 @@ void sway_seat_configure_device(struct sway_seat *seat, break; case WLR_INPUT_DEVICE_KEYBOARD: 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: From 88bcd43ebf59cfa03a9e9a158c6f7a258c1f7db2 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 17 Dec 2017 10:39:22 -0500 Subject: [PATCH 108/522] 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 | 93 ++++++++++++++++++++++++----------- sway/input/seat.c | 3 +- sway/meson.build | 1 + 9 files changed, 105 insertions(+), 31 deletions(-) create mode 100644 sway/commands/seat/fallback.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 5008831d4..4ee7af2a3 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 eb642dc2d..fdfbbedb9 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 3fb1842de..34afb6a0f 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 4f9e259b3..0149762ac 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 000000000..7c129aae4 --- /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 3a2fdaa6f..4c9e8d0dc 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 fa8e4b49c..163014892 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); - - // 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); - } - } + if (!seat) { + return; } sway_seat_set_config(seat, seat_config); + + // 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) { + 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); + } + } + + 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); + } + } + } + } } void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { diff --git a/sway/input/seat.c b/sway/input/seat.c index 8fe82b46d..945036878 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 3d38c7c95..fee2ddd21 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', From a27736adcdfe01c5232adce58201463df34da5e7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 17 Dec 2017 10:44:53 -0500 Subject: [PATCH 109/522] cleanup input-manager --- sway/input/input-manager.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 163014892..12a669179 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -94,17 +94,6 @@ static struct sway_input_device *input_sway_device_from_config( 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) { @@ -154,7 +143,8 @@ static void input_add_notify(struct wl_listener *listener, void *data) { 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, + input_device->identifier) || seat_config_get_attachment(seat->config, "*"))) { sway_seat_add_device(seat, input_device); added = true; @@ -263,7 +253,8 @@ 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) { - sway_log(L_DEBUG, "applying new seat config for seat %s", seat_config->name); + 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); if (!seat) { return; @@ -282,7 +273,8 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, continue; } if (seat_config_get_attachment(seat->config, "*") || - seat_config_get_attachment(seat->config, input_device->identifier)) { + seat_config_get_attachment(seat->config, + input_device->identifier)) { list_add(seat_list, seat); } } @@ -311,6 +303,7 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, } } } + list_free(seat_list); } } From b0291d126f1362cd5f9c00ff16043fd903f257a7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 17 Dec 2017 21:00:17 -0500 Subject: [PATCH 110/522] Fix compile error --- sway/input/seat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 945036878..df1427fa2 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -180,7 +180,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { sway_assert(!result, "Cannot load xcursor theme for output '%s' with scale %f", - output->name, output->scale); + // TODO: Fractional scaling + output->name, (double)output->scale); } wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, From 41e71d950a031ac5e63b0695e47dbfe1606e9f93 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 18 Dec 2017 07:13:02 -0500 Subject: [PATCH 111/522] remove verbose commit logging --- sway/desktop/wl_shell.c | 2 -- sway/desktop/xdg_shell_v6.c | 2 -- sway/desktop/xwayland.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index df81d5bec..e7150bf36 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -55,8 +55,6 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_wl_shell_surface *sway_surface = wl_container_of(listener, sway_surface, commit); struct sway_view *view = sway_surface->view; - sway_log(L_DEBUG, "wl_shell surface commit %dx%d", - sway_surface->pending_width, sway_surface->pending_height); // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever view->width = sway_surface->pending_width; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 82775e2f5..015cc9d04 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -61,8 +61,6 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xdg_surface_v6 *sway_surface = wl_container_of(listener, sway_surface, commit); struct sway_view *view = sway_surface->view; - sway_log(L_DEBUG, "xdg surface commit %dx%d", - sway_surface->pending_width, sway_surface->pending_height); // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever view->width = sway_surface->pending_width; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 29bed9556..42e82c645 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -84,8 +84,6 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, commit); struct sway_view *view = sway_surface->view; - sway_log(L_DEBUG, "xwayland surface commit %dx%d", - sway_surface->pending_width, sway_surface->pending_height); // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever view->width = sway_surface->pending_width; From 4e2ab531195f97370f417c6852a05be99eec2876 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 18 Dec 2017 14:06:03 +0100 Subject: [PATCH 112/522] Add IPC get_outputs --- include/sway/ipc-json.h | 1 + sway/ipc-json.c | 38 ++++++++++++++++++++++++++++++++++++-- sway/ipc-server.c | 16 ++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index 9986c399f..9435b6640 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -5,6 +5,7 @@ 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); #endif diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 2e774a964..09a32c1bd 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -4,6 +4,7 @@ #include "log.h" #include "sway/ipc-json.h" #include "sway/container.h" +#include "sway/output.h" #include #include @@ -38,10 +39,43 @@ static void ipc_json_describe_root(swayc_t *root, json_object *object) { json_object_object_add(object, "layout", json_object_new_string("splith")); } -static void ipc_json_describe_output(swayc_t *output, json_object *object) { +static const char *ipc_json_get_output_transform(enum wl_output_transform transform) { + switch (transform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + return "normal"; + case WL_OUTPUT_TRANSFORM_90: + return "90"; + case WL_OUTPUT_TRANSFORM_180: + return "180"; + case WL_OUTPUT_TRANSFORM_270: + return "270"; + case WL_OUTPUT_TRANSFORM_FLIPPED: + return "flipped"; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + return "flipped-90"; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + return "flipped-180"; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + return "flipped-270"; + } + return NULL; +} + +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)); + json_object_object_add(object, "primary", json_object_new_boolean(false)); + json_object_object_add(object, "layout", json_object_new_string("output")); + json_object_object_add(object, "make", json_object_new_string(wlr_output->make)); + json_object_object_add(object, "model", json_object_new_string(wlr_output->model)); + json_object_object_add(object, "serial", json_object_new_string(wlr_output->serial)); + json_object_object_add(object, "scale", json_object_new_double(wlr_output->scale)); + json_object_object_add(object, "refresh", json_object_new_int(wlr_output->refresh)); + json_object_object_add(object, "transform", + json_object_new_string(ipc_json_get_output_transform(wlr_output->transform))); json_object_object_add(object, "current_workspace", - (output->focused) ? json_object_new_string(output->focused->name) : NULL); + (container->focused) ? json_object_new_string(container->focused->name) : NULL); } static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 71f8dddd6..b7cd2d765 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -343,6 +343,22 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_OUTPUTS: + { + 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]; + if (container->type == C_OUTPUT) { + json_object_array_add(outputs, + ipc_json_describe_container(container)); + } + } + const char *json_string = json_object_to_json_string(outputs); + ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); + json_object_put(outputs); // free + goto exit_cleanup; + } + case IPC_GET_TREE: { json_object *tree = From c815d6d1a97fe940052f079bd8eb7f174f5ab004 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 18 Dec 2017 14:13:07 +0100 Subject: [PATCH 113/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 139d7800e..afff2738a 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 d71e4d8d4..7988e3e40 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 dc9ee37c3..ff3f73a3d 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) { From 483ede0146cd5eb5b1a68dc365f99af0c66fd156 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 18 Dec 2017 10:44:25 -0500 Subject: [PATCH 114/522] improve xkb command logging --- sway/commands/input/xkb_layout.c | 4 ++-- sway/commands/input/xkb_model.c | 4 ++-- sway/commands/input/xkb_options.c | 4 ++-- sway/commands/input/xkb_rules.c | 4 ++-- sway/commands/input/xkb_variant.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c index 4fc33e0bf..a25d38509 100644 --- a/sway/commands/input/xkb_layout.c +++ b/sway/commands/input/xkb_layout.c @@ -18,8 +18,8 @@ struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { new_config->xkb_layout = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_layout for device: %s", - current_input_config->identifier); + sway_log(L_DEBUG, "apply-xkb_layout for device: %s layout: %s", + current_input_config->identifier, new_config->xkb_layout); 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 338bd7de8..9729e8696 100644 --- a/sway/commands/input/xkb_model.c +++ b/sway/commands/input/xkb_model.c @@ -18,8 +18,8 @@ struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { new_config->xkb_model = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_model for device: %s", - current_input_config->identifier); + sway_log(L_DEBUG, "apply-xkb_model for device: %s model: %s", + current_input_config->identifier, new_config->xkb_model); 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 b24c33c11..504849ccb 100644 --- a/sway/commands/input/xkb_options.c +++ b/sway/commands/input/xkb_options.c @@ -18,8 +18,8 @@ struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { new_config->xkb_options = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_options for device: %s", - current_input_config->identifier); + sway_log(L_DEBUG, "apply-xkb_options for device: %s options: %s", + current_input_config->identifier, new_config->xkb_options); 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 def614e92..db7d8abe3 100644 --- a/sway/commands/input/xkb_rules.c +++ b/sway/commands/input/xkb_rules.c @@ -18,8 +18,8 @@ struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { new_config->xkb_rules = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_rules for device: %s", - current_input_config->identifier); + sway_log(L_DEBUG, "apply-xkb_rules for device: %s rules: %s", + current_input_config->identifier, new_config->xkb_rules); 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 cc135ccef..855e6abc1 100644 --- a/sway/commands/input/xkb_variant.c +++ b/sway/commands/input/xkb_variant.c @@ -18,8 +18,8 @@ struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { new_config->xkb_variant = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_variant for device: %s", - current_input_config->identifier); + sway_log(L_DEBUG, "apply-xkb_variant for device: %s variant: %s", + current_input_config->identifier, new_config->xkb_variant); apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From 4c436a1a6f78ce9eae40791b85c02d44458de727 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 18 Dec 2017 10:44:51 -0500 Subject: [PATCH 115/522] remove assumption of one device per identifier --- sway/input/input-manager.c | 29 +++++++++-------------------- sway/input/keyboard.c | 2 ++ 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 12a669179..52da8f5e3 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -83,17 +83,6 @@ static struct sway_input_device *input_sway_device_from_wlr( 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 *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 bool input_has_seat_configuration(struct sway_input_manager *input) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { @@ -238,16 +227,16 @@ void sway_input_manager_set_focus(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 *input_device = - input_sway_device_from_config(input, input_config); - if (!input_device) { - return; - } - input_device->config = input_config; + 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; - struct sway_seat *seat = NULL; - wl_list_for_each(seat, &input->seats, link) { - sway_seat_configure_device(seat, input_device); + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input->seats, link) { + sway_seat_configure_device(seat, input_device); + } + } } } diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index ce0df3c56..bb18edd2c 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -91,6 +91,8 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); wlr_keyboard_set_repeat_info(wlr_device->keyboard, 25, 600); xkb_context_unref(context); + struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; + wlr_seat_set_keyboard(seat, wlr_device); wl_list_remove(&keyboard->keyboard_key.link); wl_signal_add(&wlr_device->keyboard->events.key, &keyboard->keyboard_key); From f2985000f364693fbeb832df1c4fd468c608e40f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 18 Dec 2017 14:27:38 -0500 Subject: [PATCH 116/522] ipc get_inputs --- include/sway/ipc-json.h | 2 ++ sway/ipc-json.c | 37 +++++++++++++++++++++ sway/ipc-server.c | 14 ++++++++ swaymsg/main.c | 72 +++++++++++++++++++---------------------- 4 files changed, 86 insertions(+), 39 deletions(-) diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index 9435b6640..eef5a018c 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -2,10 +2,12 @@ #define _SWAY_IPC_JSON_H #include #include "sway/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_input(struct sway_input_device *device); #endif diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 09a32c1bd..bab9a2014 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -141,3 +141,40 @@ json_object *ipc_json_describe_container_recursive(swayc_t *c) { return object; } + +static const char *describe_device_type(struct sway_input_device *device) { + switch (device->wlr_device->type) { + case WLR_INPUT_DEVICE_POINTER: + return "pointer"; + case WLR_INPUT_DEVICE_KEYBOARD: + return "keyboard"; + case WLR_INPUT_DEVICE_TOUCH: + return "touch"; + case WLR_INPUT_DEVICE_TABLET_TOOL: + return "tablet_tool"; + case WLR_INPUT_DEVICE_TABLET_PAD: + return "tablet_pad"; + } + return "unknown"; +} + +json_object *ipc_json_describe_input(struct sway_input_device *device) { + if (!(sway_assert(device, "Device must not be null"))) { + return NULL; + } + + json_object *object = json_object_new_object(); + + json_object_object_add(object, "identifier", + json_object_new_string(device->identifier)); + json_object_object_add(object, "name", + json_object_new_string(device->wlr_device->name)); + json_object_object_add(object, "vendor", + json_object_new_int(device->wlr_device->vendor)); + json_object_object_add(object, "product", + json_object_new_int(device->wlr_device->product)); + json_object_object_add(object, "type", + json_object_new_string(describe_device_type(device))); + + return object; +} diff --git a/sway/ipc-server.c b/sway/ipc-server.c index b7cd2d765..046e40a8a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -20,6 +20,7 @@ #include "sway/ipc-json.h" #include "sway/ipc-server.h" #include "sway/server.h" +#include "sway/input/input-manager.h" #include "list.h" #include "log.h" @@ -359,6 +360,19 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_INPUTS: + { + json_object *inputs = json_object_new_array(); + struct sway_input_device *device = NULL; + wl_list_for_each(device, &input_manager->devices, link) { + json_object_array_add(inputs, ipc_json_describe_input(device)); + } + const char *json_string = json_object_to_json_string(inputs); + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(inputs); // free + goto exit_cleanup; + } + case IPC_GET_TREE: { json_object *tree = diff --git a/swaymsg/main.c b/swaymsg/main.c index 2f9cfb141..18f17a595 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -61,55 +61,49 @@ static void pretty_print_workspace(json_object *w) { ); } -static void pretty_print_input(json_object *i) { - json_object *id, *name, *size, *caps; - json_object_object_get_ex(i, "identifier", &id); - json_object_object_get_ex(i, "name", &name); - json_object_object_get_ex(i, "size", &size); - json_object_object_get_ex(i, "capabilities", &caps); - - printf( "Input device %s\n Type: ", json_object_get_string(name)); - +static const char *pretty_type_name(const char *name) { + // TODO these constants probably belong in the common lib struct { const char *a; const char *b; - } cap_names[] = { + } type_names[] = { { "keyboard", "Keyboard" }, { "pointer", "Mouse" }, - { "touch", "Touch" }, - { "tablet_tool", "Tablet tool" }, { "tablet_pad", "Tablet pad" }, - { "gesture", "Gesture" }, - { "switch", "Switch" }, + { "tablet_tool", "Tablet tool" }, + { "touch", "Touch" }, }; - size_t len = json_object_array_length(caps); - if (len == 0) { - printf("Unknown"); + for (size_t i = 0; i < sizeof(type_names) / sizeof(type_names[0]); ++i) { + if (strcmp(type_names[i].a, name) == 0) { + return type_names[i].b; + } } - json_object *cap; - for (size_t i = 0; i < len; ++i) { - cap = json_object_array_get_idx(caps, i); - const char *cap_s = json_object_get_string(cap); - const char *_name = NULL; - for (size_t j = 0; j < sizeof(cap_names) / sizeof(cap_names[0]); ++i) { - if (strcmp(cap_names[i].a, cap_s) == 0) { - _name = cap_names[i].b; - break; - } - } - printf("%s%s", _name ? _name : cap_s, len > 1 && i != len - 1 ? ", " : ""); - } - printf("\n Sway ID: %s\n", json_object_get_string(id)); - if (size) { - json_object *width, *height; - json_object_object_get_ex(size, "width", &width); - json_object_object_get_ex(size, "height", &height); - printf(" Size: %lfmm x %lfmm\n", - json_object_get_double(width), json_object_get_double(height)); - } - printf("\n"); + return name; +} + +static void pretty_print_input(json_object *i) { + json_object *id, *name, *type, *product, *vendor; + json_object_object_get_ex(i, "identifier", &id); + json_object_object_get_ex(i, "name", &name); + json_object_object_get_ex(i, "type", &type); + json_object_object_get_ex(i, "product", &product); + json_object_object_get_ex(i, "vendor", &vendor); + + const char *fmt = + "Input device: %s\n" + " Type: %s\n" + " Identifier: %s\n" + " Product ID: %d\n" + " Vendor ID: %d\n\n"; + + + printf(fmt, json_object_get_string(name), + pretty_type_name(json_object_get_string(type)), + json_object_get_string(id), + json_object_get_int(product), + json_object_get_int(vendor)); } static void pretty_print_output(json_object *o) { From 8b4d81114a6e25be9f8f7c7bca17e55dbebd675d Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 18 Dec 2017 17:52:50 -0500 Subject: [PATCH 117/522] fix memory leak in swaymsg --- swaymsg/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index 18f17a595..dfc175a83 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -335,7 +335,7 @@ int main(int argc, char **argv) { } else { pretty_print(type, obj); } - free(obj); + json_object_put(obj); } } close(socketfd); From f9413adde7ada3b5132435604a7db37971d4cf45 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 19 Dec 2017 08:06:23 +0100 Subject: [PATCH 118/522] build: add wlroots dependency to common It is required for include path if wlroots is not built in standard path, but found through pkg-config --- common/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/common/meson.build b/common/meson.build index 3a4282ad5..abe0cdcfe 100644 --- a/common/meson.build +++ b/common/meson.build @@ -7,5 +7,6 @@ lib_sway_common = static_library('sway-common', 'readline.c', 'ipc-client.c' ), + dependencies: [ wlroots ], include_directories: sway_inc ) From 9df4a2c7a8598c344aa5ee5fabd8566e348ee66f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 19 Dec 2017 04:52:03 -0500 Subject: [PATCH 119/522] document fallback seat --- sway/sway-input.5.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/sway-input.5.txt b/sway/sway-input.5.txt index d4652a828..0603616bb 100644 --- a/sway/sway-input.5.txt +++ b/sway/sway-input.5.txt @@ -95,6 +95,10 @@ their own "seat"). Attach an input device to this seat by its input identifier. A special value of _*_ will attach all devices to the seat. +**seat** fallback :: + Set this seat as the fallback seat. A fallback seat will attach any device not + explicitly attached to another seat (similar to a "default" seat). + See Also -------- From 730af5e721f04cf12b613341e00b44a93f3397c6 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 19 Dec 2017 04:57:42 -0500 Subject: [PATCH 120/522] use snprintf to get identifier len --- sway/input/input-manager.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 52da8f5e3..b20b7b7ec 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -34,13 +34,6 @@ static struct sway_seat *input_manager_get_seat( return sway_seat_create(input, seat_name); } -static inline int strlen_num(int num) { - if (num == 0) { - return 2; - } - return (int)((ceil(log10(abs(num)))+2)); -} - static char *get_device_identifier(struct wlr_input_device *device) { int vendor = device->vendor; int product = device->product; @@ -54,19 +47,14 @@ 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); - + const char *fmt = "%d:%d:%s"; + int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; 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; From 5c036a3eac89e3dec71484fe9c22704b120254b1 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 19 Dec 2017 05:26:55 -0500 Subject: [PATCH 121/522] error on not enough input/seat args for cmd --- sway/commands/input.c | 88 +++++++++++++++++++++---------------------- sway/commands/seat.c | 32 ++++++++-------- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/sway/commands/input.c b/sway/commands/input.c index dac028a73..ccb1d2767 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -16,50 +16,50 @@ struct cmd_results *cmd_input(int argc, char **argv) { return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); } - if (argc > 2) { - int argc_new = argc-2; - char **argv_new = argv+2; - - struct cmd_results *res; - current_input_config = new_input_config(argv[0]); - if (strcasecmp("accel_profile", argv[1]) == 0) { - res = input_cmd_accel_profile(argc_new, argv_new); - } else if (strcasecmp("click_method", argv[1]) == 0) { - res = input_cmd_click_method(argc_new, argv_new); - } else if (strcasecmp("drag_lock", argv[1]) == 0) { - res = input_cmd_drag_lock(argc_new, argv_new); - } else if (strcasecmp("dwt", argv[1]) == 0) { - res = input_cmd_dwt(argc_new, argv_new); - } else if (strcasecmp("events", argv[1]) == 0) { - res = input_cmd_events(argc_new, argv_new); - } else if (strcasecmp("left_handed", argv[1]) == 0) { - res = input_cmd_left_handed(argc_new, argv_new); - } else if (strcasecmp("middle_emulation", argv[1]) == 0) { - res = input_cmd_middle_emulation(argc_new, argv_new); - } else if (strcasecmp("natural_scroll", argv[1]) == 0) { - res = input_cmd_natural_scroll(argc_new, argv_new); - } else if (strcasecmp("pointer_accel", argv[1]) == 0) { - res = input_cmd_pointer_accel(argc_new, argv_new); - } else if (strcasecmp("scroll_method", argv[1]) == 0) { - res = input_cmd_scroll_method(argc_new, argv_new); - } else if (strcasecmp("tap", argv[1]) == 0) { - res = input_cmd_tap(argc_new, argv_new); - } else if (strcasecmp("xkb_layout", argv[1]) == 0) { - res = input_cmd_xkb_layout(argc_new, argv_new); - } else if (strcasecmp("xkb_model", argv[1]) == 0) { - res = input_cmd_xkb_model(argc_new, argv_new); - } else if (strcasecmp("xkb_options", argv[1]) == 0) { - res = input_cmd_xkb_options(argc_new, argv_new); - } else if (strcasecmp("xkb_rules", argv[1]) == 0) { - res = input_cmd_xkb_rules(argc_new, argv_new); - } else if (strcasecmp("xkb_variant", argv[1]) == 0) { - res = input_cmd_xkb_variant(argc_new, argv_new); - } else { - res = cmd_results_new(CMD_INVALID, "input ", "Unknown command %s", argv[1]); - } - current_input_config = NULL; - return res; + if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 3))) { + return error; } - return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); + int argc_new = argc-2; + char **argv_new = argv+2; + + struct cmd_results *res; + current_input_config = new_input_config(argv[0]); + if (strcasecmp("accel_profile", argv[1]) == 0) { + res = input_cmd_accel_profile(argc_new, argv_new); + } else if (strcasecmp("click_method", argv[1]) == 0) { + res = input_cmd_click_method(argc_new, argv_new); + } else if (strcasecmp("drag_lock", argv[1]) == 0) { + res = input_cmd_drag_lock(argc_new, argv_new); + } else if (strcasecmp("dwt", argv[1]) == 0) { + res = input_cmd_dwt(argc_new, argv_new); + } else if (strcasecmp("events", argv[1]) == 0) { + res = input_cmd_events(argc_new, argv_new); + } else if (strcasecmp("left_handed", argv[1]) == 0) { + res = input_cmd_left_handed(argc_new, argv_new); + } else if (strcasecmp("middle_emulation", argv[1]) == 0) { + res = input_cmd_middle_emulation(argc_new, argv_new); + } else if (strcasecmp("natural_scroll", argv[1]) == 0) { + res = input_cmd_natural_scroll(argc_new, argv_new); + } else if (strcasecmp("pointer_accel", argv[1]) == 0) { + res = input_cmd_pointer_accel(argc_new, argv_new); + } else if (strcasecmp("scroll_method", argv[1]) == 0) { + res = input_cmd_scroll_method(argc_new, argv_new); + } else if (strcasecmp("tap", argv[1]) == 0) { + res = input_cmd_tap(argc_new, argv_new); + } else if (strcasecmp("xkb_layout", argv[1]) == 0) { + res = input_cmd_xkb_layout(argc_new, argv_new); + } else if (strcasecmp("xkb_model", argv[1]) == 0) { + res = input_cmd_xkb_model(argc_new, argv_new); + } else if (strcasecmp("xkb_options", argv[1]) == 0) { + res = input_cmd_xkb_options(argc_new, argv_new); + } else if (strcasecmp("xkb_rules", argv[1]) == 0) { + res = input_cmd_xkb_rules(argc_new, argv_new); + } else if (strcasecmp("xkb_variant", argv[1]) == 0) { + res = input_cmd_xkb_variant(argc_new, argv_new); + } else { + res = cmd_results_new(CMD_INVALID, "input ", "Unknown command %s", argv[1]); + } + current_input_config = NULL; + return res; } diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 0149762ac..155bc510e 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -16,22 +16,22 @@ struct cmd_results *cmd_seat(int argc, char **argv) { 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 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]); - } - current_seat_config = NULL; - return res; + if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 3))) { + return error; } - return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); + 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) { + res = seat_cmd_fallback(argc_new, argv_new); + } else { + res = cmd_results_new(CMD_INVALID, "seat ", "Unknown command %s", argv[1]); + } + current_seat_config = NULL; + return res; } From 39e7871a859df5ce82f9d3d10088a3bc2b4ff356 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 19 Dec 2017 05:28:06 -0500 Subject: [PATCH 122/522] dont set cursor image on motion --- sway/input/cursor.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 24d4642d4..3b5cfce5c 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -15,9 +15,6 @@ static void cursor_update_position(struct sway_cursor *cursor) { double x = cursor->cursor->x; double y = cursor->cursor->y; - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, - "left_ptr", cursor->cursor); - cursor->x = x; cursor->y = y; } From f35575f71dfab5be9a935bc5e21ca5ee5dc4c2c2 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 19 Dec 2017 05:36:17 -0500 Subject: [PATCH 123/522] handle keymap not found --- sway/input/keyboard.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index bb18edd2c..724941d85 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -85,10 +85,19 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { return; } - xkb_keymap_unref(keyboard->keymap); - keyboard->keymap = + struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!keymap) { + sway_log(L_DEBUG, "cannot configure keyboard: keymap does not exist"); + xkb_context_unref(context); + return; + } + + xkb_keymap_unref(keyboard->keymap); + keyboard->keymap = keymap; wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); + wlr_keyboard_set_repeat_info(wlr_device->keyboard, 25, 600); xkb_context_unref(context); struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; From a4c1270ef0a3c5bd610b13867be7616a55e59dc5 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 19 Dec 2017 05:38:41 -0500 Subject: [PATCH 124/522] fix memory leak in swaymsg --- swaymsg/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index dfc175a83..b431872a6 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -308,9 +308,11 @@ int main(int argc, char **argv) { } free(cmdtype); - char *command = strdup(""); + char *command = NULL; if (optind < argc) { command = join_args(argv + optind, argc - optind); + } else { + command = strdup(""); } int ret = 0; From 63f7fb95172a72436698a1562b4f7ea1e9100a7e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 20 Dec 2017 06:12:08 -0500 Subject: [PATCH 125/522] cleanup --- sway/config/seat.c | 3 +++ sway/input/input-manager.c | 9 +++++---- sway/input/seat.c | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sway/config/seat.c b/sway/config/seat.c index 4c9e8d0dc..113139e8c 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -14,6 +14,7 @@ struct seat_config *new_seat_config(const char* name) { sway_log(L_DEBUG, "new_seat_config(%s)", name); seat->name = strdup(name); if (!sway_assert(seat->name, "could not allocate name for seat")) { + free(seat); return NULL; } @@ -21,6 +22,8 @@ struct seat_config *new_seat_config(const char* name) { seat->attachments = create_list(); if (!sway_assert(seat->attachments, "could not allocate seat attachments list")) { + free(seat->name); + free(seat); return NULL; } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index b20b7b7ec..4459c43bc 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -119,10 +119,11 @@ static void input_add_notify(struct wl_listener *listener, void *data) { 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, "*"))) { + bool has_attachment = seat->config && + (seat_config_get_attachment(seat->config, input_device->identifier) || + seat_config_get_attachment(seat->config, "*")); + + if (has_attachment) { sway_seat_add_device(seat, input_device); added = true; } diff --git a/sway/input/seat.c b/sway/input/seat.c index df1427fa2..fe90565a4 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -30,6 +30,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, seat->wlr_seat = wlr_seat_create(input->server->wl_display, seat_name); if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { + free(seat); return NULL; } From f3d8df45fc3b4bca0076bc564bd179d87e307b7c Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sun, 24 Dec 2017 14:53:00 +0100 Subject: [PATCH 126/522] seat_configure_pointer: apply libinput config Restore the code that used to be in config.c:apply_input_config() pre-wlroots --- sway/input/input-manager.c | 78 ++++++++++++++++++++++++++++++++++++++ sway/input/seat.c | 1 - 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 4459c43bc..128a818a0 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "sway/config.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -82,6 +83,75 @@ static bool input_has_seat_configuration(struct sway_input_manager *input) { return false; } +static void sway_input_manager_libinput_config_pointer(struct sway_input_device *input_device) { + struct wlr_input_device *wlr_device = input_device->wlr_device; + struct input_config *ic = input_device->config; + struct libinput_device *libinput_device; + + if (!ic || !wlr_input_device_is_libinput(wlr_device)) { + return; + } + + libinput_device = wlr_libinput_get_device_handle(wlr_device); + sway_log(L_DEBUG, "sway_input_manager_libinput_config_pointer(%s)", ic->identifier); + + if (ic->accel_profile != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", + ic->identifier, ic->accel_profile); + libinput_device_config_accel_set_profile(libinput_device, ic->accel_profile); + } + if (ic->click_method != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", + ic->identifier, ic->click_method); + libinput_device_config_click_set_method(libinput_device, ic->click_method); + } + if (ic->drag_lock != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", + ic->identifier, ic->click_method); + libinput_device_config_tap_set_drag_lock_enabled(libinput_device, ic->drag_lock); + } + if (ic->dwt != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", + ic->identifier, ic->dwt); + libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); + } + if (ic->left_handed != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)", + ic->identifier, ic->left_handed); + libinput_device_config_left_handed_set(libinput_device, ic->left_handed); + } + if (ic->middle_emulation != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", + ic->identifier, ic->middle_emulation); + libinput_device_config_middle_emulation_set_enabled(libinput_device, ic->middle_emulation); + } + if (ic->natural_scroll != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", + ic->identifier, ic->natural_scroll); + libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, ic->natural_scroll); + } + if (ic->pointer_accel != FLT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", + ic->identifier, ic->pointer_accel); + libinput_device_config_accel_set_speed(libinput_device, ic->pointer_accel); + } + if (ic->scroll_method != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", + ic->identifier, ic->scroll_method); + libinput_device_config_scroll_set_method(libinput_device, ic->scroll_method); + } + if (ic->send_events != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", + ic->identifier, ic->send_events); + libinput_device_config_send_events_set_mode(libinput_device, ic->send_events); + } + if (ic->tap != INT_MIN) { + sway_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", + ic->identifier, ic->tap); + libinput_device_config_tap_set_enabled(libinput_device, ic->tap); + } +} + static void input_add_notify(struct wl_listener *listener, void *data) { struct sway_input_manager *input = wl_container_of(listener, input, input_add); @@ -109,6 +179,10 @@ static void input_add_notify(struct wl_listener *listener, void *data) { } } + if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { + sway_input_manager_libinput_config_pointer(input_device); + } + struct sway_seat *seat = NULL; if (!input_has_seat_configuration(input)) { sway_log(L_DEBUG, "no seat configuration, using default seat"); @@ -221,6 +295,10 @@ void sway_input_manager_apply_input_config(struct sway_input_manager *input, if (strcmp(input_device->identifier, input_config->identifier) == 0) { input_device->config = input_config; + if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { + sway_input_manager_libinput_config_pointer(input_device); + } + struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { sway_seat_configure_device(seat, input_device); diff --git a/sway/input/seat.c b/sway/input/seat.c index fe90565a4..9a6a667bd 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -58,7 +58,6 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, 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->input_device->wlr_device); } From 2f7e435c6f2c7e4ace4f2566677d8730531985c8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 27 Dec 2017 10:10:13 -0500 Subject: [PATCH 127/522] desktop: use wlr-surface commit --- sway/desktop/wl_shell.c | 4 +++- sway/desktop/xdg_shell_v6.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index e7150bf36..a7bb8eb5a 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -114,7 +114,9 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { // - Criteria sway_surface->commit.notify = handle_commit; - wl_signal_add(&shell_surface->events.commit, &sway_surface->commit); + wl_signal_add(&shell_surface->surface->events.commit, + &sway_surface->commit); + sway_surface->destroy.notify = handle_destroy; wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 015cc9d04..5ff19f7eb 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -120,7 +120,8 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { // - Criteria sway_surface->commit.notify = handle_commit; - wl_signal_add(&xdg_surface->events.commit, &sway_surface->commit); + wl_signal_add(&xdg_surface->surface->events.commit, &sway_surface->commit); + sway_surface->destroy.notify = handle_destroy; wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); From ba69f06695c24f98a05d138a53ba130108ebce6f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 27 Dec 2017 10:08:18 -0500 Subject: [PATCH 128/522] 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 diff --git a/include/sway/config.h b/include/sway/config.h index 83ded7206..7146623eb 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 34afb6a0f..b0078a468 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 000000000..62aa535af --- /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 b591ae9e4..312e0779c 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 fee2ddd21..01d5ef36d 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', From eea80e7276f49e5d07b22db071f3ab0b6f9ffe18 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 27 Dec 2017 13:20:28 -0500 Subject: [PATCH 129/522] keyboard translate keysyms --- include/sway/input/keyboard.h | 5 ++ sway/input/keyboard.c | 147 +++++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 3 deletions(-) diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index d9251f4c3..0a5857f0a 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h @@ -3,6 +3,8 @@ #include "sway/input/seat.h" +#define SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP 32 + struct sway_keyboard { struct sway_seat_device *seat_device; @@ -10,6 +12,9 @@ struct sway_keyboard { struct wl_listener keyboard_key; struct wl_listener keyboard_modifiers; + + xkb_keysym_t pressed_keysyms_translated[SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP]; + xkb_keysym_t pressed_keysyms_raw[SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP]; }; struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 724941d85..25def7acc 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -3,6 +3,121 @@ #include "sway/input/input-manager.h" #include "log.h" +/* + * Get keysyms and modifiers from the keyboard as xkb sees them. + * + * This uses the xkb keysyms translation based on pressed modifiers and clears + * the consumed modifiers from the list of modifiers passed to keybind + * detection. + * + * On US layout, pressing Alt+Shift+2 will trigger Alt+@. + */ +static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, + xkb_keycode_t keycode, const xkb_keysym_t **keysyms, + uint32_t *modifiers) { + struct wlr_input_device *device = + keyboard->seat_device->input_device->wlr_device; + *modifiers = wlr_keyboard_get_modifiers(device->keyboard); + xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2( + device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); + *modifiers = *modifiers & ~consumed; + + return xkb_state_key_get_syms(device->keyboard->xkb_state, + keycode, keysyms); +} + +/* + * Get keysyms and modifiers from the keyboard as if modifiers didn't change + * keysyms. + * + * This avoids the xkb keysym translation based on modifiers considered pressed + * in the state. + * + * This will trigger keybinds such as Alt+Shift+2. + */ +static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, + xkb_keycode_t keycode, const xkb_keysym_t **keysyms, + uint32_t *modifiers) { + struct wlr_input_device *device = + keyboard->seat_device->input_device->wlr_device; + *modifiers = wlr_keyboard_get_modifiers(device->keyboard); + + xkb_layout_index_t layout_index = xkb_state_key_get_layout( + device->keyboard->xkb_state, keycode); + return xkb_keymap_key_get_syms_by_level(device->keyboard->keymap, + keycode, layout_index, 0, keysyms); +} + +static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms, + xkb_keysym_t keysym) { + for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { + if (pressed_keysyms[i] == keysym) { + return i; + } + } + return -1; +} + +static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) { + size_t n = 0; + for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { + if (pressed_keysyms[i] != XKB_KEY_NoSymbol) { + ++n; + } + } + return n; +} + +static void pressed_keysyms_add(xkb_keysym_t *pressed_keysyms, + xkb_keysym_t keysym) { + ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); + if (i < 0) { + i = pressed_keysyms_index(pressed_keysyms, XKB_KEY_NoSymbol); + if (i >= 0) { + pressed_keysyms[i] = keysym; + } + } +} + +static void pressed_keysyms_remove(xkb_keysym_t *pressed_keysyms, + xkb_keysym_t keysym) { + ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); + if (i >= 0) { + pressed_keysyms[i] = XKB_KEY_NoSymbol; + } +} + +static bool keysym_is_modifier(xkb_keysym_t keysym) { + switch (keysym) { + case XKB_KEY_Shift_L: case XKB_KEY_Shift_R: + case XKB_KEY_Control_L: case XKB_KEY_Control_R: + case XKB_KEY_Caps_Lock: + case XKB_KEY_Shift_Lock: + case XKB_KEY_Meta_L: case XKB_KEY_Meta_R: + case XKB_KEY_Alt_L: case XKB_KEY_Alt_R: + case XKB_KEY_Super_L: case XKB_KEY_Super_R: + case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R: + return true; + default: + return false; + } +} + +static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms, + const xkb_keysym_t *keysyms, size_t keysyms_len, + enum wlr_key_state state) { + for (size_t i = 0; i < keysyms_len; ++i) { + if (keysym_is_modifier(keysyms[i])) { + continue; + } + if (state == WLR_KEY_PRESSED) { + pressed_keysyms_add(pressed_keysyms, keysyms[i]); + } else { // WLR_KEY_RELEASED + pressed_keysyms_remove(pressed_keysyms, keysyms[i]); + } + } +} + static void handle_keyboard_key(struct wl_listener *listener, void *data) { struct sway_keyboard *keyboard = wl_container_of(listener, keyboard, keyboard_key); @@ -10,9 +125,35 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { struct wlr_input_device *wlr_device = keyboard->seat_device->input_device->wlr_device; struct wlr_event_keyboard_key *event = data; - wlr_seat_set_keyboard(wlr_seat, wlr_device); - wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, - event->keycode, event->state); + + xkb_keycode_t keycode = event->keycode + 8; + bool handled = false; + uint32_t modifiers; + const xkb_keysym_t *keysyms; + size_t keysyms_len; + + // handle translated keysyms + keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &keysyms, + &modifiers); + pressed_keysyms_update(keyboard->pressed_keysyms_translated, keysyms, + keysyms_len, event->state); + if (event->state == WLR_KEY_PRESSED) { + // TODO execute binding + } + + // Handle raw keysyms + keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &keysyms, &modifiers); + pressed_keysyms_update(keyboard->pressed_keysyms_raw, keysyms, keysyms_len, + event->state); + if (event->state == WLR_KEY_PRESSED && !handled) { + // TODO execute binding + } + + if (!handled) { + 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, From daad22233765716d0b7ba5ba5dc7492f59e63097 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 27 Dec 2017 13:31:31 -0500 Subject: [PATCH 130/522] compositor bindings --- sway/input/keyboard.c | 51 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 25def7acc..68a95bac2 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -1,8 +1,52 @@ +#include +#include #include "sway/input/seat.h" #include "sway/input/keyboard.h" #include "sway/input/input-manager.h" #include "log.h" +/** + * Execute a built-in, hardcoded compositor binding. These are triggered from a + * single keysym. + * + * Returns true if the keysym was handled by a binding and false if the event + * should be propagated to clients. + */ +static bool keyboard_execute_compositor_binding(xkb_keysym_t keysym) { + if (keysym >= XKB_KEY_XF86Switch_VT_1 && + keysym <= XKB_KEY_XF86Switch_VT_12) { + if (wlr_backend_is_multi(server.backend)) { + struct wlr_session *session = + wlr_multi_get_session(server.backend); + if (session) { + unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1; + wlr_session_change_vt(session, vt); + } + } + return true; + } + + return false; +} + +/** + * Execute keyboard bindings. These include compositor bindings and user-defined + * bindings. + * + * Returns true if the keysym was handled by a binding and false if the event + * should be propagated to clients. + */ +static bool keyboard_execute_binding(struct sway_keyboard *keyboard, + xkb_keysym_t *pressed_keysyms, uint32_t modifiers, + const xkb_keysym_t *keysyms, size_t keysyms_len) { + for (size_t i = 0; i < keysyms_len; ++i) { + if (keyboard_execute_compositor_binding(keysyms[i])) { + return true; + } + } + return false; +} + /* * Get keysyms and modifiers from the keyboard as xkb sees them. * @@ -138,7 +182,9 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { pressed_keysyms_update(keyboard->pressed_keysyms_translated, keysyms, keysyms_len, event->state); if (event->state == WLR_KEY_PRESSED) { - // TODO execute binding + handled = keyboard_execute_binding(keyboard, + keyboard->pressed_keysyms_translated, modifiers, keysyms, + keysyms_len); } // Handle raw keysyms @@ -146,7 +192,8 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { pressed_keysyms_update(keyboard->pressed_keysyms_raw, keysyms, keysyms_len, event->state); if (event->state == WLR_KEY_PRESSED && !handled) { - // TODO execute binding + handled = keyboard_execute_binding(keyboard, + keyboard->pressed_keysyms_raw, modifiers, keysyms, keysyms_len); } if (!handled) { From d941246d58b55b56179cfe159bec5b4bfb201d2e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 27 Dec 2017 15:17:01 -0500 Subject: [PATCH 131/522] match user bindsym --- sway/input/keyboard.c | 69 ++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 68a95bac2..326ee5845 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -5,6 +5,27 @@ #include "sway/input/input-manager.h" #include "log.h" +static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) { + size_t n = 0; + for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { + if (pressed_keysyms[i] != XKB_KEY_NoSymbol) { + ++n; + } + } + return n; +} + +static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms, + xkb_keysym_t keysym) { + for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { + if (pressed_keysyms[i] == keysym) { + return i; + } + } + return -1; +} + + /** * Execute a built-in, hardcoded compositor binding. These are triggered from a * single keysym. @@ -39,11 +60,39 @@ static bool keyboard_execute_compositor_binding(xkb_keysym_t keysym) { static bool keyboard_execute_binding(struct sway_keyboard *keyboard, xkb_keysym_t *pressed_keysyms, uint32_t modifiers, const xkb_keysym_t *keysyms, size_t keysyms_len) { + // compositor bindings for (size_t i = 0; i < keysyms_len; ++i) { if (keyboard_execute_compositor_binding(keysyms[i])) { return true; } } + + // configured bindings + int n = pressed_keysyms_length(pressed_keysyms); + list_t *keysym_bindings = config->current_mode->keysym_bindings; + for (int i = 0; i < keysym_bindings->length; ++i) { + struct sway_binding *binding = keysym_bindings->items[i]; + if (modifiers ^ binding->modifiers || n != binding->keys->length) { + continue; + } + + bool match = true; + for (int j = 0; j < binding->keys->length; ++j) { + match = + pressed_keysyms_index(pressed_keysyms, + *(int*)binding->keys->items[j]) < 0; + + if (!match) { + break; + } + } + + if (match) { + sway_log(L_DEBUG, "TODO: executing binding command: %s", binding->command); + return true; + } + } + return false; } @@ -92,26 +141,6 @@ static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, keycode, layout_index, 0, keysyms); } -static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms, - xkb_keysym_t keysym) { - for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { - if (pressed_keysyms[i] == keysym) { - return i; - } - } - return -1; -} - -static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) { - size_t n = 0; - for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { - if (pressed_keysyms[i] != XKB_KEY_NoSymbol) { - ++n; - } - } - return n; -} - static void pressed_keysyms_add(xkb_keysym_t *pressed_keysyms, xkb_keysym_t keysym) { ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); From 21c61f1c0909b613471f18dd41e984c54540aca8 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 27 Dec 2017 21:23:30 +0100 Subject: [PATCH 132/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 83ded7206..045359cac 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 7988e3e40..8cc74bcc3 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 ff3f73a3d..f336c949f 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; From ccaedf5b1535db37f36d7eb1424d6fae5b1ac12a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 27 Dec 2017 15:25:16 -0500 Subject: [PATCH 133/522] run binding command --- sway/input/keyboard.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 326ee5845..8b43df825 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -3,6 +3,7 @@ #include "sway/input/seat.h" #include "sway/input/keyboard.h" #include "sway/input/input-manager.h" +#include "sway/commands.h" #include "log.h" static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) { @@ -80,7 +81,7 @@ static bool keyboard_execute_binding(struct sway_keyboard *keyboard, for (int j = 0; j < binding->keys->length; ++j) { match = pressed_keysyms_index(pressed_keysyms, - *(int*)binding->keys->items[j]) < 0; + *(int*)binding->keys->items[j]) >= 0; if (!match) { break; @@ -88,7 +89,13 @@ static bool keyboard_execute_binding(struct sway_keyboard *keyboard, } if (match) { - sway_log(L_DEBUG, "TODO: executing binding command: %s", binding->command); + sway_log(L_DEBUG, "running command for binding: %s", binding->command); + struct cmd_results *results = handle_command(binding->command); + if (results->status != CMD_SUCCESS) { + sway_log(L_DEBUG, "could not run command for binding: %s", + binding->command); + } + free_cmd_results(results); return true; } } From 27cd633b409bbe6692538a26738e052e7d865be0 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 27 Dec 2017 19:07:17 -0500 Subject: [PATCH 134/522] run compositor bindings last --- sway/input/keyboard.c | 82 ++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 8b43df825..032083e9d 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -34,18 +34,22 @@ static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms, * Returns true if the keysym was handled by a binding and false if the event * should be propagated to clients. */ -static bool keyboard_execute_compositor_binding(xkb_keysym_t keysym) { - if (keysym >= XKB_KEY_XF86Switch_VT_1 && - keysym <= XKB_KEY_XF86Switch_VT_12) { - if (wlr_backend_is_multi(server.backend)) { - struct wlr_session *session = - wlr_multi_get_session(server.backend); - if (session) { - unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1; - wlr_session_change_vt(session, vt); +static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, + xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) { + for (size_t i = 0; i < keysyms_len; ++i) { + xkb_keysym_t keysym = pressed_keysyms[i]; + if (keysym >= XKB_KEY_XF86Switch_VT_1 && + keysym <= XKB_KEY_XF86Switch_VT_12) { + if (wlr_backend_is_multi(server.backend)) { + struct wlr_session *session = + wlr_multi_get_session(server.backend); + if (session) { + unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1; + wlr_session_change_vt(session, vt); + } } + return true; } - return true; } return false; @@ -58,16 +62,8 @@ static bool keyboard_execute_compositor_binding(xkb_keysym_t keysym) { * Returns true if the keysym was handled by a binding and false if the event * should be propagated to clients. */ -static bool keyboard_execute_binding(struct sway_keyboard *keyboard, - xkb_keysym_t *pressed_keysyms, uint32_t modifiers, - const xkb_keysym_t *keysyms, size_t keysyms_len) { - // compositor bindings - for (size_t i = 0; i < keysyms_len; ++i) { - if (keyboard_execute_compositor_binding(keysyms[i])) { - return true; - } - } - +static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, + xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) { // configured bindings int n = pressed_keysyms_length(pressed_keysyms); list_t *keysym_bindings = config->current_mode->keysym_bindings; @@ -208,28 +204,48 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { xkb_keycode_t keycode = event->keycode + 8; bool handled = false; - uint32_t modifiers; const xkb_keysym_t *keysyms; - size_t keysyms_len; + + // handle keycodes + // TODO + handled = keyboard_execute_bindcode(keyboard); // handle translated keysyms - keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &keysyms, - &modifiers); + uint32_t translated_modifiers; + size_t translated_keysyms_len = + keyboard_keysyms_translated(keyboard, keycode, &keysyms, + &translated_modifiers); pressed_keysyms_update(keyboard->pressed_keysyms_translated, keysyms, - keysyms_len, event->state); - if (event->state == WLR_KEY_PRESSED) { - handled = keyboard_execute_binding(keyboard, - keyboard->pressed_keysyms_translated, modifiers, keysyms, - keysyms_len); + translated_keysyms_len, event->state); + if (event->state == WLR_KEY_PRESSED && !handled) { + handled = keyboard_execute_bindsym(keyboard, + keyboard->pressed_keysyms_translated, translated_modifiers, + translated_keysyms_len); } // Handle raw keysyms - keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &keysyms, &modifiers); - pressed_keysyms_update(keyboard->pressed_keysyms_raw, keysyms, keysyms_len, + uint32_t raw_modifiers; + size_t raw_keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &keysyms, &raw_modifiers); + pressed_keysyms_update(keyboard->pressed_keysyms_raw, keysyms, raw_keysyms_len, event->state); if (event->state == WLR_KEY_PRESSED && !handled) { - handled = keyboard_execute_binding(keyboard, - keyboard->pressed_keysyms_raw, modifiers, keysyms, keysyms_len); + handled = keyboard_execute_bindsym(keyboard, + keyboard->pressed_keysyms_raw, raw_modifiers, + raw_keysyms_len); + } + + // Compositor bindings + if (event->state == WLR_KEY_PRESSED && !handled) { + handled = + keyboard_execute_compositor_binding(keyboard, + keyboard->pressed_keysyms_translated, translated_modifiers, + translated_keysyms_len); + } + if (event->state == WLR_KEY_PRESSED && !handled) { + handled = + keyboard_execute_compositor_binding(keyboard, + keyboard->pressed_keysyms_raw, raw_modifiers, + raw_keysyms_len); } if (!handled) { From 8d567cd06202b4d68bf45af6e76e5bdc49bfffee Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 28 Dec 2017 14:51:17 -0500 Subject: [PATCH 135/522] bindcode --- sway/input/keyboard.c | 128 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 106 insertions(+), 22 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 032083e9d..2464db121 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -26,7 +26,6 @@ static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms, return -1; } - /** * Execute a built-in, hardcoded compositor binding. These are triggered from a * single keysym. @@ -56,8 +55,7 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, } /** - * Execute keyboard bindings. These include compositor bindings and user-defined - * bindings. + * Execute keyboard bindings bound with `bindysm`. * * Returns true if the keysym was handled by a binding and false if the event * should be propagated to clients. @@ -99,7 +97,110 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, return false; } -/* +static bool keysym_is_modifier(xkb_keysym_t keysym) { + switch (keysym) { + case XKB_KEY_Shift_L: case XKB_KEY_Shift_R: + case XKB_KEY_Control_L: case XKB_KEY_Control_R: + case XKB_KEY_Caps_Lock: + case XKB_KEY_Shift_Lock: + case XKB_KEY_Meta_L: case XKB_KEY_Meta_R: + case XKB_KEY_Alt_L: case XKB_KEY_Alt_R: + case XKB_KEY_Super_L: case XKB_KEY_Super_R: + case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R: + return true; + default: + return false; + } +} + +static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, + struct sway_binding *binding) { + uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard); + if (modifiers ^ binding->modifiers) { + return false; + } + + // every keycode in the binding must be present in the pressed keys on the + // keyboard + for (int i = 0; i < binding->keys->length; ++i) { + uint32_t binding_keycode = *(uint32_t*)binding->keys->items[i] + 8; + bool found = false; + for (size_t j = 0; j < keyboard->num_keycodes; ++j) { + xkb_keycode_t keycode = keyboard->keycodes[j] + 8; + if (keycode == binding_keycode) { + found = true; + break; + } + } + + if (!found) { + return false; + } + } + + // every keycode pressed on the keyboard must be present within the binding + // keys (unless it is a modifier) + for (size_t i = 0; i < keyboard->num_keycodes; ++i) { + xkb_keycode_t keycode = keyboard->keycodes[i] + 8; + bool found = false; + for (int j = 0; j < binding->keys->length; ++j) { + uint32_t binding_keycode = *(uint32_t*)binding->keys->items[j] + 8; + if (binding_keycode == keycode) { + found = true; + break; + } + } + + if (!found) { + if (!binding->modifiers) { + return false; + } + + // check if it is a modifier, which we know matched from the check + // above + const xkb_keysym_t *keysyms; + int num_keysyms = + xkb_state_key_get_syms(keyboard->xkb_state, + keycode, &keysyms); + if (num_keysyms != 1 || !keysym_is_modifier(keysyms[0])) { + return false; + } + } + } + + return true; +} + +/** + * Execute keyboard bindings bound with `bindcode`. + * + * Returns true if the keysym was handled by a binding and false if the event + * should be propagated to clients. + */ +static bool keyboard_execute_bindcode(struct sway_keyboard *keyboard) { + struct wlr_keyboard *wlr_keyboard = + keyboard->seat_device->input_device->wlr_device->keyboard; + list_t *keycode_bindings = config->current_mode->keycode_bindings; + for (int i = 0; i < keycode_bindings->length; ++i) { + struct sway_binding *binding = keycode_bindings->items[i]; + //bool match = true; + for (int j = 0; j < binding->keys->length; ++j) { + if (binding_matches_keycodes(wlr_keyboard, binding)) { + struct cmd_results *results = handle_command(binding->command); + if (results->status != CMD_SUCCESS) { + sway_log(L_DEBUG, "could not run command for binding: %s", + binding->command); + } + free_cmd_results(results); + return true; + } + } + } + + return false; +} + +/** * Get keysyms and modifiers from the keyboard as xkb sees them. * * This uses the xkb keysyms translation based on pressed modifiers and clears @@ -122,7 +223,7 @@ static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, keycode, keysyms); } -/* +/** * Get keysyms and modifiers from the keyboard as if modifiers didn't change * keysyms. * @@ -163,22 +264,6 @@ static void pressed_keysyms_remove(xkb_keysym_t *pressed_keysyms, } } -static bool keysym_is_modifier(xkb_keysym_t keysym) { - switch (keysym) { - case XKB_KEY_Shift_L: case XKB_KEY_Shift_R: - case XKB_KEY_Control_L: case XKB_KEY_Control_R: - case XKB_KEY_Caps_Lock: - case XKB_KEY_Shift_Lock: - case XKB_KEY_Meta_L: case XKB_KEY_Meta_R: - case XKB_KEY_Alt_L: case XKB_KEY_Alt_R: - case XKB_KEY_Super_L: case XKB_KEY_Super_R: - case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R: - return true; - default: - return false; - } -} - static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms, const xkb_keysym_t *keysyms, size_t keysyms_len, enum wlr_key_state state) { @@ -207,7 +292,6 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { const xkb_keysym_t *keysyms; // handle keycodes - // TODO handled = keyboard_execute_bindcode(keyboard); // handle translated keysyms From 0b8481f41af32daf75324fc1f202bce62cc702f4 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 28 Dec 2017 16:52:12 -0500 Subject: [PATCH 136/522] fix keyboard_execute_bindcode --- sway/input/keyboard.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 2464db121..eacb6ceb4 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -183,17 +183,14 @@ static bool keyboard_execute_bindcode(struct sway_keyboard *keyboard) { list_t *keycode_bindings = config->current_mode->keycode_bindings; for (int i = 0; i < keycode_bindings->length; ++i) { struct sway_binding *binding = keycode_bindings->items[i]; - //bool match = true; - for (int j = 0; j < binding->keys->length; ++j) { - if (binding_matches_keycodes(wlr_keyboard, binding)) { - struct cmd_results *results = handle_command(binding->command); - if (results->status != CMD_SUCCESS) { - sway_log(L_DEBUG, "could not run command for binding: %s", - binding->command); - } - free_cmd_results(results); - return true; + if (binding_matches_keycodes(wlr_keyboard, binding)) { + struct cmd_results *results = handle_command(binding->command); + if (results->status != CMD_SUCCESS) { + sway_log(L_DEBUG, "could not run command for binding: %s", + binding->command); } + free_cmd_results(results); + return true; } } From 62b7ab3959468124086a1ba95361b3eed069b4a7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 28 Dec 2017 18:50:22 -0500 Subject: [PATCH 137/522] overwrite old bindings --- sway/commands/bind.c | 83 +++++++++++++++++++++++++++++++++++++++---- sway/input/keyboard.c | 14 +++++--- 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 62aa535af..99f54f465 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -28,6 +28,44 @@ void free_sway_binding(struct sway_binding *binding) { free(binding); } +/** + * Returns true if the bindings have the same key and modifier combinations. + * Note that keyboard layout is not considered, so the bindings might actually + * not be equivalent on some layouts. + */ +bool binding_key_compare(struct sway_binding *binding_a, + struct sway_binding *binding_b) { + if (binding_a->bindcode != binding_b->bindcode) { + return false; + } + + if (binding_a->modifiers ^ binding_b->modifiers) { + return false; + } + + if (binding_a->keys->length != binding_b->keys->length) { + return false; + } + + int keys_len = binding_a->keys->length; + for (int i = 0; i < keys_len; ++i) { + uint32_t key_a = *(uint32_t*)binding_a->keys->items[i]; + bool found = false; + for (int j = 0; j < keys_len; ++j) { + uint32_t key_b = *(uint32_t*)binding_b->keys->items[j]; + if (key_b == key_a) { + found = true; + break; + } + } + if (!found) { + return false; + } + } + + return true; +} + struct cmd_results *cmd_bindsym(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1))) { @@ -95,11 +133,26 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { 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); + + list_t *mode_bindings = config->current_mode->keysym_bindings; + + // overwrite the binding if it already exists + bool overwritten = false; + for (int i = 0; i < mode_bindings->length; ++i) { + struct sway_binding *config_binding = mode_bindings->items[i]; + if (binding_key_compare(binding, config_binding)) { + sway_log(L_DEBUG, "overwriting old binding with command '%s'", + config_binding->command); + free_sway_binding(config_binding); + mode_bindings->items[i] = binding; + overwritten = true; + } + } + + if (!overwritten) { + list_add(mode_bindings, binding); + } sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command); @@ -162,10 +215,26 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { } 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); + + list_t *mode_bindings = config->current_mode->keycode_bindings; + + // overwrite the binding if it already exists + bool overwritten = false; + for (int i = 0; i < mode_bindings->length; ++i) { + struct sway_binding *config_binding = mode_bindings->items[i]; + if (binding_key_compare(binding, config_binding)) { + sway_log(L_DEBUG, "overwriting old binding with command '%s'", + config_binding->command); + free_sway_binding(config_binding); + mode_bindings->items[i] = binding; + overwritten = true; + } + } + + if (!overwritten) { + list_add(mode_bindings, binding); + } sway_log(L_DEBUG, "bindcode - Bound %s to command %s", argv[0], binding->command); diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index eacb6ceb4..6272dcce5 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -67,7 +67,9 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, list_t *keysym_bindings = config->current_mode->keysym_bindings; for (int i = 0; i < keysym_bindings->length; ++i) { struct sway_binding *binding = keysym_bindings->items[i]; + sway_log(L_DEBUG, "@@ checking binding: %s", binding->command); if (modifiers ^ binding->modifiers || n != binding->keys->length) { + sway_log(L_DEBUG, "@@ modifiers or key num dont match"); continue; } @@ -286,17 +288,18 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { xkb_keycode_t keycode = event->keycode + 8; bool handled = false; - const xkb_keysym_t *keysyms; // handle keycodes handled = keyboard_execute_bindcode(keyboard); + sway_log(L_DEBUG, "@@ handled by bindcode? %d", handled); // handle translated keysyms + const xkb_keysym_t *translated_keysyms; uint32_t translated_modifiers; size_t translated_keysyms_len = - keyboard_keysyms_translated(keyboard, keycode, &keysyms, + keyboard_keysyms_translated(keyboard, keycode, &translated_keysyms, &translated_modifiers); - pressed_keysyms_update(keyboard->pressed_keysyms_translated, keysyms, + pressed_keysyms_update(keyboard->pressed_keysyms_translated, translated_keysyms, translated_keysyms_len, event->state); if (event->state == WLR_KEY_PRESSED && !handled) { handled = keyboard_execute_bindsym(keyboard, @@ -305,9 +308,10 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { } // Handle raw keysyms + const xkb_keysym_t *raw_keysyms; uint32_t raw_modifiers; - size_t raw_keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &keysyms, &raw_modifiers); - pressed_keysyms_update(keyboard->pressed_keysyms_raw, keysyms, raw_keysyms_len, + size_t raw_keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &raw_modifiers); + pressed_keysyms_update(keyboard->pressed_keysyms_raw, raw_keysyms, raw_keysyms_len, event->state); if (event->state == WLR_KEY_PRESSED && !handled) { handled = keyboard_execute_bindsym(keyboard, From fff67906e189e3d64860557db99b5af49d848315 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 29 Dec 2017 11:16:57 +0100 Subject: [PATCH 138/522] Pretty-print all output info in swaymsg -t get_outputs --- swaymsg/main.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index b431872a6..8a720fcab 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -107,29 +107,42 @@ static void pretty_print_input(json_object *i) { } static void pretty_print_output(json_object *o) { - json_object *name, *rect, *focused, *active, *ws, *scale; + json_object *name, *rect, *focused, *active, *ws; json_object_object_get_ex(o, "name", &name); json_object_object_get_ex(o, "rect", &rect); json_object_object_get_ex(o, "focused", &focused); json_object_object_get_ex(o, "active", &active); json_object_object_get_ex(o, "current_workspace", &ws); + json_object *make, *model, *serial, *scale, *refresh, *transform; + json_object_object_get_ex(o, "make", &make); + json_object_object_get_ex(o, "model", &model); + json_object_object_get_ex(o, "serial", &serial); json_object_object_get_ex(o, "scale", &scale); + json_object_object_get_ex(o, "refresh", &refresh); + json_object_object_get_ex(o, "transform", &transform); json_object *x, *y, *width, *height; json_object_object_get_ex(rect, "x", &x); json_object_object_get_ex(rect, "y", &y); json_object_object_get_ex(rect, "width", &width); json_object_object_get_ex(rect, "height", &height); printf( - "Output %s%s%s\n" - " Geometry: %dx%d @ %d,%d\n" + "Output %s '%s %s %s'%s%s\n" + " Mode: %dx%d @ %f Hz\n" + " Position: %d,%d\n" " Scale factor: %dx\n" + " Transform: %s\n" " Workspace: %s\n\n", json_object_get_string(name), + json_object_get_string(make), + json_object_get_string(model), + json_object_get_string(serial), json_object_get_boolean(focused) ? " (focused)" : "", !json_object_get_boolean(active) ? " (inactive)" : "", json_object_get_int(width), json_object_get_int(height), + (float)json_object_get_int(refresh) / 1000, json_object_get_int(x), json_object_get_int(y), json_object_get_int(scale), + json_object_get_string(transform), json_object_get_string(ws) ); } From bd3ca70e3d67476f4d66e9bc31c67b11aefb3519 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 29 Dec 2017 09:10:07 -0500 Subject: [PATCH 139/522] fix nitpicks --- sway/commands/bind.c | 21 ++++++++++----------- sway/input/keyboard.c | 17 ++++++++--------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 99f54f465..ef9a4b7aa 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -16,15 +16,14 @@ int binding_order = 0; void free_sway_binding(struct sway_binding *binding) { + if (!binding) { + return; + } + 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_flat_list(binding->keys); } + free(binding->command); free(binding); } @@ -72,7 +71,7 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { return error; } - struct sway_binding *binding = malloc(sizeof(struct sway_binding)); + struct sway_binding *binding = calloc(1, sizeof(struct sway_binding)); if (!binding) { return cmd_results_new(CMD_FAILURE, "bindsym", "Unable to allocate binding"); @@ -122,7 +121,7 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { free_flat_list(split); return ret; } - xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); + xkb_keysym_t *key = calloc(1, sizeof(xkb_keysym_t)); if (!key) { free_sway_binding(binding); free_flat_list(split); @@ -165,7 +164,7 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { return error; } - struct sway_binding *binding = malloc(sizeof(struct sway_binding)); + struct sway_binding *binding = calloc(1, sizeof(struct sway_binding)); if (!binding) { return cmd_results_new(CMD_FAILURE, "bindsym", "Unable to allocate binding"); @@ -209,7 +208,7 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { list_free(split); return error; } - xkb_keycode_t *key = malloc(sizeof(xkb_keycode_t)); + xkb_keycode_t *key = calloc(1, sizeof(xkb_keycode_t)); *key = keycode - 8; list_add(binding->keys, key); } diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 6272dcce5..3090d32f2 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -67,9 +67,7 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, list_t *keysym_bindings = config->current_mode->keysym_bindings; for (int i = 0; i < keysym_bindings->length; ++i) { struct sway_binding *binding = keysym_bindings->items[i]; - sway_log(L_DEBUG, "@@ checking binding: %s", binding->command); if (modifiers ^ binding->modifiers || n != binding->keys->length) { - sway_log(L_DEBUG, "@@ modifiers or key num dont match"); continue; } @@ -85,7 +83,8 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, } if (match) { - sway_log(L_DEBUG, "running command for binding: %s", binding->command); + sway_log(L_DEBUG, "running command for binding: %s", + binding->command); struct cmd_results *results = handle_command(binding->command); if (results->status != CMD_SUCCESS) { sway_log(L_DEBUG, "could not run command for binding: %s", @@ -291,7 +290,6 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { // handle keycodes handled = keyboard_execute_bindcode(keyboard); - sway_log(L_DEBUG, "@@ handled by bindcode? %d", handled); // handle translated keysyms const xkb_keysym_t *translated_keysyms; @@ -299,8 +297,8 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { size_t translated_keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &translated_keysyms, &translated_modifiers); - pressed_keysyms_update(keyboard->pressed_keysyms_translated, translated_keysyms, - translated_keysyms_len, event->state); + pressed_keysyms_update(keyboard->pressed_keysyms_translated, + translated_keysyms, translated_keysyms_len, event->state); if (event->state == WLR_KEY_PRESSED && !handled) { handled = keyboard_execute_bindsym(keyboard, keyboard->pressed_keysyms_translated, translated_modifiers, @@ -310,9 +308,10 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { // Handle raw keysyms const xkb_keysym_t *raw_keysyms; uint32_t raw_modifiers; - size_t raw_keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &raw_modifiers); - pressed_keysyms_update(keyboard->pressed_keysyms_raw, raw_keysyms, raw_keysyms_len, - event->state); + size_t raw_keysyms_len = + keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &raw_modifiers); + pressed_keysyms_update(keyboard->pressed_keysyms_raw, raw_keysyms, + raw_keysyms_len, event->state); if (event->state == WLR_KEY_PRESSED && !handled) { handled = keyboard_execute_bindsym(keyboard, keyboard->pressed_keysyms_raw, raw_modifiers, From ead3f1e676923b0457cef77b0b482e76cac50307 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 29 Dec 2017 19:04:16 +0100 Subject: [PATCH 140/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 045359cac..eecdde3aa 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 8cc74bcc3..8c0fa63c9 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 f336c949f..e798a20e9 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 6f2a3abf1..c5574275b 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; From 7196f59db0698a4d31ee99763a1f43a7e53f95cc Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Sun, 31 Dec 2017 14:32:28 -0700 Subject: [PATCH 141/522] Consolidate WLR and Sway logging See #1390 --- sway/main.c | 48 ++++++++++++++++++++++++------------------------ sway/server.c | 13 +++++++------ 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/sway/main.c b/sway/main.c index bd69395a1..c18e26775 100644 --- a/sway/main.c +++ b/sway/main.c @@ -15,12 +15,12 @@ #include #include #endif +#include #include "sway/config.h" #include "sway/server.h" #include "sway/layout.h" #include "sway/ipc-server.h" #include "ipc-client.h" -#include "log.h" #include "readline.h" #include "stringop.h" #include "util.h" @@ -126,7 +126,7 @@ static void log_env() { "SWAYSOCK" }; for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { - sway_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); + wlr_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); } } @@ -141,14 +141,14 @@ static void log_distro() { for (size_t i = 0; i < sizeof(paths) / sizeof(char *); ++i) { FILE *f = fopen(paths[i], "r"); if (f) { - sway_log(L_INFO, "Contents of %s:", paths[i]); + wlr_log(L_INFO, "Contents of %s:", paths[i]); while (!feof(f)) { char *line; if (!(line = read_line(f))) { break; } if (*line) { - sway_log(L_INFO, "%s", line); + wlr_log(L_INFO, "%s", line); } free(line); } @@ -161,7 +161,7 @@ static void log_kernel() { return; FILE *f = popen("uname -a", "r"); if (!f) { - sway_log(L_INFO, "Unable to determine kernel version"); + wlr_log(L_INFO, "Unable to determine kernel version"); return; } while (!feof(f)) { @@ -170,7 +170,7 @@ static void log_kernel() { break; } if (*line) { - sway_log(L_INFO, "%s", line); + wlr_log(L_INFO, "%s", line); } free(line); } @@ -181,14 +181,14 @@ static void security_sanity_check() { // TODO: Notify users visually if this has issues struct stat s; if (stat("/proc", &s)) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "!! DANGER !! /proc is not available - sway CANNOT enforce security rules!"); } #ifdef __linux__ cap_flag_value_t v; cap_t cap = cap_get_proc(); if (!cap || cap_get_flag(cap, CAP_SYS_PTRACE, CAP_PERMITTED, &v) != 0 || v != CAP_SET) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "!! DANGER !! Sway does not have CAP_SYS_PTRACE and cannot enforce security rules for processes running as other users."); } if (cap) { @@ -204,13 +204,13 @@ static void executable_sanity_check() { stat(exe, &sb); // We assume that cap_get_file returning NULL implies ENODATA if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "sway executable has both the s(g)uid bit AND file caps set."); - sway_log(L_ERROR, + wlr_log(L_ERROR, "This is strongly discouraged (and completely broken)."); - sway_log(L_ERROR, + wlr_log(L_ERROR, "Please clear one of them (either the suid bit, or the file caps)."); - sway_log(L_ERROR, + wlr_log(L_ERROR, "If unsure, strip the file caps."); exit(EXIT_FAILURE); } @@ -221,16 +221,16 @@ static void executable_sanity_check() { static void drop_permissions(bool keep_caps) { if (getuid() != geteuid() || getgid() != getegid()) { if (setgid(getgid()) != 0) { - sway_log(L_ERROR, "Unable to drop root"); + wlr_log(L_ERROR, "Unable to drop root"); exit(EXIT_FAILURE); } if (setuid(getuid()) != 0) { - sway_log(L_ERROR, "Unable to drop root"); + wlr_log(L_ERROR, "Unable to drop root"); exit(EXIT_FAILURE); } } if (setuid(0) != -1) { - sway_log(L_ERROR, "Root privileges can be restored."); + wlr_log(L_ERROR, "Root privileges can be restored."); exit(EXIT_FAILURE); } #ifdef __linux__ @@ -238,11 +238,11 @@ static void drop_permissions(bool keep_caps) { // Drop every cap except CAP_SYS_PTRACE cap_t caps = cap_init(); cap_value_t keep = CAP_SYS_PTRACE; - sway_log(L_INFO, "Dropping extra capabilities"); + wlr_log(L_INFO, "Dropping extra capabilities"); if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || cap_set_proc(caps)) { - sway_log(L_ERROR, "Failed to drop extra capabilities"); + wlr_log(L_ERROR, "Failed to drop extra capabilities"); exit(EXIT_FAILURE); } } @@ -330,22 +330,22 @@ int main(int argc, char **argv) { // TODO: switch logging over to wlroots? if (debug) { - init_log(L_DEBUG); + wlr_log_init(L_DEBUG, NULL); } else if (verbose || validate) { - init_log(L_INFO); + wlr_log_init(L_INFO, NULL); } else { - init_log(L_ERROR); + wlr_log_init(L_ERROR, NULL); } if (optind < argc) { // Behave as IPC client if(optind != 1) { - sway_log(L_ERROR, "Don't use options with the IPC client"); + wlr_log(L_ERROR, "Don't use options with the IPC client"); exit(EXIT_FAILURE); } drop_permissions(false); char *socket_path = getenv("SWAYSOCK"); if (!socket_path) { - sway_log(L_ERROR, "Unable to retrieve socket path"); + wlr_log(L_ERROR, "Unable to retrieve socket path"); exit(EXIT_FAILURE); } char *command = join_args(argv + optind, argc - optind); @@ -359,7 +359,7 @@ int main(int argc, char **argv) { if (getuid() != geteuid() || getgid() != getegid()) { // Retain capabilities after setuid() if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { - sway_log(L_ERROR, "Cannot keep caps after setuid()"); + wlr_log(L_ERROR, "Cannot keep caps after setuid()"); exit(EXIT_FAILURE); } suid = true; @@ -380,7 +380,7 @@ int main(int argc, char **argv) { // prevent ipc from crashing sway signal(SIGPIPE, SIG_IGN); - sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); + wlr_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); init_layout(); diff --git a/sway/server.c b/sway/server.c index 32c8f03c5..365094ef2 100644 --- a/sway/server.c +++ b/sway/server.c @@ -10,12 +10,12 @@ #include // TODO WLR: make Xwayland optional #include +#include #include "sway/server.h" #include "sway/input/input-manager.h" -#include "log.h" bool server_init(struct sway_server *server) { - sway_log(L_DEBUG, "Initializing Wayland server"); + wlr_log(L_DEBUG, "Initializing Wayland server"); server->wl_display = wl_display_create(); server->wl_event_loop = wl_display_get_event_loop(server->wl_display); @@ -55,7 +55,8 @@ bool server_init(struct sway_server *server) { server->wl_shell_surface.notify = handle_wl_shell_surface; server->socket = wl_display_add_socket_auto(server->wl_display); - if (!sway_assert(server->socket, "Unable to open wayland socket")) { + if (!server->socket) { + wlr_log(L_ERROR, "Unable to open wayland socket"); wlr_backend_destroy(server->backend); return false; } @@ -71,11 +72,11 @@ void server_fini(struct sway_server *server) { } void server_run(struct sway_server *server) { - sway_log(L_INFO, "Running compositor on wayland display '%s'", + wlr_log(L_INFO, "Running compositor on wayland display '%s'", server->socket); setenv("_WAYLAND_DISPLAY", server->socket, true); - if (!sway_assert(wlr_backend_start(server->backend), - "Failed to start backend")) { + if (!wlr_backend_start(server->backend)) { + wlr_log(L_ERROR, "Failed to start backend"); wlr_backend_destroy(server->backend); return; } From 50e791cadbfc51d531fff44cfbe3323a3b456adf Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 4 Jan 2018 07:25:52 -0500 Subject: [PATCH 142/522] binding release --- include/sway/input/keyboard.h | 3 ++ sway/commands/bind.c | 4 ++ sway/input/keyboard.c | 96 +++++++++++++++++++++++++++-------- 3 files changed, 82 insertions(+), 21 deletions(-) diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index 0a5857f0a..8ec3eb356 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h @@ -14,7 +14,10 @@ struct sway_keyboard { struct wl_listener keyboard_modifiers; xkb_keysym_t pressed_keysyms_translated[SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP]; + uint32_t modifiers_translated; + xkb_keysym_t pressed_keysyms_raw[SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP]; + uint32_t modifiers_raw; }; struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, diff --git a/sway/commands/bind.c b/sway/commands/bind.c index ef9a4b7aa..791214041 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -34,6 +34,10 @@ void free_sway_binding(struct sway_binding *binding) { */ bool binding_key_compare(struct sway_binding *binding_a, struct sway_binding *binding_b) { + if (binding_a->release != binding_b->release) { + return false; + } + if (binding_a->bindcode != binding_b->bindcode) { return false; } diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 3090d32f2..7b90dacf1 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -1,3 +1,4 @@ +#include #include #include #include "sway/input/seat.h" @@ -54,6 +55,18 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, return false; } +static bool binding_matches_keystate(struct sway_binding *binding, + enum wlr_key_state key_state) { + if (key_state == WLR_KEY_PRESSED && !binding->release) { + return true; + } + if (key_state == WLR_KEY_RELEASED && binding->release) { + return true; + } + + return false; +} + /** * Execute keyboard bindings bound with `bindysm`. * @@ -61,13 +74,15 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, * should be propagated to clients. */ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, - xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) { + xkb_keysym_t *pressed_keysyms, uint32_t modifiers, enum wlr_key_state key_state) { // configured bindings int n = pressed_keysyms_length(pressed_keysyms); list_t *keysym_bindings = config->current_mode->keysym_bindings; for (int i = 0; i < keysym_bindings->length; ++i) { struct sway_binding *binding = keysym_bindings->items[i]; - if (modifiers ^ binding->modifiers || n != binding->keys->length) { + if (!binding_matches_keystate(binding, key_state) || + modifiers ^ binding->modifiers || + n != binding->keys->length) { continue; } @@ -115,16 +130,43 @@ static bool keysym_is_modifier(xkb_keysym_t keysym) { } static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, - struct sway_binding *binding) { + struct sway_binding *binding, struct wlr_event_keyboard_key *event) { + assert(binding->bindcode); + + uint32_t keycode = event->keycode + 8; + + if (!binding_matches_keystate(binding, event->state)) { + return false; + } + uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard); if (modifiers ^ binding->modifiers) { return false; } + // on release, the released key must be in the binding + if (event->state == WLR_KEY_RELEASED) { + bool found = false; + for (int i = 0; i < binding->keys->length; ++i) { + uint32_t binding_keycode = *(uint32_t*)binding->keys->items[i] + 8; + if (binding_keycode == keycode) { + found = true; + break; + } + } + if (!found) { + return false; + } + } + // every keycode in the binding must be present in the pressed keys on the // keyboard for (int i = 0; i < binding->keys->length; ++i) { uint32_t binding_keycode = *(uint32_t*)binding->keys->items[i] + 8; + if (event->state == WLR_KEY_RELEASED && keycode == binding_keycode) { + continue; + } + bool found = false; for (size_t j = 0; j < keyboard->num_keycodes; ++j) { xkb_keycode_t keycode = keyboard->keycodes[j] + 8; @@ -178,13 +220,14 @@ static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, * Returns true if the keysym was handled by a binding and false if the event * should be propagated to clients. */ -static bool keyboard_execute_bindcode(struct sway_keyboard *keyboard) { +static bool keyboard_execute_bindcode(struct sway_keyboard *keyboard, + struct wlr_event_keyboard_key *event) { struct wlr_keyboard *wlr_keyboard = keyboard->seat_device->input_device->wlr_device->keyboard; list_t *keycode_bindings = config->current_mode->keycode_bindings; for (int i = 0; i < keycode_bindings->length; ++i) { struct sway_binding *binding = keycode_bindings->items[i]; - if (binding_matches_keycodes(wlr_keyboard, binding)) { + if (binding_matches_keycodes(wlr_keyboard, binding, event)) { struct cmd_results *results = handle_command(binding->command); if (results->status != CMD_SUCCESS) { sway_log(L_DEBUG, "could not run command for binding: %s", @@ -289,50 +332,61 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { bool handled = false; // handle keycodes - handled = keyboard_execute_bindcode(keyboard); + handled = keyboard_execute_bindcode(keyboard, event); // handle translated keysyms + if (!handled && event->state == WLR_KEY_RELEASED) { + handled = keyboard_execute_bindsym(keyboard, + keyboard->pressed_keysyms_translated, + keyboard->modifiers_translated, + event->state); + } const xkb_keysym_t *translated_keysyms; - uint32_t translated_modifiers; size_t translated_keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &translated_keysyms, - &translated_modifiers); + &keyboard->modifiers_translated); pressed_keysyms_update(keyboard->pressed_keysyms_translated, translated_keysyms, translated_keysyms_len, event->state); - if (event->state == WLR_KEY_PRESSED && !handled) { + if (!handled && event->state == WLR_KEY_PRESSED) { handled = keyboard_execute_bindsym(keyboard, - keyboard->pressed_keysyms_translated, translated_modifiers, - translated_keysyms_len); + keyboard->pressed_keysyms_translated, + keyboard->modifiers_translated, + event->state); } // Handle raw keysyms + if (!handled && event->state == WLR_KEY_RELEASED) { + handled = keyboard_execute_bindsym(keyboard, + keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, + event->state); + } const xkb_keysym_t *raw_keysyms; - uint32_t raw_modifiers; size_t raw_keysyms_len = - keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &raw_modifiers); + keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &keyboard->modifiers_raw); pressed_keysyms_update(keyboard->pressed_keysyms_raw, raw_keysyms, raw_keysyms_len, event->state); - if (event->state == WLR_KEY_PRESSED && !handled) { + if (!handled && event->state == WLR_KEY_PRESSED) { handled = keyboard_execute_bindsym(keyboard, - keyboard->pressed_keysyms_raw, raw_modifiers, - raw_keysyms_len); + keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, + event->state); } // Compositor bindings - if (event->state == WLR_KEY_PRESSED && !handled) { + if (!handled && event->state == WLR_KEY_PRESSED) { handled = keyboard_execute_compositor_binding(keyboard, - keyboard->pressed_keysyms_translated, translated_modifiers, + keyboard->pressed_keysyms_translated, + keyboard->modifiers_translated, translated_keysyms_len); } - if (event->state == WLR_KEY_PRESSED && !handled) { + if (!handled && event->state == WLR_KEY_PRESSED) { handled = keyboard_execute_compositor_binding(keyboard, - keyboard->pressed_keysyms_raw, raw_modifiers, + keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, raw_keysyms_len); } - if (!handled) { + if (!handled || event->state == WLR_KEY_RELEASED) { wlr_seat_set_keyboard(wlr_seat, wlr_device); wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, event->keycode, event->state); From 8b4eb5d7d1846447b54ebf786c7dd6869a27670a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 4 Jan 2018 07:54:14 -0500 Subject: [PATCH 143/522] cleanup bindings --- sway/input/keyboard.c | 162 +++++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 7b90dacf1..c2bb25780 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -7,6 +7,22 @@ #include "sway/commands.h" #include "log.h" +static bool keysym_is_modifier(xkb_keysym_t keysym) { + switch (keysym) { + case XKB_KEY_Shift_L: case XKB_KEY_Shift_R: + case XKB_KEY_Control_L: case XKB_KEY_Control_R: + case XKB_KEY_Caps_Lock: + case XKB_KEY_Shift_Lock: + case XKB_KEY_Meta_L: case XKB_KEY_Meta_R: + case XKB_KEY_Alt_L: case XKB_KEY_Alt_R: + case XKB_KEY_Super_L: case XKB_KEY_Super_R: + case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R: + return true; + default: + return false; + } +} + static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) { size_t n = 0; for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { @@ -27,6 +43,63 @@ static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms, return -1; } +static void pressed_keysyms_add(xkb_keysym_t *pressed_keysyms, + xkb_keysym_t keysym) { + ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); + if (i < 0) { + i = pressed_keysyms_index(pressed_keysyms, XKB_KEY_NoSymbol); + if (i >= 0) { + pressed_keysyms[i] = keysym; + } + } +} + +static void pressed_keysyms_remove(xkb_keysym_t *pressed_keysyms, + xkb_keysym_t keysym) { + ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); + if (i >= 0) { + pressed_keysyms[i] = XKB_KEY_NoSymbol; + } +} + +static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms, + const xkb_keysym_t *keysyms, size_t keysyms_len, + enum wlr_key_state state) { + for (size_t i = 0; i < keysyms_len; ++i) { + if (keysym_is_modifier(keysyms[i])) { + continue; + } + if (state == WLR_KEY_PRESSED) { + pressed_keysyms_add(pressed_keysyms, keysyms[i]); + } else { // WLR_KEY_RELEASED + pressed_keysyms_remove(pressed_keysyms, keysyms[i]); + } + } +} + +static bool binding_matches_key_state(struct sway_binding *binding, + enum wlr_key_state key_state) { + if (key_state == WLR_KEY_PRESSED && !binding->release) { + return true; + } + if (key_state == WLR_KEY_RELEASED && binding->release) { + return true; + } + + return false; +} + +static void binding_execute_command(struct sway_binding *binding) { + sway_log(L_DEBUG, "running command for binding: %s", + binding->command); + struct cmd_results *results = handle_command(binding->command); + if (results->status != CMD_SUCCESS) { + sway_log(L_DEBUG, "could not run command for binding: %s", + binding->command); + } + free_cmd_results(results); +} + /** * Execute a built-in, hardcoded compositor binding. These are triggered from a * single keysym. @@ -55,32 +128,21 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, return false; } -static bool binding_matches_keystate(struct sway_binding *binding, - enum wlr_key_state key_state) { - if (key_state == WLR_KEY_PRESSED && !binding->release) { - return true; - } - if (key_state == WLR_KEY_RELEASED && binding->release) { - return true; - } - - return false; -} - /** - * Execute keyboard bindings bound with `bindysm`. + * Execute keyboard bindings bound with `bindysm` for the given keyboard state. * * Returns true if the keysym was handled by a binding and false if the event * should be propagated to clients. */ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, - xkb_keysym_t *pressed_keysyms, uint32_t modifiers, enum wlr_key_state key_state) { + xkb_keysym_t *pressed_keysyms, uint32_t modifiers, + enum wlr_key_state key_state) { // configured bindings int n = pressed_keysyms_length(pressed_keysyms); list_t *keysym_bindings = config->current_mode->keysym_bindings; for (int i = 0; i < keysym_bindings->length; ++i) { struct sway_binding *binding = keysym_bindings->items[i]; - if (!binding_matches_keystate(binding, key_state) || + if (!binding_matches_key_state(binding, key_state) || modifiers ^ binding->modifiers || n != binding->keys->length) { continue; @@ -98,14 +160,7 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, } if (match) { - sway_log(L_DEBUG, "running command for binding: %s", - binding->command); - struct cmd_results *results = handle_command(binding->command); - if (results->status != CMD_SUCCESS) { - sway_log(L_DEBUG, "could not run command for binding: %s", - binding->command); - } - free_cmd_results(results); + binding_execute_command(binding); return true; } } @@ -113,29 +168,13 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, return false; } -static bool keysym_is_modifier(xkb_keysym_t keysym) { - switch (keysym) { - case XKB_KEY_Shift_L: case XKB_KEY_Shift_R: - case XKB_KEY_Control_L: case XKB_KEY_Control_R: - case XKB_KEY_Caps_Lock: - case XKB_KEY_Shift_Lock: - case XKB_KEY_Meta_L: case XKB_KEY_Meta_R: - case XKB_KEY_Alt_L: case XKB_KEY_Alt_R: - case XKB_KEY_Super_L: case XKB_KEY_Super_R: - case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R: - return true; - default: - return false; - } -} - static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, struct sway_binding *binding, struct wlr_event_keyboard_key *event) { assert(binding->bindcode); uint32_t keycode = event->keycode + 8; - if (!binding_matches_keystate(binding, event->state)) { + if (!binding_matches_key_state(binding, event->state)) { return false; } @@ -215,7 +254,7 @@ static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, } /** - * Execute keyboard bindings bound with `bindcode`. + * Execute keyboard bindings bound with `bindcode` for the given keyboard state. * * Returns true if the keysym was handled by a binding and false if the event * should be propagated to clients. @@ -228,12 +267,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)) { - struct cmd_results *results = handle_command(binding->command); - if (results->status != CMD_SUCCESS) { - sway_log(L_DEBUG, "could not run command for binding: %s", - binding->command); - } - free_cmd_results(results); + binding_execute_command(binding); return true; } } @@ -286,40 +320,6 @@ static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, keycode, layout_index, 0, keysyms); } -static void pressed_keysyms_add(xkb_keysym_t *pressed_keysyms, - xkb_keysym_t keysym) { - ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); - if (i < 0) { - i = pressed_keysyms_index(pressed_keysyms, XKB_KEY_NoSymbol); - if (i >= 0) { - pressed_keysyms[i] = keysym; - } - } -} - -static void pressed_keysyms_remove(xkb_keysym_t *pressed_keysyms, - xkb_keysym_t keysym) { - ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); - if (i >= 0) { - pressed_keysyms[i] = XKB_KEY_NoSymbol; - } -} - -static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms, - const xkb_keysym_t *keysyms, size_t keysyms_len, - enum wlr_key_state state) { - for (size_t i = 0; i < keysyms_len; ++i) { - if (keysym_is_modifier(keysyms[i])) { - continue; - } - if (state == WLR_KEY_PRESSED) { - pressed_keysyms_add(pressed_keysyms, keysyms[i]); - } else { // WLR_KEY_RELEASED - pressed_keysyms_remove(pressed_keysyms, keysyms[i]); - } - } -} - static void handle_keyboard_key(struct wl_listener *listener, void *data) { struct sway_keyboard *keyboard = wl_container_of(listener, keyboard, keyboard_key); From dc0e6d46fb63aad09b8767d94976c6e56db5ffdb Mon Sep 17 00:00:00 2001 From: Rachel K Date: Thu, 4 Jan 2018 15:43:40 +0000 Subject: [PATCH 144/522] update json-c dep to 0.13 --- meson.build | 2 +- swaymsg/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 029aea46b..493921263 100644 --- a/meson.build +++ b/meson.build @@ -18,7 +18,7 @@ datadir = get_option('datadir') sysconfdir = get_option('sysconfdir') prefix = get_option('prefix') -jsonc = dependency('json-c', version: '>=0.12.1') +jsonc = dependency('json-c', version: '>=0.13') pcre = dependency('libpcre') wlroots = dependency('wlroots') wayland_server = dependency('wayland-server') diff --git a/swaymsg/main.c b/swaymsg/main.c index 8a720fcab..a34eced4e 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -156,7 +156,7 @@ static void pretty_print_version(json_object *v) { static void pretty_print_clipboard(json_object *v) { if (success(v, true)) { if (json_object_is_type(v, json_type_array)) { - for (int i = 0; i < json_object_array_length(v); ++i) { + for (size_t i = 0; i < json_object_array_length(v); ++i) { json_object *o = json_object_array_get_idx(v, i); printf("%s\n", json_object_get_string(o)); } From afca73b6fc799790a1e4c4f103788c357ebecb74 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 29 Dec 2017 11:25:07 +0100 Subject: [PATCH 145/522] apply_input_config: restore previous `current_input_config` This is important for freeing the proper one at end of block --- sway/commands.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/commands.c b/sway/commands.c index b0078a468..b7432bf60 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -70,8 +70,10 @@ 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) { From 28b8ea9f1ee57672f39e42521f6ed2aece0d3b2e Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 29 Dec 2017 11:28:10 +0100 Subject: [PATCH 146/522] cmd_input: cleanup around current_input_config - Restore old one if we weren't part of a block (should be NULL anyway) - Check current_input_config got properly allocated - free temporary current_input_config when done using it --- sway/commands/input.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sway/commands/input.c b/sway/commands/input.c index ccb1d2767..edf45e4c7 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -24,7 +24,11 @@ struct cmd_results *cmd_input(int argc, char **argv) { 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) { @@ -60,6 +64,7 @@ struct cmd_results *cmd_input(int argc, char **argv) { } else { res = cmd_results_new(CMD_INVALID, "input ", "Unknown command %s", argv[1]); } - current_input_config = NULL; + free_input_config(current_input_config); + current_input_config = old_input_config; return res; } From f5b33cb4b62438bd084505ec0632bc7dbedc0acd Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 29 Dec 2017 11:29:13 +0100 Subject: [PATCH 147/522] fix typos in comments/messages; add shutting down message --- sway/commands.c | 2 +- sway/config.c | 2 +- sway/main.c | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index b7432bf60..c1c6dc5d1 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -197,7 +197,7 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { struct cmd_results *handle_command(char *_exec) { // Even though this function will process multiple commands we will only // return the last error, if any (for now). (Since we have access to an - // error string we could e.g. concatonate all errors there.) + // error string we could e.g. concatenate all errors there.) struct cmd_results *results = NULL; char *exec = strdup(_exec); char *head = exec; diff --git a/sway/config.c b/sway/config.c index 312e0779c..53a54a07a 100644 --- a/sway/config.c +++ b/sway/config.c @@ -446,7 +446,7 @@ bool read_config(FILE *file, struct sway_config *config) { break; case CMD_DEFER: - sway_log(L_DEBUG, "Defferring command `%s'", line); + sway_log(L_DEBUG, "Deferring command `%s'", line); list_add(config->cmd_queue, strdup(line)); break; diff --git a/sway/main.c b/sway/main.c index c18e26775..f2f24be35 100644 --- a/sway/main.c +++ b/sway/main.c @@ -380,7 +380,7 @@ int main(int argc, char **argv) { // prevent ipc from crashing sway signal(SIGPIPE, SIG_IGN); - wlr_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); + wlr_log(L_INFO, "Starting sway version " SWAY_VERSION); init_layout(); @@ -414,6 +414,8 @@ int main(int argc, char **argv) { server_run(&server); } + wlr_log(L_INFO, "Shutting down sway"); + server_fini(&server); ipc_terminate(); From 9a326be7f881f8589049a517b9e3112b562d81ea Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 29 Dec 2017 11:31:08 +0100 Subject: [PATCH 148/522] config: leak sanitizer pass Add free for everything that's implemented right now. Will need to add more as the implementations are re-added. --- sway/config.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/sway/config.c b/sway/config.c index 53a54a07a..37f6e75a8 100644 --- a/sway/config.c +++ b/sway/config.c @@ -31,8 +31,79 @@ struct sway_config *config = NULL; +static void free_binding(struct sway_binding *bind) { + if (!bind) { + return; + } + free_flat_list(bind->keys); + free(bind->command); + free(bind); +} + +static void free_mode(struct sway_mode *mode) { + int i; + + if (!mode) { + return; + } + free(mode->name); + if (mode->keysym_bindings) { + for (i = 0; i < mode->keysym_bindings->length; i++) { + free_binding(mode->keysym_bindings->items[i]); + } + list_free(mode->keysym_bindings); + } + if (mode->keycode_bindings) { + for (i = 0; i < mode->keycode_bindings->length; i++) { + free_binding(mode->keycode_bindings->items[i]); + } + list_free(mode->keycode_bindings); + } + free(mode); +} + void free_config(struct sway_config *config) { - // TODO + int i; + + if (!config) { + return; + } + + // TODO: handle all currently unhandled lists as we add implementations + list_free(config->symbols); + if (config->modes) { + for (i = 0; i < config->modes->length; i++) { + free_mode(config->modes->items[i]); + } + list_free(config->modes); + } + list_free(config->bars); + list_free(config->cmd_queue); + list_free(config->workspace_outputs); + list_free(config->pid_workspaces); + list_free(config->output_configs); + if (config->input_configs) { + for (i = 0; i < config->input_configs->length; i++) { + free_input_config(config->input_configs->items[i]); + } + list_free(config->input_configs); + } + list_free(config->seat_configs); + list_free(config->criteria); + list_free(config->no_focus); + list_free(config->active_bar_modifiers); + list_free(config->config_chain); + list_free(config->command_policies); + list_free(config->feature_policies); + list_free(config->ipc_policies); + free(config->current_bar); + free(config->floating_scroll_up_cmd); + free(config->floating_scroll_down_cmd); + free(config->floating_scroll_left_cmd); + free(config->floating_scroll_right_cmd); + free(config->font); + free((char *)config->current_config); + free(config); } static void config_defaults(struct sway_config *config) { @@ -186,6 +257,7 @@ static char *get_config_path(void) { if (file_exists(path)) { return path; } + free(path); } } @@ -524,6 +596,7 @@ bool read_config(FILE *file, struct sway_config *config) { case CMD_BLOCK_INPUT: sway_log(L_DEBUG, "End of input block"); + free_input_config(current_input_config); current_input_config = NULL; block = CMD_BLOCK_END; break; From 19ddb70a3296a7cc3256be65c488c18d87de4261 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 29 Dec 2017 14:44:39 +0100 Subject: [PATCH 149/522] fixup free config use free_sway_binding --- sway/config.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/sway/config.c b/sway/config.c index 37f6e75a8..627ed94f5 100644 --- a/sway/config.c +++ b/sway/config.c @@ -31,15 +31,6 @@ struct sway_config *config = NULL; -static void free_binding(struct sway_binding *bind) { - if (!bind) { - return; - } - free_flat_list(bind->keys); - free(bind->command); - free(bind); -} - static void free_mode(struct sway_mode *mode) { int i; @@ -49,13 +40,13 @@ static void free_mode(struct sway_mode *mode) { free(mode->name); if (mode->keysym_bindings) { for (i = 0; i < mode->keysym_bindings->length; i++) { - free_binding(mode->keysym_bindings->items[i]); + free_sway_binding(mode->keysym_bindings->items[i]); } list_free(mode->keysym_bindings); } if (mode->keycode_bindings) { for (i = 0; i < mode->keycode_bindings->length; i++) { - free_binding(mode->keycode_bindings->items[i]); + free_sway_binding(mode->keycode_bindings->items[i]); } list_free(mode->keycode_bindings); } From c83900593daace2ef85174163edf2748179e28f2 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 29 Dec 2017 15:31:04 +0100 Subject: [PATCH 150/522] 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 diff --git a/include/sway/config.h b/include/sway/config.h index 405092e3f..0a9c45958 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 c1c6dc5d1..f01329db9 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 000000000..dcd928ba6 --- /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 627ed94f5..e0a93e192 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 01d5ef36d..30ec166bd 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', From 67985e903188a464e602d04f9ed218bd397f5ab1 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 5 Jan 2018 22:32:51 +0100 Subject: [PATCH 151/522] sway: change all sway_log to wlr_log --- common/ipc-client.c | 2 +- common/readline.c | 4 +- common/util.c | 2 +- include/log.h | 25 +---------- sway/commands.c | 12 +++--- sway/commands/bind.c | 8 ++-- sway/commands/exec.c | 2 +- sway/commands/exec_always.c | 8 ++-- sway/commands/input.c | 2 +- sway/commands/input/click_method.c | 2 +- sway/commands/input/events.c | 2 +- sway/commands/input/tap.c | 4 +- sway/commands/input/xkb_layout.c | 4 +- sway/commands/input/xkb_model.c | 4 +- sway/commands/input/xkb_options.c | 4 +- sway/commands/input/xkb_rules.c | 4 +- sway/commands/input/xkb_variant.c | 4 +- sway/commands/output.c | 8 ++-- sway/commands/seat.c | 2 +- sway/commands/set.c | 2 +- sway/config.c | 66 +++++++++++++++--------------- sway/config/input.c | 6 +-- sway/config/output.c | 16 ++++---- sway/config/seat.c | 6 +-- sway/desktop/output.c | 4 +- sway/desktop/wl_shell.c | 2 +- sway/desktop/xdg_shell_v6.c | 2 +- sway/desktop/xwayland.c | 2 +- sway/input/cursor.c | 12 +++--- sway/input/input-manager.c | 36 ++++++++-------- sway/input/keyboard.c | 6 +-- sway/input/seat.c | 8 ++-- sway/ipc-server.c | 50 +++++++++++----------- sway/tree/container.c | 14 +++---- sway/tree/layout.c | 20 ++++----- sway/tree/workspace.c | 2 +- 36 files changed, 167 insertions(+), 190 deletions(-) diff --git a/common/ipc-client.c b/common/ipc-client.c index 1ab6627bd..582c5e863 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -79,7 +79,7 @@ struct ipc_response *ipc_recv_response(int socketfd) { error_2: free(response); error_1: - sway_log(L_ERROR, "Unable to allocate memory for IPC response"); + wlr_log(L_ERROR, "Unable to allocate memory for IPC response"); return NULL; } diff --git a/common/readline.c b/common/readline.c index cc40a2cc1..ed5801de4 100644 --- a/common/readline.c +++ b/common/readline.c @@ -8,7 +8,7 @@ char *read_line(FILE *file) { char *string = malloc(size); char lastChar = '\0'; if (!string) { - sway_log(L_ERROR, "Unable to allocate memory for read_line"); + wlr_log(L_ERROR, "Unable to allocate memory for read_line"); return NULL; } while (1) { @@ -29,7 +29,7 @@ char *read_line(FILE *file) { char *new_string = realloc(string, size *= 2); if (!new_string) { free(string); - sway_log(L_ERROR, "Unable to allocate memory for read_line"); + wlr_log(L_ERROR, "Unable to allocate memory for read_line"); return NULL; } string = new_string; diff --git a/common/util.c b/common/util.c index 839811608..fb7f94541 100644 --- a/common/util.c +++ b/common/util.c @@ -113,7 +113,7 @@ uint32_t parse_color(const char *color) { int len = strlen(color); if (len != 6 && len != 8) { - sway_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); + wlr_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); return 0xFFFFFFFF; } uint32_t res = (uint32_t)strtoul(color, NULL, 16); diff --git a/include/log.h b/include/log.h index a1e33fa23..646776f57 100644 --- a/include/log.h +++ b/include/log.h @@ -1,22 +1,7 @@ #ifndef _SWAY_LOG_H #define _SWAY_LOG_H #include - -typedef enum { - L_SILENT = 0, - L_ERROR = 1, - L_INFO = 2, - L_DEBUG = 3, -} log_importance_t; - -void init_log(log_importance_t verbosity); -void set_log_level(log_importance_t verbosity); -log_importance_t get_log_level(void); -void reset_log_level(void); -// returns whether debug logging is on after switching. -bool toggle_debug_logging(void); -void sway_log_colors(int mode); -void sway_log_errno(log_importance_t verbosity, char* format, ...) __attribute__((format(printf,2,3))); +#include void _sway_abort(const char *filename, int line, const char* format, ...) __attribute__((format(printf,3,4))); #define sway_abort(FMT, ...) \ @@ -26,14 +11,6 @@ bool _sway_assert(bool condition, const char *filename, int line, const char* fo #define sway_assert(COND, FMT, ...) \ _sway_assert(COND, __FILE__, __LINE__, "%s:" FMT, __PRETTY_FUNCTION__, ##__VA_ARGS__) -void _sway_log(const char *filename, int line, log_importance_t verbosity, const char* format, ...) __attribute__((format(printf,4,5))); - -#define sway_log(VERBOSITY, FMT, ...) \ - _sway_log(__FILE__, __LINE__, VERBOSITY, FMT, ##__VA_ARGS__) - -#define sway_vlog(VERBOSITY, FMT, VA_ARGS) \ - _sway_vlog(__FILE__, __LINE__, VERBOSITY, FMT, VA_ARGS) - void error_handler(int sig); #endif diff --git a/sway/commands.c b/sway/commands.c index f01329db9..1005cf686 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -176,7 +176,7 @@ static struct cmd_handler seat_handlers[] = { 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_SEAT); + wlr_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); if (block == CMD_BLOCK_INPUT) { res = bsearch(&d, input_handlers, @@ -215,10 +215,10 @@ struct cmd_results *handle_command(char *_exec) { cmd = argsep(&cmdlist, ","); cmd += strspn(cmd, whitespace); if (strcmp(cmd, "") == 0) { - sway_log(L_INFO, "Ignoring empty command."); + wlr_log(L_INFO, "Ignoring empty command."); continue; } - sway_log(L_INFO, "Handling command '%s'", cmd); + wlr_log(L_INFO, "Handling command '%s'", cmd); //TODO better handling of argv int argc; char **argv = split_args(cmd, &argc); @@ -276,7 +276,7 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) { goto cleanup; } - sway_log(L_INFO, "handling config command '%s'", exec); + wlr_log(L_INFO, "handling config command '%s'", exec); // Endblock if (**argv == '}') { results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); @@ -380,7 +380,7 @@ struct cmd_results *config_commands_command(char *exec) { } policy->context = context; - sway_log(L_INFO, "Set command policy for %s to %d", + wlr_log(L_INFO, "Set command policy for %s to %d", policy->command, policy->context); results = cmd_results_new(CMD_SUCCESS, NULL, NULL); @@ -394,7 +394,7 @@ 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)); if (!results) { - sway_log(L_ERROR, "Unable to allocate command results"); + wlr_log(L_ERROR, "Unable to allocate command results"); return NULL; } results->status = status; diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 791214041..cbabb07bf 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -145,7 +145,7 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { for (int i = 0; i < mode_bindings->length; ++i) { struct sway_binding *config_binding = mode_bindings->items[i]; if (binding_key_compare(binding, config_binding)) { - sway_log(L_DEBUG, "overwriting old binding with command '%s'", + wlr_log(L_DEBUG, "overwriting old binding with command '%s'", config_binding->command); free_sway_binding(config_binding); mode_bindings->items[i] = binding; @@ -157,7 +157,7 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { list_add(mode_bindings, binding); } - sway_log(L_DEBUG, "bindsym - Bound %s to command %s", + wlr_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -227,7 +227,7 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { for (int i = 0; i < mode_bindings->length; ++i) { struct sway_binding *config_binding = mode_bindings->items[i]; if (binding_key_compare(binding, config_binding)) { - sway_log(L_DEBUG, "overwriting old binding with command '%s'", + wlr_log(L_DEBUG, "overwriting old binding with command '%s'", config_binding->command); free_sway_binding(config_binding); mode_bindings->items[i] = binding; @@ -239,7 +239,7 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { list_add(mode_bindings, binding); } - sway_log(L_DEBUG, "bindcode - Bound %s to command %s", + wlr_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/commands/exec.c b/sway/commands/exec.c index fbbc49410..363d5bef4 100644 --- a/sway/commands/exec.c +++ b/sway/commands/exec.c @@ -8,7 +8,7 @@ struct cmd_results *cmd_exec(int argc, char **argv) { 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); + wlr_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); free(args); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 9527a4872..61870c513 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -20,7 +20,7 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { char *tmp = NULL; if (strcmp((char*)*argv, "--no-startup-id") == 0) { - sway_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); + wlr_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) { return error; } @@ -35,11 +35,11 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { strncpy(cmd, tmp, sizeof(cmd)); cmd[sizeof(cmd) - 1] = 0; free(tmp); - sway_log(L_DEBUG, "Executing %s", cmd); + wlr_log(L_DEBUG, "Executing %s", cmd); int fd[2]; if (pipe(fd) != 0) { - sway_log(L_ERROR, "Unable to create pipe for fork"); + wlr_log(L_ERROR, "Unable to create pipe for fork"); } pid_t pid; @@ -75,7 +75,7 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { // cleanup child process wait(0); if (*child > 0) { - sway_log(L_DEBUG, "Child process created with pid %d", *child); + wlr_log(L_DEBUG, "Child process created with pid %d", *child); // TODO: add PID to active workspace } else { free(child); diff --git a/sway/commands/input.c b/sway/commands/input.c index edf45e4c7..5ea39f626 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -12,7 +12,7 @@ struct cmd_results *cmd_input(int argc, char **argv) { if (config->reading && strcmp("{", argv[1]) == 0) { current_input_config = new_input_config(argv[0]); - sway_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); + wlr_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); } diff --git a/sway/commands/input/click_method.c b/sway/commands/input/click_method.c index dcf64c1a2..22eb15f71 100644 --- a/sway/commands/input/click_method.c +++ b/sway/commands/input/click_method.c @@ -6,7 +6,7 @@ #include "log.h" struct cmd_results *input_cmd_click_method(int argc, char **argv) { - sway_log(L_DEBUG, "click_method for device: %d %s", + 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))) { diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c index 8a74c11ef..a1bfbacd3 100644 --- a/sway/commands/input/events.c +++ b/sway/commands/input/events.c @@ -6,7 +6,7 @@ #include "log.h" struct cmd_results *input_cmd_events(int argc, char **argv) { - sway_log(L_DEBUG, "events for device: %s", + 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))) { diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c index 8547c0cd8..ecab9a5b9 100644 --- a/sway/commands/input/tap.c +++ b/sway/commands/input/tap.c @@ -6,7 +6,7 @@ #include "log.h" struct cmd_results *input_cmd_tap(int argc, char **argv) { - sway_log(L_DEBUG, "tap for device: %s", current_input_config->identifier); + 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; @@ -26,7 +26,7 @@ struct cmd_results *input_cmd_tap(int argc, char **argv) { "Expected 'tap '"); } - sway_log(L_DEBUG, "apply-tap for device: %s", + wlr_log(L_DEBUG, "apply-tap for device: %s", current_input_config->identifier); 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 a25d38509..25db1a331 100644 --- a/sway/commands/input/xkb_layout.c +++ b/sway/commands/input/xkb_layout.c @@ -5,7 +5,7 @@ #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); + 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; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { new_config->xkb_layout = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_layout for device: %s layout: %s", + wlr_log(L_DEBUG, "apply-xkb_layout for device: %s layout: %s", current_input_config->identifier, new_config->xkb_layout); 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 9729e8696..819b796bf 100644 --- a/sway/commands/input/xkb_model.c +++ b/sway/commands/input/xkb_model.c @@ -5,7 +5,7 @@ #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); + 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; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { new_config->xkb_model = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_model for device: %s model: %s", + wlr_log(L_DEBUG, "apply-xkb_model for device: %s model: %s", current_input_config->identifier, new_config->xkb_model); 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 504849ccb..ff5f83ecd 100644 --- a/sway/commands/input/xkb_options.c +++ b/sway/commands/input/xkb_options.c @@ -5,7 +5,7 @@ #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); + 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; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { new_config->xkb_options = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_options for device: %s options: %s", + wlr_log(L_DEBUG, "apply-xkb_options for device: %s options: %s", current_input_config->identifier, new_config->xkb_options); 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 db7d8abe3..aafe00037 100644 --- a/sway/commands/input/xkb_rules.c +++ b/sway/commands/input/xkb_rules.c @@ -5,7 +5,7 @@ #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); + 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; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { new_config->xkb_rules = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_rules for device: %s rules: %s", + wlr_log(L_DEBUG, "apply-xkb_rules for device: %s rules: %s", current_input_config->identifier, new_config->xkb_rules); 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 855e6abc1..89a61fdce 100644 --- a/sway/commands/input/xkb_variant.c +++ b/sway/commands/input/xkb_variant.c @@ -5,7 +5,7 @@ #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); + 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; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { new_config->xkb_variant = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_variant for device: %s variant: %s", + wlr_log(L_DEBUG, "apply-xkb_variant for device: %s variant: %s", current_input_config->identifier, new_config->xkb_variant); apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/output.c b/sway/commands/output.c index 8c0fa63c9..e747eb4e7 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -203,12 +203,12 @@ static struct cmd_results *cmd_output_background(struct output_config *output, if (src) { sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); } else { - sway_log(L_ERROR, + wlr_log(L_ERROR, "Unable to allocate background source"); } free(conf); } else { - sway_log(L_ERROR, "Unable to allocate background source"); + wlr_log(L_ERROR, "Unable to allocate background source"); } } if (!src || access(src, F_OK) == -1) { @@ -238,7 +238,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { struct output_config *output = new_output_config(argv[0]); if (!output) { - sway_log(L_ERROR, "Failed to allocate output config"); + wlr_log(L_ERROR, "Failed to allocate output config"); return NULL; } @@ -284,7 +284,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { list_add(config->output_configs, output); } - sway_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " + wlr_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " "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, diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 155bc510e..6284002bf 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -12,7 +12,7 @@ struct cmd_results *cmd_seat(int argc, char **argv) { 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); + wlr_log(L_DEBUG, "entering seat block: %s", current_seat_config->name); return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); } diff --git a/sway/commands/set.c b/sway/commands/set.c index dcd928ba6..856c73e79 100644 --- a/sway/commands/set.c +++ b/sway/commands/set.c @@ -33,7 +33,7 @@ struct cmd_results *cmd_set(int argc, char **argv) { } if (argv[0][0] != '$') { - sway_log(L_INFO, "Warning: variable '%s' doesn't start with $", argv[0]); + wlr_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); diff --git a/sway/config.c b/sway/config.c index e0a93e192..5ec45b172 100644 --- a/sway/config.c +++ b/sway/config.c @@ -232,12 +232,12 @@ static char *get_config_path(void) { 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"); + wlr_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); + wlr_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); free(config_home); } } @@ -263,7 +263,7 @@ static char *get_config_path(void) { 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); + wlr_log(L_INFO, "Loading config from %s", path); current_config_path = path; struct stat sb; @@ -272,13 +272,13 @@ static bool load_config(const char *path, struct sway_config *config) { } if (path == NULL) { - sway_log(L_ERROR, "Unable to find a config file!"); + wlr_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); + wlr_log(L_ERROR, "Unable to open %s for reading", path); return false; } @@ -286,7 +286,7 @@ static bool load_config(const char *path, struct sway_config *config) { fclose(f); if (!config_load_success) { - sway_log(L_ERROR, "Error(s) loading config!"); + wlr_log(L_ERROR, "Error(s) loading config!"); } current_config_path = NULL; @@ -313,7 +313,7 @@ bool load_main_config(const char *file, bool is_active) { config_defaults(config); if (is_active) { - sway_log(L_DEBUG, "Performing configuration file reload"); + wlr_log(L_DEBUG, "Performing configuration file reload"); config->reloading = true; config->active = true; } @@ -327,7 +327,7 @@ bool load_main_config(const char *file, bool is_active) { bool success = true; DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); if (!dir) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "%s does not exist, sway will have no security configuration" " and will probably be broken", SYSCONFDIR "/sway/security.d"); } else { @@ -356,7 +356,7 @@ bool load_main_config(const char *file, bool is_active) { 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, + wlr_log(L_ERROR, "Refusing to load %s - it must be owned by root " "and mode 644 or 444", _path); success = false; @@ -398,7 +398,7 @@ static bool load_include_config(const char *path, const char *parent_dir, len = len + strlen(parent_dir) + 2; full_path = malloc(len * sizeof(char)); if (!full_path) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "Unable to allocate full path to included config"); return false; } @@ -409,7 +409,7 @@ static bool load_include_config(const char *path, const char *parent_dir, free(full_path); if (real_path == NULL) { - sway_log(L_DEBUG, "%s not found.", path); + wlr_log(L_DEBUG, "%s not found.", path); return false; } @@ -418,7 +418,7 @@ static bool load_include_config(const char *path, const char *parent_dir, for (j = 0; j < config->config_chain->length; ++j) { char *old_path = config->config_chain->items[j]; if (strcmp(real_path, old_path) == 0) { - sway_log(L_DEBUG, + wlr_log(L_DEBUG, "%s already included once, won't be included again.", real_path); free(real_path); @@ -472,7 +472,7 @@ bool load_include_configs(const char *path, struct sway_config *config) { // restore wd if (chdir(wd) < 0) { free(wd); - sway_log(L_ERROR, "failed to restore working directory"); + wlr_log(L_ERROR, "failed to restore working directory"); return false; } @@ -508,13 +508,13 @@ bool read_config(FILE *file, struct sway_config *config) { switch(res->status) { case CMD_FAILURE: case CMD_INVALID: - sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, + wlr_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, "Deferring command `%s'", line); + wlr_log(L_DEBUG, "Deferring command `%s'", line); list_add(config->cmd_queue, strdup(line)); break; @@ -522,7 +522,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_MODE; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -530,7 +530,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_INPUT; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -538,7 +538,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_SEAT; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -546,7 +546,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_BAR; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -554,7 +554,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_BAR) { block = CMD_BLOCK_BAR_COLORS; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -562,7 +562,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_COMMANDS; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -570,7 +570,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_IPC; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -578,59 +578,59 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_IPC) { block = CMD_BLOCK_IPC_EVENTS; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_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"); + wlr_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"); + wlr_log(L_DEBUG, "End of input block"); free_input_config(current_input_config); current_input_config = NULL; block = CMD_BLOCK_END; break; case CMD_BLOCK_SEAT: - sway_log(L_DEBUG, "End of seat block"); + wlr_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"); + wlr_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"); + wlr_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"); + wlr_log(L_DEBUG, "End of commands block"); block = CMD_BLOCK_END; break; case CMD_BLOCK_IPC: - sway_log(L_DEBUG, "End of IPC block"); + wlr_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"); + wlr_log(L_DEBUG, "End of IPC events block"); block = CMD_BLOCK_IPC; break; case CMD_BLOCK_END: - sway_log(L_ERROR, "Unmatched }"); + wlr_log(L_ERROR, "Unmatched }"); break; default:; @@ -663,7 +663,7 @@ char *do_var_replacement(char *str) { int vvlen = strlen(var->value); char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); if (!newstr) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "Unable to allocate replacement " "during variable expansion"); break; diff --git a/sway/config/input.c b/sway/config/input.c index 6f8d31f75..961813029 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -8,13 +8,13 @@ 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"); + wlr_log(L_DEBUG, "Unable to allocate input config"); return NULL; } - sway_log(L_DEBUG, "new_input_config(%s)", identifier); + wlr_log(L_DEBUG, "new_input_config(%s)", identifier); if (!(input->identifier = strdup(identifier))) { free(input); - sway_log(L_DEBUG, "Unable to allocate input config"); + wlr_log(L_DEBUG, "Unable to allocate input config"); return NULL; } diff --git a/sway/config/output.c b/sway/config/output.c index e798a20e9..69e883f1d 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -84,7 +84,7 @@ static void set_mode(struct wlr_output *output, int width, int height, float refresh_rate) { int mhz = (int)(refresh_rate * 1000); if (wl_list_empty(&output->modes)) { - sway_log(L_DEBUG, "Assigning custom mode to %s", output->name); + wlr_log(L_DEBUG, "Assigning custom mode to %s", output->name); wlr_output_set_custom_mode(output, width, height, mhz); return; } @@ -100,9 +100,9 @@ static void set_mode(struct wlr_output *output, int width, int height, } } if (!best) { - sway_log(L_ERROR, "Configured mode for %s not available", output->name); + wlr_log(L_ERROR, "Configured mode for %s not available", output->name); } else { - sway_log(L_DEBUG, "Assigning configured mode to %s", output->name); + wlr_log(L_DEBUG, "Assigning configured mode to %s", output->name); wlr_output_set_mode(output, best); } } @@ -119,22 +119,22 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { } if (oc && oc->width > 0 && oc->height > 0) { - sway_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, + wlr_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, oc->height, oc->refresh_rate); set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); } if (oc && oc->scale > 0) { - sway_log(L_DEBUG, "Set %s scale to %f", oc->name, oc->scale); + wlr_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) { - sway_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); + wlr_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); wlr_output_set_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); + wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); wlr_output_layout_add(root_container.sway_root->output_layout, wlr_output, oc->x, oc->y); } else { @@ -165,7 +165,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { terminate_swaybg(output->bg_pid); } - sway_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); + wlr_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); size_t bufsize = 12; char output_id[bufsize]; diff --git a/sway/config/seat.c b/sway/config/seat.c index 113139e8c..03cc6d4ea 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -7,11 +7,11 @@ 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"); + wlr_log(L_DEBUG, "Unable to allocate seat config"); return NULL; } - sway_log(L_DEBUG, "new_seat_config(%s)", name); + wlr_log(L_DEBUG, "new_seat_config(%s)", name); seat->name = strdup(name); if (!sway_assert(seat->name, "could not allocate name for seat")) { free(seat); @@ -34,7 +34,7 @@ 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"); + wlr_log(L_DEBUG, "cannot allocate attachment config"); return NULL; } return attachment; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 3b87c2e7e..2b428c30b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -110,7 +110,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { void output_add_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_add); struct wlr_output *wlr_output = data; - sway_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); + wlr_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); struct sway_output *output = calloc(1, sizeof(struct sway_output)); if (!output) { @@ -140,7 +140,7 @@ void output_add_notify(struct wl_listener *listener, void *data) { void output_remove_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_remove); struct wlr_output *wlr_output = data; - sway_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); + wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); swayc_t *output_container = NULL; for (int i = 0 ; i < root_container.children->length; ++i) { diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index a7bb8eb5a..345a1398c 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -82,7 +82,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { return; } - sway_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", + wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", shell_surface->title, shell_surface->class); wlr_wl_shell_surface_ping(shell_surface); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 5ff19f7eb..df48345c7 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -88,7 +88,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { return; } - sway_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", + wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", xdg_surface->title, xdg_surface->app_id); wlr_xdg_surface_v6_ping(xdg_surface); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 42e82c645..43bb2e006 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -124,7 +124,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { return; } - sway_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", + wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", xsurface->title, xsurface->class); struct sway_xwayland_surface *sway_surface = diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 3b5cfce5c..c51b59f99 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -85,35 +85,35 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); struct wlr_event_touch_down *event = data; - sway_log(L_DEBUG, "TODO: handle touch down event: %p", event); + wlr_log(L_DEBUG, "TODO: handle touch down event: %p", event); } static void handle_touch_up(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); struct wlr_event_touch_up *event = data; - sway_log(L_DEBUG, "TODO: handle touch up event: %p", event); + wlr_log(L_DEBUG, "TODO: handle touch up event: %p", event); } static void handle_touch_motion(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_motion); struct wlr_event_touch_motion *event = data; - sway_log(L_DEBUG, "TODO: handle touch motion event: %p", event); + wlr_log(L_DEBUG, "TODO: handle touch motion event: %p", event); } static void handle_tool_axis(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); struct wlr_event_tablet_tool_axis *event = data; - sway_log(L_DEBUG, "TODO: handle tool axis event: %p", event); + wlr_log(L_DEBUG, "TODO: handle tool axis event: %p", event); } static void handle_tool_tip(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); struct wlr_event_tablet_tool_tip *event = data; - sway_log(L_DEBUG, "TODO: handle tool tip event: %p", event); + wlr_log(L_DEBUG, "TODO: handle tool tip event: %p", event); } static void handle_request_set_cursor(struct wl_listener *listener, @@ -121,7 +121,7 @@ static void handle_request_set_cursor(struct wl_listener *listener, struct sway_cursor *cursor = wl_container_of(listener, cursor, request_set_cursor); struct wlr_seat_pointer_request_set_cursor_event *event = data; - sway_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); + wlr_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); } struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 128a818a0..26cf5035d 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -52,7 +52,7 @@ static char *get_device_identifier(struct wlr_input_device *device) { int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; char *identifier = malloc(len); if (!identifier) { - sway_log(L_ERROR, "Unable to allocate unique input device name"); + wlr_log(L_ERROR, "Unable to allocate unique input device name"); return NULL; } @@ -93,60 +93,60 @@ static void sway_input_manager_libinput_config_pointer(struct sway_input_device } libinput_device = wlr_libinput_get_device_handle(wlr_device); - sway_log(L_DEBUG, "sway_input_manager_libinput_config_pointer(%s)", ic->identifier); + wlr_log(L_DEBUG, "sway_input_manager_libinput_config_pointer(%s)", ic->identifier); if (ic->accel_profile != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", ic->identifier, ic->accel_profile); libinput_device_config_accel_set_profile(libinput_device, ic->accel_profile); } if (ic->click_method != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", ic->identifier, ic->click_method); libinput_device_config_click_set_method(libinput_device, ic->click_method); } if (ic->drag_lock != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", ic->identifier, ic->click_method); libinput_device_config_tap_set_drag_lock_enabled(libinput_device, ic->drag_lock); } if (ic->dwt != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", ic->identifier, ic->dwt); libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); } if (ic->left_handed != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)", ic->identifier, ic->left_handed); libinput_device_config_left_handed_set(libinput_device, ic->left_handed); } if (ic->middle_emulation != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", ic->identifier, ic->middle_emulation); libinput_device_config_middle_emulation_set_enabled(libinput_device, ic->middle_emulation); } if (ic->natural_scroll != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", ic->identifier, ic->natural_scroll); libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, ic->natural_scroll); } if (ic->pointer_accel != FLT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", ic->identifier, ic->pointer_accel); libinput_device_config_accel_set_speed(libinput_device, ic->pointer_accel); } if (ic->scroll_method != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", ic->identifier, ic->scroll_method); libinput_device_config_scroll_set_method(libinput_device, ic->scroll_method); } if (ic->send_events != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", ic->identifier, ic->send_events); libinput_device_config_send_events_set_mode(libinput_device, ic->send_events); } if (ic->tap != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", ic->identifier, ic->tap); libinput_device_config_tap_set_enabled(libinput_device, ic->tap); } @@ -167,7 +167,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { input_device->identifier = get_device_identifier(device); wl_list_insert(&input->devices, &input_device->link); - sway_log(L_DEBUG, "adding device: '%s'", + wlr_log(L_DEBUG, "adding device: '%s'", input_device->identifier); // find config @@ -185,7 +185,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { struct sway_seat *seat = NULL; if (!input_has_seat_configuration(input)) { - sway_log(L_DEBUG, "no seat configuration, using default seat"); + wlr_log(L_DEBUG, "no seat configuration, using default seat"); seat = input_manager_get_seat(input, default_seat); sway_seat_add_device(seat, input_device); return; @@ -213,7 +213,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { } if (!added) { - sway_log(L_DEBUG, + wlr_log(L_DEBUG, "device '%s' is not configured on any seats", input_device->identifier); } @@ -231,7 +231,7 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { return; } - sway_log(L_DEBUG, "removing device: '%s'", + wlr_log(L_DEBUG, "removing device: '%s'", input_device->identifier); struct sway_seat *seat = NULL; @@ -309,7 +309,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) { - sway_log(L_DEBUG, "applying new seat config for seat %s", + wlr_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); if (!seat) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index c2bb25780..e7539c48b 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -90,11 +90,11 @@ static bool binding_matches_key_state(struct sway_binding *binding, } static void binding_execute_command(struct sway_binding *binding) { - sway_log(L_DEBUG, "running command for binding: %s", + wlr_log(L_DEBUG, "running command for binding: %s", binding->command); struct cmd_results *results = handle_command(binding->command); if (results->status != CMD_SUCCESS) { - sway_log(L_DEBUG, "could not run command for binding: %s", + wlr_log(L_DEBUG, "could not run command for binding: %s", binding->command); } free_cmd_results(results); @@ -467,7 +467,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { - sway_log(L_DEBUG, "cannot configure keyboard: keymap does not exist"); + wlr_log(L_DEBUG, "cannot configure keyboard: keymap does not exist"); xkb_context_unref(context); return; } diff --git a/sway/input/seat.c b/sway/input/seat.c index 9a6a667bd..268486ab3 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -112,7 +112,7 @@ void sway_seat_configure_device(struct sway_seat *seat, case WLR_INPUT_DEVICE_TOUCH: case WLR_INPUT_DEVICE_TABLET_PAD: case WLR_INPUT_DEVICE_TABLET_TOOL: - sway_log(L_DEBUG, "TODO: configure other devices"); + wlr_log(L_DEBUG, "TODO: configure other devices"); break; } } @@ -127,11 +127,11 @@ void sway_seat_add_device(struct sway_seat *seat, 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"); + wlr_log(L_DEBUG, "could not allocate seat device"); return; } - sway_log(L_DEBUG, "adding device %s to seat %s", + wlr_log(L_DEBUG, "adding device %s to seat %s", input_device->identifier, seat->wlr_seat->name); seat_device->sway_seat = seat; @@ -150,7 +150,7 @@ void sway_seat_remove_device(struct sway_seat *seat, return; } - sway_log(L_DEBUG, "removing device %s from seat %s", + wlr_log(L_DEBUG, "removing device %s from seat %s", input_device->identifier, seat->wlr_seat->name); seat_device_destroy(seat_device); diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 046e40a8a..d2dd881f0 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -125,32 +125,32 @@ struct sockaddr_un *ipc_user_sockaddr(void) { int ipc_handle_connection(int fd, uint32_t mask, void *data) { (void) fd; struct sway_server *server = data; - sway_log(L_DEBUG, "Event on IPC listening socket"); + wlr_log(L_DEBUG, "Event on IPC listening socket"); assert(mask == WL_EVENT_READABLE); int client_fd = accept(ipc_socket, NULL, NULL); if (client_fd == -1) { - sway_log_errno(L_ERROR, "Unable to accept IPC client connection"); + wlr_log_errno(L_ERROR, "Unable to accept IPC client connection"); return 0; } int flags; if ((flags = fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { - sway_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); + wlr_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); close(client_fd); return 0; } if ((flags = fcntl(client_fd, F_GETFL)) == -1 || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { - sway_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); + wlr_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); close(client_fd); return 0; } struct ipc_client *client = malloc(sizeof(struct ipc_client)); if (!client) { - sway_log(L_ERROR, "Unable to allocate ipc client"); + wlr_log(L_ERROR, "Unable to allocate ipc client"); close(client_fd); return 0; } @@ -166,12 +166,12 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { client->write_buffer_len = 0; client->write_buffer = malloc(client->write_buffer_size); if (!client->write_buffer) { - sway_log(L_ERROR, "Unable to allocate ipc client write buffer"); + wlr_log(L_ERROR, "Unable to allocate ipc client write buffer"); close(client_fd); return 0; } - sway_log(L_DEBUG, "New client: fd %d", client_fd); + wlr_log(L_DEBUG, "New client: fd %d", client_fd); list_add(ipc_client_list, client); return 0; } @@ -182,22 +182,22 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; if (mask & WL_EVENT_ERROR) { - sway_log(L_ERROR, "IPC Client socket error, removing client"); + wlr_log(L_ERROR, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } if (mask & WL_EVENT_HANGUP) { - sway_log(L_DEBUG, "Client %d hung up", client->fd); + wlr_log(L_DEBUG, "Client %d hung up", client->fd); ipc_client_disconnect(client); return 0; } - sway_log(L_DEBUG, "Client %d readable", client->fd); + wlr_log(L_DEBUG, "Client %d readable", client->fd); int read_available; if (ioctl(client_fd, FIONREAD, &read_available) == -1) { - sway_log_errno(L_INFO, "Unable to read IPC socket buffer size"); + wlr_log_errno(L_INFO, "Unable to read IPC socket buffer size"); ipc_client_disconnect(client); return 0; } @@ -219,13 +219,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { // Should be fully available, because read_available >= ipc_header_size ssize_t received = recv(client_fd, buf, ipc_header_size, 0); if (received == -1) { - sway_log_errno(L_INFO, "Unable to receive header from IPC client"); + wlr_log_errno(L_INFO, "Unable to receive header from IPC client"); ipc_client_disconnect(client); return 0; } if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { - sway_log(L_DEBUG, "IPC header check failed"); + wlr_log(L_DEBUG, "IPC header check failed"); ipc_client_disconnect(client); return 0; } @@ -244,13 +244,13 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; if (mask & WL_EVENT_ERROR) { - sway_log(L_ERROR, "IPC Client socket error, removing client"); + wlr_log(L_ERROR, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } if (mask & WL_EVENT_HANGUP) { - sway_log(L_DEBUG, "Client %d hung up", client->fd); + wlr_log(L_DEBUG, "Client %d hung up", client->fd); ipc_client_disconnect(client); return 0; } @@ -259,14 +259,14 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { return 0; } - sway_log(L_DEBUG, "Client %d writable", client->fd); + wlr_log(L_DEBUG, "Client %d writable", client->fd); ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); if (written == -1 && errno == EAGAIN) { return 0; } else if (written == -1) { - sway_log_errno(L_INFO, "Unable to send data from queue to IPC client"); + wlr_log_errno(L_INFO, "Unable to send data from queue to IPC client"); ipc_client_disconnect(client); return 0; } @@ -291,7 +291,7 @@ void ipc_client_disconnect(struct ipc_client *client) { shutdown(client->fd, SHUT_RDWR); } - sway_log(L_INFO, "IPC Client %d disconnected", client->fd); + wlr_log(L_INFO, "IPC Client %d disconnected", client->fd); wl_event_source_remove(client->event_source); if (client->writable_event_source) { wl_event_source_remove(client->writable_event_source); @@ -313,7 +313,7 @@ void ipc_client_handle_command(struct ipc_client *client) { char *buf = malloc(client->payload_length + 1); if (!buf) { - sway_log_errno(L_INFO, "Unable to allocate IPC payload"); + wlr_log_errno(L_INFO, "Unable to allocate IPC payload"); ipc_client_disconnect(client); return; } @@ -322,7 +322,7 @@ void ipc_client_handle_command(struct ipc_client *client) { ssize_t received = recv(client->fd, buf, client->payload_length, 0); if (received == -1) { - sway_log_errno(L_INFO, "Unable to receive payload from IPC client"); + wlr_log_errno(L_INFO, "Unable to receive payload from IPC client"); ipc_client_disconnect(client); free(buf); return; @@ -393,12 +393,12 @@ void ipc_client_handle_command(struct ipc_client *client) { } default: - sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); + wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command); goto exit_cleanup; } ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); - sway_log(L_DEBUG, "Denied IPC client access to %i", client->current_command); + wlr_log(L_DEBUG, "Denied IPC client access to %i", client->current_command); exit_cleanup: client->payload_length = 0; @@ -422,14 +422,14 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay } if (client->write_buffer_size > 4e6) { // 4 MB - sway_log(L_ERROR, "Client write buffer too big, disconnecting client"); + wlr_log(L_ERROR, "Client write buffer too big, disconnecting client"); ipc_client_disconnect(client); return false; } char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); if (!new_buffer) { - sway_log(L_ERROR, "Unable to reallocate ipc client write buffer"); + wlr_log(L_ERROR, "Unable to reallocate ipc client write buffer"); ipc_client_disconnect(client); return false; } @@ -446,6 +446,6 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay ipc_client_handle_writable, client); } - sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); + wlr_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); return true; } diff --git a/sway/tree/container.c b/sway/tree/container.c index c5574275b..31ec2ce50 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -92,11 +92,11 @@ swayc_t *new_output(struct sway_output *sway_output) { if (strcasecmp(name, cur->name) == 0 || strcasecmp(identifier, cur->name) == 0) { - sway_log(L_DEBUG, "Matched output config for %s", name); + wlr_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); + wlr_log(L_DEBUG, "Matched wildcard output config for %s", name); all = cur; } @@ -126,7 +126,7 @@ swayc_t *new_output(struct sway_output *sway_output) { // Create workspace char *ws_name = workspace_next_name(output->name); - sway_log(L_DEBUG, "Creating default workspace %s", ws_name); + wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); new_workspace(output, ws_name); free(ws_name); return output; @@ -136,7 +136,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { if (!sway_assert(output, "new_workspace called with null output")) { return NULL; } - sway_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); + wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); swayc_t *workspace = new_swayc(C_WORKSPACE); workspace->x = output->x; @@ -159,7 +159,7 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { } const char *title = sway_view->iface.get_prop(sway_view, VIEW_PROP_TITLE); swayc_t *swayc = new_swayc(C_VIEW); - sway_log(L_DEBUG, "Adding new view %p:%s to container %p %d", + wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d", swayc, title, sibling, sibling ? sibling->type : 0); // Setup values swayc->sway_view = sway_view; @@ -200,7 +200,7 @@ swayc_t *destroy_output(swayc_t *output) { } } - sway_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); + wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); free_swayc(output); return &root_container; @@ -210,7 +210,7 @@ swayc_t *destroy_view(swayc_t *view) { if (!sway_assert(view, "null view passed to destroy_view")) { return NULL; } - sway_log(L_DEBUG, "Destroying view '%s'", view->name); + wlr_log(L_DEBUG, "Destroying view '%s'", view->name); swayc_t *parent = view->parent; free_swayc(view); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 4bcf0e2fd..13b8a3951 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -59,7 +59,7 @@ void init_layout(void) { } void add_child(swayc_t *parent, swayc_t *child) { - sway_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", + 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); list_add(parent->children, child); @@ -145,7 +145,7 @@ void arrange_windows(swayc_t *container, double width, double height) { width = floor(width); height = floor(height); - sway_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, + wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, container->name, container->width, container->height, container->x, container->y); @@ -155,7 +155,7 @@ void arrange_windows(swayc_t *container, double width, double height) { // TODO: wlr_output_layout probably for (i = 0; i < container->children->length; ++i) { swayc_t *output = container->children->items[i]; - sway_log(L_DEBUG, "Arranging output '%s' at %f,%f", + wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); arrange_windows(output, -1, -1); } @@ -181,7 +181,7 @@ void arrange_windows(swayc_t *container, double width, double height) { container->height = output->height; container->x = x; container->y = y; - sway_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", + wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", container->name, container->x, container->y); } // children are properly handled below @@ -192,7 +192,7 @@ void arrange_windows(swayc_t *container, double width, double height) { container->height = height; container->sway_view->iface.set_size(container->sway_view, container->width, container->height); - sway_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", + wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", container->width, container->height, container->x, container->y); } @@ -215,7 +215,7 @@ void arrange_windows(swayc_t *container, double width, double height) { container->children->length); break; default: - sway_log(L_DEBUG, "TODO: arrange layout type %d", container->layout); + wlr_log(L_DEBUG, "TODO: arrange layout type %d", container->layout); apply_horiz_layout(container, x, y, width, height, 0, container->children->length); break; @@ -244,10 +244,10 @@ static void apply_horiz_layout(swayc_t *container, // Resize windows double child_x = x; if (scale > 0.1) { - sway_log(L_DEBUG, "Arranging %p horizontally", container); + wlr_log(L_DEBUG, "Arranging %p horizontally", container); for (int i = start; i < end; ++i) { swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, + wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); child->sway_view->iface.set_position(child->sway_view, child_x, y); @@ -294,10 +294,10 @@ void apply_vert_layout(swayc_t *container, // Resize double child_y = y; if (scale > 0.1) { - sway_log(L_DEBUG, "Arranging %p vertically", container); + wlr_log(L_DEBUG, "Arranging %p vertically", container); for (i = start; i < end; ++i) { swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, + wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); child->sway_view->iface.set_position(child->sway_view, x, child_y); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index e8ed4102c..c37a873cc 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -11,7 +11,7 @@ void next_name_map(swayc_t *ws, void *data) { } char *workspace_next_name(const char *output_name) { - sway_log(L_DEBUG, "Workspace: Generating new workspace name for output %s", + wlr_log(L_DEBUG, "Workspace: Generating new workspace name for output %s", output_name); int count = 0; next_name_map(&root_container, &count); From 51f6718581ab7e21fd7a8d50450586f3969781ab Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 5 Jan 2018 23:09:26 +0100 Subject: [PATCH 152/522] swaymsg: convert to wlr_log --- swaymsg/main.c | 2 +- swaymsg/meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index a34eced4e..88b14813e 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -232,7 +232,7 @@ int main(int argc, char **argv) { char *socket_path = NULL; char *cmdtype = NULL; - init_log(L_INFO); + wlr_log_init(L_INFO, NULL); static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, diff --git a/swaymsg/meson.build b/swaymsg/meson.build index 2d678878f..8638b838d 100644 --- a/swaymsg/meson.build +++ b/swaymsg/meson.build @@ -2,7 +2,7 @@ executable( 'swaymsg', 'main.c', include_directories: [sway_inc], - dependencies: [jsonc], + dependencies: [jsonc, wlroots], link_with: [lib_sway_common], install: true ) From d4ddfec32e15fd1f47568f1b82eacc27cda5266a Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 5 Jan 2018 23:36:32 +0100 Subject: [PATCH 153/522] common/log: finish removing most log functions Keep sway_abort and sway_assert and convert them to use wlr_log functions --- common/log.c | 149 ++------------------------------------------------ include/log.h | 8 +-- 2 files changed, 8 insertions(+), 149 deletions(-) diff --git a/common/log.c b/common/log.c index c47b4eeae..2cc7289c5 100644 --- a/common/log.c +++ b/common/log.c @@ -1,167 +1,26 @@ -#define _POSIX_C_SOURCE 199506L -#include -#include #include #include -#include #include -#include -#include -#include #include "log.h" -#include "readline.h" - -static int colored = 1; -static log_importance_t loglevel_default = L_ERROR; -static log_importance_t v = L_SILENT; - -static const char *verbosity_colors[] = { - [L_SILENT] = "", - [L_ERROR ] = "\x1B[1;31m", - [L_INFO ] = "\x1B[1;34m", - [L_DEBUG ] = "\x1B[1;30m", -}; -static const char verbosity_chars[] = { - [L_SILENT] = '\0', - [L_ERROR ] = 'E', - [L_INFO ] = 'I', - [L_DEBUG ] = 'D', -}; - -void init_log(log_importance_t verbosity) { - if (verbosity != L_DEBUG) { - // command "debuglog" needs to know the user specified log level when - // turning off debug logging. - loglevel_default = verbosity; - } - v = verbosity; -} - -void set_log_level(log_importance_t verbosity) { - v = verbosity; -} - -log_importance_t get_log_level(void) { - return v; -} - -void reset_log_level(void) { - v = loglevel_default; -} - -bool toggle_debug_logging(void) { - v = (v == L_DEBUG) ? loglevel_default : L_DEBUG; - return (v == L_DEBUG); -} - -void sway_log_colors(int mode) { - colored = (mode == 1) ? 1 : 0; -} - -void _sway_vlog(const char *filename, int line, log_importance_t verbosity, - const char *format, va_list args) { - if (verbosity <= v) { - // prefix the time to the log message - static struct tm result; - static time_t t; - static struct tm *tm_info; - char buffer[26]; - - unsigned int c = verbosity; - if (c > sizeof(verbosity_colors) / sizeof(char *) - 1) { - c = sizeof(verbosity_colors) / sizeof(char *) - 1; - } - - // First, if not printing color, show the log level - if (!(colored && isatty(STDERR_FILENO)) && c != L_SILENT) { - fprintf(stderr, "%c: ", verbosity_chars[c]); - } - - // get current time - t = time(NULL); - // convert time to local time (determined by the locale) - tm_info = localtime_r(&t, &result); - // generate time prefix - strftime(buffer, sizeof(buffer), "%x %X - ", tm_info); - fprintf(stderr, "%s", buffer); - - if (colored && isatty(STDERR_FILENO)) { - fprintf(stderr, "%s", verbosity_colors[c]); - } - - if (filename && line) { - const char *file = filename + strlen(filename); - while (file != filename && *file != '/') { - --file; - } - if (*file == '/') { - ++file; - } - fprintf(stderr, "[%s:%d] ", file, line); - } - - vfprintf(stderr, format, args); - - if (colored && isatty(STDERR_FILENO)) { - fprintf(stderr, "\x1B[0m"); - } - fprintf(stderr, "\n"); - } -} - -void _sway_log(const char *filename, int line, log_importance_t verbosity, const char* format, ...) { - va_list args; - va_start(args, format); - _sway_vlog(filename, line, verbosity, format, args); - va_end(args); -} void sway_terminate(int code); -void _sway_abort(const char *filename, int line, const char* format, ...) { +void _sway_abort(const char *format, ...) { va_list args; va_start(args, format); - _sway_vlog(filename, line, L_ERROR, format, args); + _wlr_vlog(L_ERROR, format, args); va_end(args); sway_terminate(EXIT_FAILURE); } -void sway_log_errno(log_importance_t verbosity, char* format, ...) { - if (verbosity <= v) { - unsigned int c = verbosity; - if (c > sizeof(verbosity_colors) / sizeof(char *) - 1) { - c = sizeof(verbosity_colors) / sizeof(char *) - 1; - } - - if (colored && isatty(STDERR_FILENO)) { - fprintf(stderr, "%s", verbosity_colors[c]); - } else if (c != L_SILENT) { - fprintf(stderr, "%c: ", verbosity_chars[c]); - } - - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - - fprintf(stderr, ": "); - fprintf(stderr, "%s", strerror(errno)); - - if (colored && isatty(STDERR_FILENO)) { - fprintf(stderr, "\x1B[0m"); - } - fprintf(stderr, "\n"); - } -} - -bool _sway_assert(bool condition, const char *filename, int line, const char* format, ...) { +bool _sway_assert(bool condition, const char *format, ...) { if (condition) { return true; } va_list args; va_start(args, format); - _sway_vlog(filename, line, L_ERROR, format, args); + _wlr_vlog(L_ERROR, format, args); va_end(args); #ifndef NDEBUG diff --git a/include/log.h b/include/log.h index 646776f57..350a59ef3 100644 --- a/include/log.h +++ b/include/log.h @@ -3,13 +3,13 @@ #include #include -void _sway_abort(const char *filename, int line, const char* format, ...) __attribute__((format(printf,3,4))); +void _sway_abort(const char *filename, ...) ATTRIB_PRINTF(1, 2); #define sway_abort(FMT, ...) \ - _sway_abort(__FILE__, __LINE__, FMT, ##__VA_ARGS__) + _sway_abort("[%s:%d] " FMT, _strip_path(__FILE__), __LINE__, ##__VA_ARGS__) -bool _sway_assert(bool condition, const char *filename, int line, const char* format, ...) __attribute__((format(printf,4,5))); +bool _sway_assert(bool condition, const char* format, ...) ATTRIB_PRINTF(2, 3); #define sway_assert(COND, FMT, ...) \ - _sway_assert(COND, __FILE__, __LINE__, "%s:" FMT, __PRETTY_FUNCTION__, ##__VA_ARGS__) + _sway_assert(COND, "[%s:%d] %s:" FMT, _strip_path(__FILE__), __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) void error_handler(int sig); From 4c8c9b29e43668e9076234a7e221b3746012669f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 14 Jan 2018 10:35:56 -0500 Subject: [PATCH 154/522] render xdg surface --- sway/desktop/output.c | 187 +++++++++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 66 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2b428c30b..1e9a823ae 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -15,76 +16,131 @@ #include "sway/input/input-manager.h" #include "sway/input/seat.h" +/** + * Rotate a child's position relative to a parent. The parent size is (pw, ph), + * the child position is (*sx, *sy) and its size is (sw, sh). + */ +static void rotate_child_position(double *sx, double *sy, double sw, double sh, + double pw, double ph, float rotation) { + if (rotation != 0.0) { + // Coordinates relative to the center of the subsurface + double ox = *sx - pw/2 + sw/2, + oy = *sy - ph/2 + sh/2; + // Rotated coordinates + double rx = cos(-rotation)*ox - sin(-rotation)*oy, + ry = cos(-rotation)*oy + sin(-rotation)*ox; + *sx = rx + pw/2 - sw/2; + *sy = ry + ph/2 - sh/2; + } +} + +static void render_surface(struct wlr_surface *surface, + struct wlr_output *wlr_output, struct timespec *when, + double lx, double ly, float rotation) { + if (!wlr_surface_has_buffer(surface)) { + return; + } + struct wlr_output_layout *layout = root_container.sway_root->output_layout; + int width = surface->current->width; + int height = surface->current->height; + int render_width = width * wlr_output->scale; + int render_height = height * wlr_output->scale; + double ox = lx, oy = ly; + wlr_output_layout_output_coords(layout, wlr_output, &ox, &oy); + ox *= wlr_output->scale; + oy *= wlr_output->scale; + + struct wlr_box render_box = { + .x = lx, .y = ly, + .width = render_width, .height = render_height, + }; + if (wlr_output_layout_intersects(layout, wlr_output, &render_box)) { + float matrix[16]; + + float translate_center[16]; + wlr_matrix_translate(&translate_center, + (int)ox + render_width / 2, (int)oy + render_height / 2, 0); + + float rotate[16]; + wlr_matrix_rotate(&rotate, rotation); + + float translate_origin[16]; + wlr_matrix_translate(&translate_origin, -render_width / 2, + -render_height / 2, 0); + + float scale[16]; + wlr_matrix_scale(&scale, render_width, render_height, 1); + + float transform[16]; + wlr_matrix_mul(&translate_center, &rotate, &transform); + wlr_matrix_mul(&transform, &translate_origin, &transform); + wlr_matrix_mul(&transform, &scale, &transform); + + if (surface->current->transform != WL_OUTPUT_TRANSFORM_NORMAL) { + float surface_translate_center[16]; + wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0); + + float surface_transform[16]; + wlr_matrix_transform(surface_transform, + wlr_output_transform_invert(surface->current->transform)); + + float surface_translate_origin[16]; + wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0); + + wlr_matrix_mul(&transform, &surface_translate_center, + &transform); + wlr_matrix_mul(&transform, &surface_transform, &transform); + wlr_matrix_mul(&transform, &surface_translate_origin, + &transform); + } + + wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix); + + wlr_render_with_matrix(server.renderer, surface->texture, + &matrix); + + wlr_surface_send_frame_done(surface, when); + } + + struct wlr_subsurface *subsurface; + wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { + struct wlr_surface_state *state = subsurface->surface->current; + double sx = state->subsurface_position.x; + double sy = state->subsurface_position.y; + double sw = state->buffer_width / state->scale; + double sh = state->buffer_height / state->scale; + rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); + + render_surface(subsurface->surface, wlr_output, when, + lx + sx, + ly + sy, + rotation); + } +} + static void output_frame_view(swayc_t *view, void *data) { struct sway_output *output = data; struct wlr_output *wlr_output = output->wlr_output; struct sway_view *sway_view = view->sway_view; struct wlr_surface *surface = sway_view->surface; - if (!wlr_surface_has_buffer(surface)) { - return; + + switch (sway_view->type) { + case SWAY_XDG_SHELL_V6_VIEW: { + int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x; + int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y; + render_surface(surface, wlr_output, &output->last_frame, + view->x - window_offset_x, + view->y - window_offset_y, + 0); + break; } - // TODO - // - Deal with wlr_output_layout - int width = sway_view->surface->current->width; - int height = sway_view->surface->current->height; - int render_width = width * wlr_output->scale; - int render_height = height * wlr_output->scale; - double ox = view->x, oy = view->y; - // TODO - //wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); - ox *= wlr_output->scale; - oy *= wlr_output->scale; - // TODO - //if (wlr_output_layout_intersects(desktop->layout, wlr_output, - // lx, ly, lx + render_width, ly + render_height)) { - // return; - //} - - // if the shell specifies window geometry, make the top left corner of the - // window in the top left corner of the container to avoid arbitrarily - // sized gaps based on the attached buffer size - int window_offset_x = 0; - int window_offset_y = 0; - - if (view->sway_view->type == SWAY_XDG_SHELL_V6_VIEW) { - window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x; - window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y; + case SWAY_WL_SHELL_VIEW: + break; + case SWAY_XWAYLAND_VIEW: + break; + case SWAY_VIEW_TYPES: + break; } - - // TODO - double rotation = 0; - float matrix[16]; - - float translate_origin[16]; - wlr_matrix_translate(&translate_origin, - (int)ox + render_width / 2 - window_offset_x, - (int)oy + render_height / 2 - window_offset_y, - 0); - - float rotate[16]; - wlr_matrix_rotate(&rotate, rotation); - - float translate_center[16]; - wlr_matrix_translate(&translate_center, - -render_width / 2, - -render_height / 2, 0); - - float scale[16]; - wlr_matrix_scale(&scale, render_width, render_height, 1); - - float transform[16]; - wlr_matrix_mul(&translate_origin, &rotate, &transform); - wlr_matrix_mul(&transform, &translate_center, &transform); - wlr_matrix_mul(&transform, &scale, &transform); - wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix); - - wlr_render_with_matrix(output->server->renderer, surface->texture, &matrix); - - // TODO: move into wlroots - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - wlr_surface_send_frame_done(surface, &now); } static void output_frame_notify(struct wl_listener *listener, void *data) { @@ -92,9 +148,6 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; struct sway_server *server = soutput->server; - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - wlr_output_make_current(wlr_output); wlr_renderer_begin(server->renderer, wlr_output); @@ -104,6 +157,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { wlr_renderer_end(server->renderer); wlr_output_swap_buffers(wlr_output); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); soutput->last_frame = now; } From 76ce62919830b2917c696f599e7710ce05d109c0 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 14 Jan 2018 10:47:19 -0500 Subject: [PATCH 155/522] xdg-popups --- sway/desktop/output.c | 31 +++++++++++++++++++++++++++++++ sway/tree/container.c | 15 ++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 1e9a823ae..9182f8d57 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -118,6 +118,33 @@ static void render_surface(struct wlr_surface *surface, } } +static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, + struct wlr_output *wlr_output, struct timespec *when, double base_x, + double base_y, float rotation) { + double width = surface->surface->current->width; + double height = surface->surface->current->height; + + struct wlr_xdg_surface_v6 *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + if (!popup->configured) { + continue; + } + + double popup_width = popup->surface->current->width; + double popup_height = popup->surface->current->height; + + double popup_sx, popup_sy; + wlr_xdg_surface_v6_popup_get_position(popup, &popup_sx, &popup_sy); + rotate_child_position(&popup_sx, &popup_sy, popup_width, popup_height, + width, height, rotation); + + render_surface(popup->surface, wlr_output, when, + base_x + popup_sx, base_y + popup_sy, rotation); + render_xdg_v6_popups(popup, wlr_output, when, + base_x + popup_sx, base_y + popup_sy, rotation); + } +} + static void output_frame_view(swayc_t *view, void *data) { struct sway_output *output = data; struct wlr_output *wlr_output = output->wlr_output; @@ -132,6 +159,10 @@ static void output_frame_view(swayc_t *view, void *data) { view->x - window_offset_x, view->y - window_offset_y, 0); + render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, + &output->last_frame, + view->x - window_offset_x, view->y - window_offset_y, + 0); break; } case SWAY_WL_SHELL_VIEW: diff --git a/sway/tree/container.c b/sway/tree/container.c index 31ec2ce50..82f68519a 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -259,7 +259,6 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, int width = swayc->sway_view->surface->current->width; int height = swayc->sway_view->surface->current->height; - // TODO popups and subsurfaces switch (sview->type) { case SWAY_WL_SHELL_VIEW: break; @@ -268,6 +267,20 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, // coordinate of the top left corner of the window geometry view_sx += sview->wlr_xdg_surface_v6->geometry->x; view_sy += sview->wlr_xdg_surface_v6->geometry->y; + + // check for popups + double popup_sx, popup_sy; + struct wlr_xdg_surface_v6 *popup = + wlr_xdg_surface_v6_popup_at(sview->wlr_xdg_surface_v6, + view_sx, view_sy, &popup_sx, &popup_sy); + + if (popup) { + *sx = view_sx - popup_sx; + *sy = view_sy - popup_sy; + *surface = popup->surface; + list_free(queue); + return swayc; + } break; case SWAY_XWAYLAND_VIEW: break; From 619254db76e5a0c87750f075afccb608b32f9c48 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 14 Jan 2018 10:50:20 -0500 Subject: [PATCH 156/522] subsurface input --- sway/tree/container.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index 82f68519a..862406cf6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -288,6 +288,19 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, break; } + // check for subsurfaces + double sub_x, sub_y; + struct wlr_subsurface *subsurface = + wlr_surface_subsurface_at(sview->surface, + view_sx, view_sy, &sub_x, &sub_y); + if (subsurface) { + *sx = view_sx - sub_x; + *sy = view_sy - sub_y; + *surface = subsurface->surface; + list_free(queue); + return swayc; + } + if (view_sx > 0 && view_sx < width && view_sy > 0 && view_sy < height && pixman_region32_contains_point( From 2ce1d8d6cd0ae1520ea191678e3c39d555c66b58 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 14 Jan 2018 11:47:48 -0500 Subject: [PATCH 157/522] render wl-shell and xwayland views --- sway/desktop/output.c | 35 ++++++++++++++++++++++++++++++++++- sway/desktop/wl_shell.c | 6 ++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9182f8d57..ec204c6f4 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include "log.h" @@ -145,6 +146,34 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, } } +static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, + struct wlr_output *wlr_output, struct timespec *when, + double lx, double ly, float rotation, + bool is_child) { + if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) { + render_surface(surface->surface, wlr_output, when, + lx, ly, rotation); + + double width = surface->surface->current->width; + double height = surface->surface->current->height; + + struct wlr_wl_shell_surface *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + double popup_width = popup->surface->current->width; + double popup_height = popup->surface->current->height; + + double popup_x = popup->transient_state->x; + double popup_y = popup->transient_state->y; + rotate_child_position(&popup_x, &popup_y, popup_width, popup_height, + width, height, rotation); + + render_wl_shell_surface(popup, wlr_output, when, + lx + popup_x, ly + popup_y, rotation, true); + } + } +} + + static void output_frame_view(swayc_t *view, void *data) { struct sway_output *output = data; struct wlr_output *wlr_output = output->wlr_output; @@ -166,10 +195,14 @@ static void output_frame_view(swayc_t *view, void *data) { break; } case SWAY_WL_SHELL_VIEW: + render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, + &output->last_frame, view->x, view->y, 0, false); break; case SWAY_XWAYLAND_VIEW: + render_surface(surface, wlr_output, &output->last_frame, view->x, + view->y, 0); break; - case SWAY_VIEW_TYPES: + default: break; } } diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 345a1398c..e34f51608 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -77,11 +77,13 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { listener, server, wl_shell_surface); struct wlr_wl_shell_surface *shell_surface = data; - if (shell_surface->state != WLR_WL_SHELL_SURFACE_STATE_TOPLEVEL) { - // TODO: transient and popups should be floating + if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { + // popups don't get views return; } + // TODO make transient windows floating + wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", shell_surface->title, shell_surface->class); wlr_wl_shell_surface_ping(shell_surface); From 83ddd2d9dbee1b77993f5cc45427854e18aae6f1 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 14 Jan 2018 13:19:21 -0500 Subject: [PATCH 158/522] render override redirect --- include/sway/layout.h | 2 ++ include/sway/view.h | 5 ++++ sway/desktop/output.c | 13 +++++++++ sway/desktop/xwayland.c | 61 +++++++++++++++++++++++++++++++++-------- sway/input/cursor.c | 25 +++++++++++++++++ sway/tree/container.c | 2 +- sway/tree/layout.c | 1 + 7 files changed, 97 insertions(+), 12 deletions(-) diff --git a/include/sway/layout.h b/include/sway/layout.h index bfd96a026..af5614531 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h @@ -9,6 +9,8 @@ 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 }; void init_layout(void); diff --git a/include/sway/view.h b/include/sway/view.h index 900bd296f..08c5480b6 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -28,6 +28,8 @@ struct sway_xwayland_surface { 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; @@ -91,6 +93,9 @@ struct sway_view { double ox, double oy); void (*set_activated)(struct sway_view *view, bool activated); } iface; + + // only used for unmanaged views (shell specific) + struct wl_list unmanaged_view_link; // sway_root::unmanaged views }; #endif diff --git a/sway/desktop/output.c b/sway/desktop/output.c index ec204c6f4..21c8513f3 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -218,6 +218,19 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { swayc_descendants_of_type( &root_container, C_VIEW, output_frame_view, soutput); + // render unmanaged views on top + struct sway_view *view; + wl_list_for_each(view, &root_container.sway_root->unmanaged_views, + unmanaged_view_link) { + if (view->type == SWAY_XWAYLAND_VIEW) { + // the only kind of unamanged view right now is xwayland override redirect + int view_x = view->wlr_xwayland_surface->x; + int view_y = view->wlr_xwayland_surface->y; + render_surface(view->surface, wlr_output, &soutput->last_frame, + view_x, view_y, 0); + } + } + wlr_renderer_end(server->renderer); wlr_output_swap_buffers(wlr_output); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 43bb2e006..0c0dbfff5 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -93,13 +93,43 @@ static void handle_commit(struct wl_listener *listener, void *data) { static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, destroy); + struct wlr_xwayland_surface *xsurface = data; wl_list_remove(&sway_surface->commit.link); wl_list_remove(&sway_surface->destroy.link); wl_list_remove(&sway_surface->request_configure.link); - swayc_t *parent = destroy_view(sway_surface->view->swayc); + if (xsurface->override_redirect) { + if (xsurface->mapped) { + wl_list_remove(&sway_surface->view->unmanaged_view_link); + } + } else { + swayc_t *parent = destroy_view(sway_surface->view->swayc); + arrange_windows(parent, -1, -1); + } free(sway_surface->view); free(sway_surface); - arrange_windows(parent, -1, -1); +} + +static void handle_unmap_notify(struct wl_listener *listener, void *data) { + // TODO take the view out of the tree + struct sway_xwayland_surface *sway_surface = + wl_container_of(listener, sway_surface, unmap_notify); + struct wlr_xwayland_surface *xsurface = data; + if (xsurface->override_redirect) { + wl_list_remove(&sway_surface->view->unmanaged_view_link); + } + sway_surface->view->surface = NULL; +} + +static void handle_map_notify(struct wl_listener *listener, void *data) { + // TODO put the view back into the tree + struct sway_xwayland_surface *sway_surface = + wl_container_of(listener, sway_surface, map_notify); + struct wlr_xwayland_surface *xsurface = data; + if (xsurface->override_redirect) { + wl_list_insert(&root_container.sway_root->unmanaged_views, + &sway_surface->view->unmanaged_view_link); + } + sway_surface->view->surface = xsurface->surface; } static void handle_configure_request(struct wl_listener *listener, void *data) { @@ -119,11 +149,6 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { listener, server, xwayland_surface); struct wlr_xwayland_surface *xsurface = data; - if (xsurface->override_redirect) { - // TODO: floating popups - return; - } - wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", xsurface->title, xsurface->class); @@ -155,15 +180,29 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { // - Set new view to maximized so it behaves nicely // - Criteria - sway_surface->commit.notify = handle_commit; wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); - sway_surface->destroy.notify = handle_destroy; + sway_surface->commit.notify = handle_commit; + wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); - sway_surface->request_configure.notify = handle_configure_request; + sway_surface->destroy.notify = handle_destroy; + wl_signal_add(&xsurface->events.request_configure, &sway_surface->request_configure); + sway_surface->request_configure.notify = handle_configure_request; + + wl_signal_add(&xsurface->events.unmap_notify, &sway_surface->unmap_notify); + sway_surface->unmap_notify.notify = handle_unmap_notify; + + wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify); + sway_surface->map_notify.notify = handle_map_notify; + + if (xsurface->override_redirect) { + // these don't get a container in the tree + wl_list_insert(&root_container.sway_root->unmanaged_views, + &sway_view->unmanaged_view_link); + return; + } - // TODO: actual focus semantics swayc_t *parent = root_container.children->items[0]; parent = parent->children->items[0]; // workspace diff --git a/sway/input/cursor.c b/sway/input/cursor.c index c51b59f99..e6a4eca8a 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -24,6 +24,31 @@ 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; + + // check for unmanaged views first + struct sway_view *view; + wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views, + unmanaged_view_link) { + if (view->type == SWAY_XWAYLAND_VIEW) { + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; + struct wlr_box box = { + .x = xsurface->x, + .y = xsurface->y, + .width = xsurface->width, + .height = xsurface->height, + }; + + if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { + surface = xsurface->surface; + sx = cursor->x - box.x; + sy = cursor->y - box.y; + wlr_seat_pointer_notify_enter(seat, surface, sx, sy); + wlr_seat_pointer_notify_motion(seat, time, sx, sy); + return; + } + } + } + swayc_t *swayc = swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); if (swayc) { diff --git a/sway/tree/container.c b/sway/tree/container.c index 862406cf6..d241f69a4 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -207,7 +207,7 @@ swayc_t *destroy_output(swayc_t *output) { } swayc_t *destroy_view(swayc_t *view) { - if (!sway_assert(view, "null view passed to destroy_view")) { + if (!view) { return NULL; } wlr_log(L_DEBUG, "Destroying view '%s'", view->name); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 13b8a3951..01535f2de 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -51,6 +51,7 @@ void init_layout(void) { root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); root_container.sway_root->output_layout = wlr_output_layout_create(); + wl_list_init(&root_container.sway_root->unmanaged_views); root_container.sway_root->output_layout_change.notify = output_layout_change_notify; From ddc49ede4636b01dad8d8bfb7d0314bf1eb88258 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 15 Jan 2018 09:38:05 -0500 Subject: [PATCH 159/522] xwm handle map and unmap --- sway/desktop/output.c | 4 ++++ sway/desktop/xwayland.c | 36 +++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 21c8513f3..0f00222b3 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -180,6 +180,10 @@ static void output_frame_view(swayc_t *view, void *data) { struct sway_view *sway_view = view->sway_view; struct wlr_surface *surface = sway_view->surface; + if (!surface) { + return; + } + switch (sway_view->type) { case SWAY_XDG_SHELL_V6_VIEW: { int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 0c0dbfff5..a4d9687d4 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -101,22 +101,32 @@ static void handle_destroy(struct wl_listener *listener, void *data) { if (xsurface->mapped) { wl_list_remove(&sway_surface->view->unmanaged_view_link); } - } else { - swayc_t *parent = destroy_view(sway_surface->view->swayc); + } + + swayc_t *parent = destroy_view(sway_surface->view->swayc); + if (parent) { arrange_windows(parent, -1, -1); } + free(sway_surface->view); free(sway_surface); } static void handle_unmap_notify(struct wl_listener *listener, void *data) { - // TODO take the view out of the tree struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, unmap_notify); struct wlr_xwayland_surface *xsurface = data; if (xsurface->override_redirect) { wl_list_remove(&sway_surface->view->unmanaged_view_link); } + + // take it out of the tree + swayc_t *parent = destroy_view(sway_surface->view->swayc); + if (parent) { + arrange_windows(parent, -1, -1); + } + + sway_surface->view->swayc = NULL; sway_surface->view->surface = NULL; } @@ -125,11 +135,26 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, map_notify); struct wlr_xwayland_surface *xsurface = data; + + sway_surface->view->surface = xsurface->surface; + + // put it back into the tree if (xsurface->override_redirect) { wl_list_insert(&root_container.sway_root->unmanaged_views, &sway_surface->view->unmanaged_view_link); + } else { + struct sway_view *view = sway_surface->view; + destroy_view(view->swayc); + + swayc_t *parent = root_container.children->items[0]; + parent = parent->children->items[0]; // workspace + + swayc_t *cont = new_view(parent, view); + view->swayc = cont; + + arrange_windows(cont->parent, -1, -1); + sway_input_manager_set_focus(input_manager, cont); } - sway_surface->view->surface = xsurface->surface; } static void handle_configure_request(struct wl_listener *listener, void *data) { @@ -169,13 +194,10 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { sway_view->iface.set_activated = set_activated; sway_view->wlr_xwayland_surface = xsurface; sway_view->sway_xwayland_surface = sway_surface; - // TODO remove from the tree when the surface goes away (unmapped) sway_view->surface = xsurface->surface; sway_surface->view = sway_view; // TODO: - // - Wire up listeners - // - Handle popups // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria From 9f54cd89359119897fed2747c373879c09ae8706 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 17 Jan 2018 09:49:02 -0500 Subject: [PATCH 160/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 0a9c45958..967d37563 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 5ec45b172..cbd9a8b29 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 961813029..c4f6211da 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 03cc6d4ea..bd8b45c87 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 26cf5035d..bfe9d9c40 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 268486ab3..d134bc68e 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); } } From 2bf76509f8fab86c166a35689223d9eeab0f654f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 17 Jan 2018 11:47:27 -0500 Subject: [PATCH 161/522] update for new wlr-keyboard modifiers --- sway/input/keyboard.c | 2 +- sway/input/seat.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index e7539c48b..5827a1cac 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -401,7 +401,7 @@ static void handle_keyboard_modifiers(struct wl_listener *listener, struct wlr_input_device *wlr_device = keyboard->seat_device->input_device->wlr_device; wlr_seat_set_keyboard(wlr_seat, wlr_device); - wlr_seat_keyboard_notify_modifiers(wlr_seat); + wlr_seat_keyboard_notify_modifiers(wlr_seat, &wlr_device->keyboard->modifiers); } struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, diff --git a/sway/input/seat.c b/sway/input/seat.c index 268486ab3..d24a6c7ac 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -67,13 +67,16 @@ static void seat_configure_keyboard(struct sway_seat *seat, if (!seat_device->keyboard) { sway_keyboard_create(seat, seat_device); } + struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard; sway_keyboard_configure(seat_device->keyboard); wlr_seat_set_keyboard(seat->wlr_seat, seat_device->input_device->wlr_device); if (seat->focus) { // force notify reenter to pick up the new configuration wlr_seat_keyboard_clear_focus(seat->wlr_seat); - wlr_seat_keyboard_notify_enter(seat->wlr_seat, seat->focus->sway_view->surface); + wlr_seat_keyboard_notify_enter(seat->wlr_seat, + seat->focus->sway_view->surface, wlr_keyboard->keycodes, + wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); } } @@ -214,7 +217,16 @@ 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->wlr_seat, view->surface); + + 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); + } else { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, + NULL, 0, NULL); + } } seat->focus = container; From 9e0595f26bcca2a4d0aa735c4cd9fc4f792918bf Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 20 Jan 2018 11:32:07 -0500 Subject: [PATCH 162/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 0a9c45958..1ab96b519 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 53064eed2..8388f930a 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 1005cf686..fd2e15141 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 5ea39f626..5de65621b 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 f72b7d482..37d6e1338 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 22eb15f71..8f1f0aa7c 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 1783978a0..8273a7d48 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 8108a1100..995a2f47e 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 a1bfbacd3..2217f5cec 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 35740df34..94b8e03ee 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 7bc08ae6a..a551fd51e 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 a7dcdc2c1..c4e19b78b 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 d2261a630..171063aa0 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 035262cf8..0a1c57ac5 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 ecab9a5b9..e7f030581 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 25db1a331..867e65d3a 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 819b796bf..e8c8e04eb 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 ff5f83ecd..e9ddd6e31 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 aafe00037..926d0ac15 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 89a61fdce..0e3ffd41e 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 5ec45b172..543576254 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); From cc3c713889e529c74888d9cd89af7039bfbae20c Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 20 Jan 2018 11:44:34 -0500 Subject: [PATCH 163/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 1ab96b519..27fae0c6f 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 8388f930a..58a93fe31 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 fd2e15141..414ef8098 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 5de65621b..fa9cf05a6 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 6284002bf..450796163 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 80ec63ced..3e771c000 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 7c129aae4..56feaab58 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 543576254..2683d6bce 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; From c353e01c85049cfbc09510657e453b6aa5fd9c2d Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 20 Jan 2018 14:10:11 -0500 Subject: [PATCH 164/522] 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 diff --git a/include/sway/config.h b/include/sway/config.h index 27fae0c6f..be29082e7 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 58a93fe31..2bf297ce9 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 08c5480b6..240ffaa5b 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 414ef8098..28943963e 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 000000000..4bbf94e51 --- /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 e34f51608..0cde6583d 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 df48345c7..4b50093f4 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 a4d9687d4..7603d3ca9 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 26cf5035d..7b19991b6 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 5827a1cac..6dc57d461 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 30ec166bd..d5dead42c 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', From 6a1d71b8b8f33bdea3fb41bcd0de9439c0452682 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 20 Jan 2018 16:21:45 -0500 Subject: [PATCH 165/522] 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 diff --git a/include/sway/config.h b/include/sway/config.h index be29082e7..d07a71df7 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 9a5e312b7..a99e26945 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 000000000..c5ed9857e --- /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 28943963e..c1e25c5ff 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 4bbf94e51..f0e3722a3 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 000000000..c15f63541 --- /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 d5dead42c..46d79d44b 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 d241f69a4..e224539f4 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); + } +} From 1156523ccf8b45102333cca7d80b3451930b48e8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 21 Jan 2018 08:46:31 -0500 Subject: [PATCH 166/522] run all commands with focused container context --- sway/commands.c | 30 +++++++++++++++++++----------- sway/commands/kill.c | 28 ++++++++++------------------ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index c1e25c5ff..3ab5add6e 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -11,6 +11,7 @@ #include "sway/criteria.h" #include "sway/security.h" #include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "stringop.h" #include "log.h" @@ -271,19 +272,26 @@ struct cmd_results *handle_command(char *_exec) { } 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; + // without criteria, the command acts upon the focused + // container + struct sway_seat *seat = config->handler_context.seat; + if (!seat) { + seat = sway_input_manager_get_default_seat(input_manager); + } + if (seat) { + config->handler_context.current_container = seat->focus; + 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); } - 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); diff --git a/sway/commands/kill.c b/sway/commands/kill.c index f0e3722a3..a04c21f36 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -1,29 +1,21 @@ +#include #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); + if (!config->handler_context.current_container) { + wlr_log(L_ERROR, "cmd_kill called without container context"); + return cmd_results_new(CMD_INVALID, NULL, + "cmd_kill called without container context " + "(this is a bug in sway)"); } + // TODO close arbitrary containers without a view + struct sway_view *view = + config->handler_context.current_container->sway_view; - // 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 = 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) { + if (view && view->iface.close) { view->iface.close(view); } From 0e3eae4baa7717321ec87cf2c46f6798e89e3ded Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 21 Jan 2018 09:09:53 -0500 Subject: [PATCH 167/522] view interface --- include/sway/view.h | 16 +++++++++++++ sway/commands/kill.c | 4 ++-- sway/criteria.c | 22 ++++++++---------- sway/input/seat.c | 5 ++-- sway/meson.build | 1 + sway/tree/container.c | 2 +- sway/tree/layout.c | 8 +++---- sway/tree/view.c | 53 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 sway/tree/view.c diff --git a/include/sway/view.h b/include/sway/view.h index 240ffaa5b..ac33e11a5 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -99,4 +99,20 @@ struct sway_view { 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); + #endif diff --git a/sway/commands/kill.c b/sway/commands/kill.c index a04c21f36..62a3a5149 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -15,8 +15,8 @@ struct cmd_results *cmd_kill(int argc, char **argv) { struct sway_view *view = config->handler_context.current_container->sway_view; - if (view && view->iface.close) { - view->iface.close(view); + if (view) { + view_close(view); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/criteria.c b/sway/criteria.c index c15f63541..21278a94a 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -299,21 +299,17 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) { case CRIT_ID: // TODO break; case CRIT_APP_ID: - if (!view->iface.get_prop) { + { + const char *app_id = view_get_app_id(cont->sway_view); + if (!app_id) { + break; + } + + if (crit->regex && regex_cmp(app_id, crit->regex) == 0) { + matches++; + } 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 diff --git a/sway/input/seat.c b/sway/input/seat.c index d24a6c7ac..ae6dc7c4e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -214,7 +214,7 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { if (container) { struct sway_view *view = container->sway_view; - view->iface.set_activated(view, true); + view_set_activated(view, true); wl_signal_add(&container->events.destroy, &seat->focus_destroy); seat->focus_destroy.notify = handle_focus_destroy; @@ -234,8 +234,7 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { if (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); - + view_set_activated(view, false); } } diff --git a/sway/meson.build b/sway/meson.build index 46d79d44b..80ccc01d5 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -48,6 +48,7 @@ sway_sources = files( 'security.c', 'tree/container.c', 'tree/layout.c', + 'tree/view.c', 'tree/workspace.c', ) diff --git a/sway/tree/container.c b/sway/tree/container.c index e224539f4..b7b9bc682 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -157,7 +157,7 @@ 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 = sway_view->iface.get_prop(sway_view, VIEW_PROP_TITLE); + const char *title = view_get_title(sway_view); swayc_t *swayc = new_swayc(C_VIEW); wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d", swayc, title, sibling, sibling ? sibling->type : 0); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 01535f2de..41ff81b2f 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -191,8 +191,8 @@ void arrange_windows(swayc_t *container, double width, double height) { { container->width = width; container->height = height; - container->sway_view->iface.set_size(container->sway_view, - container->width, container->height); + view_set_size(container->sway_view, + container->width, container->height); wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", container->width, container->height, container->x, container->y); @@ -251,7 +251,7 @@ static void apply_horiz_layout(swayc_t *container, wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); - child->sway_view->iface.set_position(child->sway_view, child_x, y); + view_set_position(child->sway_view, child_x, y); if (i == end - 1) { double remaining_width = x + width - child_x; @@ -301,7 +301,7 @@ void apply_vert_layout(swayc_t *container, wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); - child->sway_view->iface.set_position(child->sway_view, x, child_y); + view_set_position(child->sway_view, x, child_y); if (i == end - 1) { double remaining_height = y + height - child_y; diff --git a/sway/tree/view.c b/sway/tree/view.c new file mode 100644 index 000000000..b46c3b172 --- /dev/null +++ b/sway/tree/view.c @@ -0,0 +1,53 @@ +#include "sway/view.h" + +const char *view_get_title(struct sway_view *view) { + if (view->iface.get_prop) { + return view->iface.get_prop(view, VIEW_PROP_TITLE); + } + return NULL; +} + +const char *view_get_app_id(struct sway_view *view) { + if (view->iface.get_prop) { + return view->iface.get_prop(view, VIEW_PROP_APP_ID); + } + return NULL; +} + +const char *view_get_class(struct sway_view *view) { + if (view->iface.get_prop) { + return view->iface.get_prop(view, VIEW_PROP_CLASS); + } + return NULL; +} + +const char *view_get_instance(struct sway_view *view) { + if (view->iface.get_prop) { + return view->iface.get_prop(view, VIEW_PROP_INSTANCE); + } + return NULL; +} + +void view_set_size(struct sway_view *view, int width, int height) { + if (view->iface.set_size) { + view->iface.set_size(view, width, height); + } +} + +void view_set_position(struct sway_view *view, double ox, double oy) { + if (view->iface.set_position) { + view->iface.set_position(view, ox, oy); + } +} + +void view_set_activated(struct sway_view *view, bool activated) { + if (view->iface.set_activated) { + view->iface.set_activated(view, activated); + } +} + +void view_close(struct sway_view *view) { + if (view->iface.close) { + view->iface.close(view); + } +} From 6b03b1205d39d23ea1dee3beb0b533ef5426031e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 21 Jan 2018 09:17:51 -0500 Subject: [PATCH 168/522] implement property criteria --- sway/criteria.c | 81 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/sway/criteria.c b/sway/criteria.c index 21278a94a..097336162 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -275,28 +275,39 @@ 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; + case CRIT_CLASS: + { + const char *class = view_get_class(cont->sway_view); + if (!class) { + break; + } + if (crit->regex && regex_cmp(class, crit->regex) == 0) { + matches++; + } + 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_CON_MARK: // TODO + case CRIT_FLOATING: + // TODO break; - case CRIT_FLOATING: // TODO - break; - case CRIT_ID: // TODO + case CRIT_ID: + // TODO break; case CRIT_APP_ID: { @@ -310,24 +321,44 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) { } break; } - case CRIT_INSTANCE: // TODO - break; - case CRIT_TILING: // TODO + case CRIT_INSTANCE: + { + const char *instance = view_get_instance(cont->sway_view); + if (!instance) { + break; + } + + if (crit->regex && regex_cmp(instance, crit->regex) == 0) { + matches++; + } + 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++; + { + const char *title = view_get_title(cont->sway_view); + if (!title) { + break; + } + + if (crit->regex && regex_cmp(title, crit->regex) == 0) { + matches++; + } + break; } - break; - case CRIT_URGENT: // "latest" or "oldest" + case CRIT_URGENT: + // TODO "latest" or "oldest" break; case CRIT_WINDOW_ROLE: + // TODO break; case CRIT_WINDOW_TYPE: + // TODO break; - case CRIT_WORKSPACE: // TODO + case CRIT_WORKSPACE: + // TODO break; default: sway_abort("Invalid criteria type (%i)", crit->type); From a6bc46eea9d7dec6a2b93f85bac2e3737e0c6725 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 21 Jan 2018 12:21:57 -0500 Subject: [PATCH 169/522] Remove sway/old/ --- sway/old/border.c | 510 ----- sway/old/commands.c | 686 ------- sway/old/commands/assign.c | 57 - sway/old/commands/bar.c | 59 - sway/old/commands/bar/activate_button.c | 26 - .../old/commands/bar/binding_mode_indicator.c | 27 - sway/old/commands/bar/bindsym.c | 48 - sway/old/commands/bar/colors.c | 129 -- sway/old/commands/bar/context_button.c | 26 - sway/old/commands/bar/font.c | 26 - sway/old/commands/bar/height.c | 21 - sway/old/commands/bar/hidden_state.c | 79 - sway/old/commands/bar/icon_theme.c | 25 - sway/old/commands/bar/id.c | 33 - sway/old/commands/bar/mode.c | 81 - sway/old/commands/bar/modifier.c | 35 - sway/old/commands/bar/output.c | 50 - sway/old/commands/bar/pango_markup.c | 27 - sway/old/commands/bar/position.c | 33 - sway/old/commands/bar/secondary_button.c | 26 - sway/old/commands/bar/separator_symbol.c | 21 - sway/old/commands/bar/status_command.c | 21 - .../commands/bar/strip_workspace_numbers.c | 27 - sway/old/commands/bar/swaybar_command.c | 21 - sway/old/commands/bar/tray_output.c | 29 - sway/old/commands/bar/tray_padding.c | 34 - sway/old/commands/bar/workspace_buttons.c | 27 - sway/old/commands/bar/wrap_scroll.c | 27 - sway/old/commands/bind.c | 170 -- sway/old/commands/border.c | 65 - sway/old/commands/client.c | 72 - sway/old/commands/clipboard.c | 38 - sway/old/commands/commands.c | 26 - sway/old/commands/debuglog.c | 27 - sway/old/commands/default_border.c | 44 - sway/old/commands/default_floating_border.c | 45 - sway/old/commands/exec.c | 16 - sway/old/commands/exec_always.c | 85 - sway/old/commands/exit.c | 17 - sway/old/commands/floating.c | 81 - sway/old/commands/floating_maximum_size.c | 38 - sway/old/commands/floating_minimum_size.c | 38 - sway/old/commands/floating_mod.c | 42 - sway/old/commands/floating_scroll.c | 46 - sway/old/commands/focus.c | 100 - sway/old/commands/focus_follows_mouse.c | 13 - sway/old/commands/font.c | 27 - sway/old/commands/for_window.c | 41 - sway/old/commands/force_focus_wrapping.c | 13 - sway/old/commands/fullscreen.c | 60 - sway/old/commands/gaps.c | 166 -- sway/old/commands/hide_edge_borders.c | 27 - sway/old/commands/include.c | 15 - sway/old/commands/input.c | 55 - sway/old/commands/input/accel_profile.c | 27 - sway/old/commands/input/click_method.c | 30 - sway/old/commands/input/drag_lock.c | 26 - sway/old/commands/input/dwt.c | 26 - sway/old/commands/input/events.c | 30 - sway/old/commands/input/left_handed.c | 26 - sway/old/commands/input/middle_emulation.c | 26 - sway/old/commands/input/natural_scroll.c | 26 - sway/old/commands/input/pointer_accel.c | 24 - sway/old/commands/input/scroll_method.c | 30 - sway/old/commands/input/tap.c | 29 - sway/old/commands/ipc.c | 162 -- sway/old/commands/kill.c | 12 - sway/old/commands/layout.c | 196 -- sway/old/commands/log_colors.c | 22 - sway/old/commands/mark.c | 87 - sway/old/commands/mode.c | 57 - sway/old/commands/mouse_warping.c | 17 - sway/old/commands/move.c | 189 -- sway/old/commands/new_float.c | 8 - sway/old/commands/new_window.c | 8 - sway/old/commands/no_focus.c | 41 - sway/old/commands/orientation.c | 21 - sway/old/commands/output.c | 219 -- sway/old/commands/permit.c | 108 - sway/old/commands/reload.c | 19 - sway/old/commands/resize.c | 375 ---- sway/old/commands/scratchpad.c | 72 - sway/old/commands/seamless_mouse.c | 13 - sway/old/commands/set.c | 61 - sway/old/commands/show_marks.c | 13 - sway/old/commands/smart_gaps.c | 20 - sway/old/commands/split.c | 98 - sway/old/commands/sticky.c | 25 - sway/old/commands/unmark.c | 31 - sway/old/commands/workspace.c | 92 - .../commands/workspace_auto_back_and_forth.c | 18 - sway/old/commands/workspace_layout.c | 40 - sway/old/config.c | 1313 ------------ sway/old/container.c | 1024 ---------- sway/old/criteria.c | 451 ----- sway/old/focus.c | 278 --- sway/old/handlers.c | 1143 ----------- sway/old/input_state.c | 490 ----- sway/old/ipc-json.c | 521 ----- sway/old/ipc-server.c | 840 -------- sway/old/layout.c | 1773 ----------------- sway/old/output.c | 278 --- sway/old/security.c | 228 --- sway/old/workspace.c | 373 ---- 104 files changed, 14614 deletions(-) delete mode 100644 sway/old/border.c delete mode 100644 sway/old/commands.c delete mode 100644 sway/old/commands/assign.c delete mode 100644 sway/old/commands/bar.c delete mode 100644 sway/old/commands/bar/activate_button.c delete mode 100644 sway/old/commands/bar/binding_mode_indicator.c delete mode 100644 sway/old/commands/bar/bindsym.c delete mode 100644 sway/old/commands/bar/colors.c delete mode 100644 sway/old/commands/bar/context_button.c delete mode 100644 sway/old/commands/bar/font.c delete mode 100644 sway/old/commands/bar/height.c delete mode 100644 sway/old/commands/bar/hidden_state.c delete mode 100644 sway/old/commands/bar/icon_theme.c delete mode 100644 sway/old/commands/bar/id.c delete mode 100644 sway/old/commands/bar/mode.c delete mode 100644 sway/old/commands/bar/modifier.c delete mode 100644 sway/old/commands/bar/output.c delete mode 100644 sway/old/commands/bar/pango_markup.c delete mode 100644 sway/old/commands/bar/position.c delete mode 100644 sway/old/commands/bar/secondary_button.c delete mode 100644 sway/old/commands/bar/separator_symbol.c delete mode 100644 sway/old/commands/bar/status_command.c delete mode 100644 sway/old/commands/bar/strip_workspace_numbers.c delete mode 100644 sway/old/commands/bar/swaybar_command.c delete mode 100644 sway/old/commands/bar/tray_output.c delete mode 100644 sway/old/commands/bar/tray_padding.c delete mode 100644 sway/old/commands/bar/workspace_buttons.c delete mode 100644 sway/old/commands/bar/wrap_scroll.c delete mode 100644 sway/old/commands/bind.c delete mode 100644 sway/old/commands/border.c delete mode 100644 sway/old/commands/client.c delete mode 100644 sway/old/commands/clipboard.c delete mode 100644 sway/old/commands/commands.c delete mode 100644 sway/old/commands/debuglog.c delete mode 100644 sway/old/commands/default_border.c delete mode 100644 sway/old/commands/default_floating_border.c delete mode 100644 sway/old/commands/exec.c delete mode 100644 sway/old/commands/exec_always.c delete mode 100644 sway/old/commands/exit.c delete mode 100644 sway/old/commands/floating.c delete mode 100644 sway/old/commands/floating_maximum_size.c delete mode 100644 sway/old/commands/floating_minimum_size.c delete mode 100644 sway/old/commands/floating_mod.c delete mode 100644 sway/old/commands/floating_scroll.c delete mode 100644 sway/old/commands/focus.c delete mode 100644 sway/old/commands/focus_follows_mouse.c delete mode 100644 sway/old/commands/font.c delete mode 100644 sway/old/commands/for_window.c delete mode 100644 sway/old/commands/force_focus_wrapping.c delete mode 100644 sway/old/commands/fullscreen.c delete mode 100644 sway/old/commands/gaps.c delete mode 100644 sway/old/commands/hide_edge_borders.c delete mode 100644 sway/old/commands/include.c delete mode 100644 sway/old/commands/input.c delete mode 100644 sway/old/commands/input/accel_profile.c delete mode 100644 sway/old/commands/input/click_method.c delete mode 100644 sway/old/commands/input/drag_lock.c delete mode 100644 sway/old/commands/input/dwt.c delete mode 100644 sway/old/commands/input/events.c delete mode 100644 sway/old/commands/input/left_handed.c delete mode 100644 sway/old/commands/input/middle_emulation.c delete mode 100644 sway/old/commands/input/natural_scroll.c delete mode 100644 sway/old/commands/input/pointer_accel.c delete mode 100644 sway/old/commands/input/scroll_method.c delete mode 100644 sway/old/commands/input/tap.c delete mode 100644 sway/old/commands/ipc.c delete mode 100644 sway/old/commands/kill.c delete mode 100644 sway/old/commands/layout.c delete mode 100644 sway/old/commands/log_colors.c delete mode 100644 sway/old/commands/mark.c delete mode 100644 sway/old/commands/mode.c delete mode 100644 sway/old/commands/mouse_warping.c delete mode 100644 sway/old/commands/move.c delete mode 100644 sway/old/commands/new_float.c delete mode 100644 sway/old/commands/new_window.c delete mode 100644 sway/old/commands/no_focus.c delete mode 100644 sway/old/commands/orientation.c delete mode 100644 sway/old/commands/output.c delete mode 100644 sway/old/commands/permit.c delete mode 100644 sway/old/commands/reload.c delete mode 100644 sway/old/commands/resize.c delete mode 100644 sway/old/commands/scratchpad.c delete mode 100644 sway/old/commands/seamless_mouse.c delete mode 100644 sway/old/commands/set.c delete mode 100644 sway/old/commands/show_marks.c delete mode 100644 sway/old/commands/smart_gaps.c delete mode 100644 sway/old/commands/split.c delete mode 100644 sway/old/commands/sticky.c delete mode 100644 sway/old/commands/unmark.c delete mode 100644 sway/old/commands/workspace.c delete mode 100644 sway/old/commands/workspace_auto_back_and_forth.c delete mode 100644 sway/old/commands/workspace_layout.c delete mode 100644 sway/old/config.c delete mode 100644 sway/old/container.c delete mode 100644 sway/old/criteria.c delete mode 100644 sway/old/focus.c delete mode 100644 sway/old/handlers.c delete mode 100644 sway/old/input_state.c delete mode 100644 sway/old/ipc-json.c delete mode 100644 sway/old/ipc-server.c delete mode 100644 sway/old/layout.c delete mode 100644 sway/old/output.c delete mode 100644 sway/old/security.c delete mode 100644 sway/old/workspace.c diff --git a/sway/old/border.c b/sway/old/border.c deleted file mode 100644 index df0022ce2..000000000 --- a/sway/old/border.c +++ /dev/null @@ -1,510 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include -#include -#include -#include "sway/border.h" -#include "sway/container.h" -#include "sway/config.h" -#include "client/pango.h" - -void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { - color = htonl(color); - - cairo_set_source_rgba(cairo, - (color >> (2*8) & 0xFF) / 255.0, - (color >> (1*8) & 0xFF) / 255.0, - (color >> (0*8) & 0xFF) / 255.0, - (color >> (3*8) & 0xFF) / 255.0); -} - -void border_clear(struct border *border) { - if (border && border->buffer) { - free(border->buffer); - border->buffer = NULL; - } -} - -static cairo_t *create_border_buffer(swayc_t *view, struct wlc_geometry g, cairo_surface_t **surface) { - if (view->border == NULL) { - view->border = malloc(sizeof(struct border)); - if (!view->border) { - sway_log(L_ERROR, "Unable to allocate window border information"); - return NULL; - } - } - cairo_t *cr; - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, g.size.w); - view->border->buffer = calloc(stride * g.size.h, sizeof(unsigned char)); - view->border->geometry = g; - if (!view->border->buffer) { - sway_log(L_ERROR, "Unable to allocate window border buffer"); - return NULL; - } - *surface = cairo_image_surface_create_for_data(view->border->buffer, - CAIRO_FORMAT_ARGB32, g.size.w, g.size.h, stride); - if (cairo_surface_status(*surface) != CAIRO_STATUS_SUCCESS) { - border_clear(view->border); - sway_log(L_ERROR, "Unable to allocate window border surface"); - return NULL; - } - cr = cairo_create(*surface); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) { - cairo_surface_destroy(*surface); - border_clear(view->border); - sway_log(L_ERROR, "Unable to create cairo context"); - return NULL; - } - return cr; -} - -// TODO: move to client/cairo.h when local set_source_u32 is fixed. -/** - * 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); - } -} - -int get_font_text_height(const char *font) { - cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 200, 200); - cairo_t *cr = cairo_create(surface); - int width, height; - get_text_size(cr, font, &width, &height, 1, false, "Gg"); - cairo_surface_destroy(surface); - cairo_destroy(cr); - return height; -} - -static void render_borders(swayc_t *view, cairo_t *cr, struct border_colors *colors, bool top) { - struct wlc_geometry *g = &view->border->geometry; - struct wlc_geometry *b = &view->border_geometry; - struct wlc_geometry *v = &view->actual_geometry; - enum swayc_layouts layout = view->parent->layout; - uint32_t color; - - int x = b->origin.x - g->origin.x; - int y = b->origin.y - g->origin.y; - - // draw vertical/horizontal indicator if container is the only child of its parent container - bool is_only_child = view->parent && view->parent->children && view->parent->children->length == 1; - - // left border - int left_border = v->origin.x - b->origin.x; - if (left_border > 0) { - render_sharp_line(cr, - colors->child_border, - x, y, - left_border, - b->size.h); - } - - // right border - int right_border = b->size.w - v->size.w - left_border; - if (right_border > 0) { - if (is_only_child && layout == L_HORIZ && !view->is_floating) { - color = colors->indicator; - } else { - color = colors->child_border; - } - render_sharp_line(cr, - color, - x + b->size.w - right_border, - y, - right_border, - b->size.h); - } - - // top border - int top_border = v->origin.y - b->origin.y; - if (top && top_border > 0) { - render_sharp_line(cr, - colors->child_border, - x, y, - b->size.w, - top_border); - } - - // bottom border - int bottom_border = b->size.h - (top_border + v->size.h); - if (bottom_border > 0) { - if (is_only_child && layout == L_VERT && !view->is_floating) { - color = colors->indicator; - } else { - color = colors->child_border; - } - render_sharp_line(cr, - color, - x, - y + b->size.h - bottom_border, - b->size.w, - bottom_border); - } -} - -static void render_title_bar(swayc_t *view, cairo_t *cr, struct wlc_geometry *b, struct border_colors *colors) { - struct wlc_geometry *tb = &view->title_bar_geometry; - int x = MIN(tb->origin.x, tb->origin.x - b->origin.x); - int y = MIN(tb->origin.y, tb->origin.y - b->origin.y); - - // title bar background - cairo_set_source_u32(cr, colors->background); - cairo_rectangle(cr, x, y, tb->size.w, tb->size.h); - cairo_fill(cr); - - // header top line - render_sharp_line(cr, colors->border, x, y, tb->size.w, 1); - - // text - if (view->name) { - int width, height; - get_text_size(cr, config->font, &width, &height, 1, false, "%s", view->name); - cairo_move_to(cr, x + 2, y + 2); - cairo_set_source_u32(cr, colors->text); - pango_printf(cr, config->font, 1, false, "%s", view->name); - } - // Marks - if (config->show_marks && view->marks) { - int total_len = 0; - - for(int i = view->marks->length - 1; i >= 0; --i) { - char *mark = (char *)view->marks->items[i]; - if (*mark != '_') { - int width, height; - get_text_size(cr, config->font, &width, &height, 1, false, "[%s]", mark); - total_len += width; - if ((int)tb->size.w + x - (total_len + 2) < x + 2) { - break; - } else { - cairo_move_to(cr, (int)tb->size.w + x - (total_len + 2), y + 2); - cairo_set_source_u32(cr, colors->text); - pango_printf(cr, config->font, 1, false, "[%s]", mark); - } - } - } - } - - // titlebars has a border all around for tabbed layouts - if (view->parent->layout == L_TABBED) { - // header bottom line - render_sharp_line(cr, colors->border, x, y + tb->size.h - 1, - tb->size.w, 1); - - // left border - render_sharp_line(cr, colors->border, x, y, 1, tb->size.h); - - // right border - render_sharp_line(cr, colors->border, x + tb->size.w - 1, y, - 1, tb->size.h); - - return; - } - - if ((uint32_t)(view->actual_geometry.origin.y - tb->origin.y) == tb->size.h) { - // header bottom line - render_sharp_line(cr, colors->border, - x + view->actual_geometry.origin.x - tb->origin.x, - y + tb->size.h - 1, - view->actual_geometry.size.w, 1); - } else { - // header bottom line - render_sharp_line(cr, colors->border, x, - y + tb->size.h - 1, - tb->size.w, 1); - } -} - -/** - * Generate nested container title for tabbed/stacked layouts - */ -static char *generate_container_title(swayc_t *container) { - char layout = 'H'; - char *name, *prev_name = NULL; - switch (container->layout) { - case L_TABBED: - layout = 'T'; - break; - case L_STACKED: - layout = 'S'; - break; - case L_VERT: - layout = 'V'; - break; - default: - layout = 'H'; - } - int len = 9; - name = malloc(len * sizeof(char)); - if (!name) { - sway_log(L_ERROR, "Unable to allocate container title"); - return NULL; - } - snprintf(name, len, "sway: %c[", layout); - - int i; - for (i = 0; i < container->children->length; ++i) { - prev_name = name; - swayc_t* child = container->children->items[i]; - const char *title = NULL; - if (child->type == C_VIEW) { - title = child->app_id ? child->app_id : - (child->instance ? child->instance : - (child->class ? child->class :"(null)")); - } else { //child->type == C_CONTAINER - title = generate_container_title(child); - } - - len = strlen(name) + strlen(title) + 1; - if (i < container->children->length-1) { - len++; - } - - name = malloc(len * sizeof(char)); - if (!name) { - free(prev_name); - sway_log(L_ERROR, "Unable to allocate container title"); - return NULL; - } - if (i < container->children->length-1) { - snprintf(name, len, "%s%s ", prev_name, title); - } else { - snprintf(name, len, "%s%s", prev_name, title); - } - free(prev_name); - } - - prev_name = name; - len = strlen(name) + 2; - name = malloc(len * sizeof(char)); - if (!name) { - free(prev_name); - sway_log(L_ERROR, "Unable to allocate container title"); - return NULL; - } - snprintf(name, len, "%s]", prev_name); - free(prev_name); - free(container->name); - container->name = name; - return container->name + 6; // don't include "sway: " -} - -void update_tabbed_stacked_titlebars(swayc_t *c, cairo_t *cr, struct wlc_geometry *g, swayc_t *focused, swayc_t *focused_inactive) { - if (c->type == C_CONTAINER) { - if (c->parent->focused == c) { - render_title_bar(c, cr, g, &config->border_colors.focused_inactive); - } else { - render_title_bar(c, cr, g, &config->border_colors.unfocused); - } - - if (!c->visible) { - return; - } - - int i; - for (i = 0; i < c->children->length; ++i) { - swayc_t *child = c->children->items[i]; - update_tabbed_stacked_titlebars(child, cr, g, focused, focused_inactive); - } - } else { - bool is_child_of_focused = swayc_is_child_of(c, get_focused_container(&root_container)); - - if (focused == c || is_child_of_focused) { - render_title_bar(c, cr, g, &config->border_colors.focused); - } else if (focused_inactive == c) { - render_title_bar(c, cr, g, &config->border_colors.focused_inactive); - } else { - render_title_bar(c, cr, g, &config->border_colors.unfocused); - } - } -} - -static void update_view_border(swayc_t *view) { - if (!view->visible) { - return; - } - - cairo_t *cr = NULL; - cairo_surface_t *surface = NULL; - - // clear previous border buffer. - border_clear(view->border); - - // get focused and focused_inactive views - swayc_t *focused = get_focused_view(&root_container); - swayc_t *container = swayc_parent_by_type(view, C_CONTAINER); - swayc_t *focused_inactive = NULL; - - bool is_child_of_focused = swayc_is_parent_of(get_focused_container(&root_container), view); - - if (container) { - focused_inactive = swayc_focus_by_type(container, C_VIEW); - } else { - container = swayc_parent_by_type(view, C_WORKSPACE); - if (container) { - focused_inactive = swayc_focus_by_type(container, C_VIEW); - } - } - - // for tabbed/stacked layouts the focused view has to draw all the - // titlebars of the hidden views. - swayc_t *p = NULL; - if (view->parent->focused == view && (p = swayc_tabbed_stacked_ancestor(view))) { - struct wlc_geometry g = { - .origin = { - .x = p->x, - .y = p->y - }, - .size = { - .w = p->width, - .h = p->height - } - }; - cr = create_border_buffer(view, g, &surface); - if (!cr) { - goto cleanup; - } - - bool render_top = !should_hide_top_border(view, view->y); - if (view == focused || is_child_of_focused) { - render_borders(view, cr, &config->border_colors.focused, render_top); - } else { - render_borders(view, cr, &config->border_colors.focused_inactive, render_top); - } - - // generate container titles - int i; - for (i = 0; i < p->children->length; ++i) { - swayc_t *child = p->children->items[i]; - if (child->type == C_CONTAINER) { - generate_container_title(child); - } - } - - update_tabbed_stacked_titlebars(p, cr, &g, focused, focused_inactive); - } else { - switch (view->border_type) { - case B_NONE: - break; - case B_PIXEL: - cr = create_border_buffer(view, view->border_geometry, &surface); - if (!cr) { - break; - } - - if (focused == view || is_child_of_focused) { - render_borders(view, cr, &config->border_colors.focused, true); - } else if (focused_inactive == view) { - render_borders(view, cr, &config->border_colors.focused_inactive, true); - } else { - render_borders(view, cr, &config->border_colors.unfocused, true); - } - - break; - case B_NORMAL: - cr = create_border_buffer(view, view->border_geometry, &surface); - if (!cr) { - break; - } - - if (focused == view || is_child_of_focused) { - render_borders(view, cr, &config->border_colors.focused, false); - render_title_bar(view, cr, &view->border_geometry, - &config->border_colors.focused); - } else if (focused_inactive == view) { - render_borders(view, cr, &config->border_colors.focused_inactive, false); - render_title_bar(view, cr, &view->border_geometry, - &config->border_colors.focused_inactive); - } else { - render_borders(view, cr, &config->border_colors.unfocused, false); - render_title_bar(view, cr, &view->border_geometry, - &config->border_colors.unfocused); - } - - break; - } - } - -cleanup: - - if (surface) { - cairo_surface_flush(surface); - cairo_surface_destroy(surface); - } - - if (cr) { - cairo_destroy(cr); - } -} - -void update_container_border(swayc_t *container) { - if (container->type == C_VIEW) { - update_view_border(container); - return; - } else { - for (int i = 0; i < container->children->length; ++i) { - update_container_border(container->children->items[i]); - } - } -} - -void render_view_borders(wlc_handle view) { - swayc_t *c = swayc_by_handle(view); - - - // emulate i3 behavior for drawing borders for tabbed and stacked layouts: - // if we are not the only child in the container, always draw borders, - // regardless of the border setting on the individual view - if (!c || (c->border_type == B_NONE - && !((c->parent->layout == L_TABBED || c->parent->layout == L_STACKED) - && c->parent->children->length > 1))) { - return; - } - - if (c->border && c->border->buffer) { - wlc_pixels_write(WLC_RGBA8888, &c->border->geometry, c->border->buffer); - } -} - -bool should_hide_top_border(swayc_t *con, double y) { - // returns true if container is child of tabbed/stacked layout and is - // sharing top border with tabbed titlebar - swayc_t *par = con->parent; - while (par->type != C_WORKSPACE) { - if (par->layout == L_TABBED || par->layout == L_STACKED) { - return con->y == y; - } - con = par; - par = par->parent; - } - return false; -} diff --git a/sway/old/commands.c b/sway/old/commands.c deleted file mode 100644 index e11818934..000000000 --- a/sway/old/commands.c +++ /dev/null @@ -1,686 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sway/layout.h" -#include "sway/focus.h" -#include "sway/workspace.h" -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/output.h" -#include "sway/handlers.h" -#include "sway/input_state.h" -#include "sway/criteria.h" -#include "sway/ipc-server.h" -#include "sway/security.h" -#include "sway/input.h" -#include "sway/border.h" -#include "stringop.h" -#include "sway.h" -#include "util.h" -#include "list.h" -#include "log.h" - -struct cmd_handler { - char *command; - sway_cmd *handle; -}; - -int sp_index = 0; - -swayc_t *current_container = NULL; - -// Returns error object, or NULL if check succeeds. -struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val) { - struct cmd_results *error = NULL; - switch (type) { - case EXPECTED_MORE_THAN: - if (argc > val) { - return NULL; - } - error = cmd_results_new(CMD_INVALID, name, "Invalid %s command " - "(expected more than %d argument%s, got %d)", - name, val, (char*[2]){"s", ""}[argc==1], argc); - break; - case EXPECTED_AT_LEAST: - if (argc >= val) { - return NULL; - } - error = cmd_results_new(CMD_INVALID, name, "Invalid %s command " - "(expected at least %d argument%s, got %d)", - name, val, (char*[2]){"s", ""}[argc==1], argc); - break; - case EXPECTED_LESS_THAN: - if (argc < val) { - return NULL; - }; - error = cmd_results_new(CMD_INVALID, name, "Invalid %s command " - "(expected less than %d argument%s, got %d)", - name, val, (char*[2]){"s", ""}[argc==1], argc); - break; - case EXPECTED_EQUAL_TO: - if (argc == val) { - return NULL; - }; - error = cmd_results_new(CMD_INVALID, name, "Invalid %s command " - "(expected %d arguments, got %d)", name, val, argc); - break; - } - return error; -} - -void hide_view_in_scratchpad(swayc_t *sp_view) { - if (sp_view == NULL) { - return; - } - - wlc_view_set_mask(sp_view->handle, 0); - sp_view->visible = false; - swayc_t *ws = sp_view->parent; - remove_child(sp_view); - if (swayc_active_workspace() != ws && ws->floating->length == 0 && ws->children->length == 0) { - destroy_workspace(ws); - } else { - arrange_windows(ws, -1, -1); - } - set_focused_container(container_under_pointer()); -} - -void input_cmd_apply(struct input_config *input) { - int i; - i = list_seq_find(config->input_configs, input_identifier_cmp, input->identifier); - if (i >= 0) { - // merge existing config - struct input_config *ic = config->input_configs->items[i]; - merge_input_config(ic, input); - free_input_config(input); - input = ic; - } else { - list_add(config->input_configs, input); - } - - current_input_config = input; - - if (input->identifier) { - // Try to find the input device and apply configuration now. If - // this is during startup then there will be no container and config - // will be applied during normal "new input" event from wlc. - /* 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; - } - } - */ - } -} - -void remove_view_from_scratchpad(swayc_t *view) { - int i; - for (i = 0; i < scratchpad->length; i++) { - if (scratchpad->items[i] == view) { - if (sp_index == 0) { - sp_index = scratchpad->length - 1; - } else { - sp_index--; - } - list_del(scratchpad, sp_index); - sp_view = NULL; - } - } -} - -/* Keep alphabetized */ -static struct cmd_handler handlers[] = { - { "assign", cmd_assign }, - { "bar", cmd_bar }, - { "bindcode", cmd_bindcode }, - { "bindsym", cmd_bindsym }, - { "border", cmd_border }, - { "client.background", cmd_client_background }, - { "client.focused", cmd_client_focused }, - { "client.focused_inactive", cmd_client_focused_inactive }, - { "client.placeholder", cmd_client_placeholder }, - { "client.unfocused", cmd_client_unfocused }, - { "client.urgent", cmd_client_urgent }, - { "clipboard", cmd_clipboard }, - { "commands", cmd_commands }, - { "debuglog", cmd_debuglog }, - { "default_border", cmd_default_border }, - { "default_floating_border", cmd_default_floating_border }, - { "default_orientation", cmd_orientation }, - { "exec", cmd_exec }, - { "exec_always", cmd_exec_always }, - { "exit", cmd_exit }, - { "floating", cmd_floating }, - { "floating_maximum_size", cmd_floating_maximum_size }, - { "floating_minimum_size", cmd_floating_minimum_size }, - { "floating_modifier", cmd_floating_mod }, - { "floating_scroll", cmd_floating_scroll }, - { "focus", cmd_focus }, - { "focus_follows_mouse", cmd_focus_follows_mouse }, - { "font", cmd_font }, - { "for_window", cmd_for_window }, - { "force_focus_wrapping", cmd_force_focus_wrapping }, - { "fullscreen", cmd_fullscreen }, - { "gaps", cmd_gaps }, - { "hide_edge_borders", cmd_hide_edge_borders }, - { "include", cmd_include }, - { "input", cmd_input }, - { "ipc", cmd_ipc }, - { "kill", cmd_kill }, - { "layout", cmd_layout }, - { "log_colors", cmd_log_colors }, - { "mark", cmd_mark }, - { "mode", cmd_mode }, - { "mouse_warping", cmd_mouse_warping }, - { "move", cmd_move }, - { "new_float", cmd_new_float }, - { "new_window", cmd_new_window }, - { "no_focus", cmd_no_focus }, - { "output", cmd_output }, - { "permit", cmd_permit }, - { "reject", cmd_reject }, - { "reload", cmd_reload }, - { "resize", cmd_resize }, - { "scratchpad", cmd_scratchpad }, - { "seamless_mouse", cmd_seamless_mouse }, - { "set", cmd_set }, - { "show_marks", cmd_show_marks }, - { "smart_gaps", cmd_smart_gaps }, - { "split", cmd_split }, - { "splith", cmd_splith }, - { "splitt", cmd_splitt }, - { "splitv", cmd_splitv }, - { "sticky", cmd_sticky }, - { "unmark", cmd_unmark }, - { "workspace", cmd_workspace }, - { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth }, - { "workspace_layout", cmd_workspace_layout }, -}; - -static struct cmd_handler bar_handlers[] = { - { "activate_button", bar_cmd_activate_button }, - { "binding_mode_indicator", bar_cmd_binding_mode_indicator }, - { "bindsym", bar_cmd_bindsym }, - { "colors", bar_cmd_colors }, - { "context_button", bar_cmd_context_button }, - { "font", bar_cmd_font }, - { "height", bar_cmd_height }, - { "hidden_state", bar_cmd_hidden_state }, - { "icon_theme", bar_cmd_icon_theme }, - { "id", bar_cmd_id }, - { "mode", bar_cmd_mode }, - { "modifier", bar_cmd_modifier }, - { "output", bar_cmd_output }, - { "pango_markup", bar_cmd_pango_markup }, - { "position", bar_cmd_position }, - { "secondary_button", bar_cmd_secondary_button }, - { "separator_symbol", bar_cmd_separator_symbol }, - { "status_command", bar_cmd_status_command }, - { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, - { "swaybar_command", bar_cmd_swaybar_command }, - { "tray_output", bar_cmd_tray_output }, - { "tray_padding", bar_cmd_tray_padding }, - { "workspace_buttons", bar_cmd_workspace_buttons }, - { "wrap_scroll", bar_cmd_wrap_scroll }, -}; - -/** - * Check and add color to buffer. - * - * return error object, or NULL if color is valid. - */ -struct cmd_results *add_color(const char *name, char *buffer, const char *color) { - int len = strlen(color); - if (len != 7 && len != 9) { - return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); - } - - if (color[0] != '#') { - return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); - } - - int i; - for (i = 1; i < len; ++i) { - if (!isxdigit(color[i])) { - return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); - } - } - - // copy color to buffer - strncpy(buffer, color, len); - // add default alpha channel if color was defined without it - if (len == 7) { - buffer[7] = 'f'; - buffer[8] = 'f'; - } - buffer[9] = '\0'; - - return NULL; -} - -static struct cmd_handler input_handlers[] = { - { "accel_profile", input_cmd_accel_profile }, - { "click_method", input_cmd_click_method }, - { "drag_lock", input_cmd_drag_lock }, - { "dwt", input_cmd_dwt }, - { "events", input_cmd_events }, - { "left_handed", input_cmd_left_handed }, - { "middle_emulation", input_cmd_middle_emulation }, - { "natural_scroll", input_cmd_natural_scroll }, - { "pointer_accel", input_cmd_pointer_accel }, - { "scroll_method", input_cmd_scroll_method }, - { "tap", input_cmd_tap }, -}; - -static struct cmd_handler bar_colors_handlers[] = { - { "active_workspace", bar_colors_cmd_active_workspace }, - { "background", bar_colors_cmd_background }, - { "binding_mode", bar_colors_cmd_binding_mode }, - { "focused_background", bar_colors_cmd_focused_background }, - { "focused_separator", bar_colors_cmd_focused_separator }, - { "focused_statusline", bar_colors_cmd_focused_statusline }, - { "focused_workspace", bar_colors_cmd_focused_workspace }, - { "inactive_workspace", bar_colors_cmd_inactive_workspace }, - { "separator", bar_colors_cmd_separator }, - { "statusline", bar_colors_cmd_statusline }, - { "urgent_workspace", bar_colors_cmd_urgent_workspace }, -}; - -static struct cmd_handler ipc_handlers[] = { - { "*", cmd_ipc_cmd }, - { "bar-config", cmd_ipc_cmd }, - { "command", cmd_ipc_cmd }, - { "events", cmd_ipc_events }, - { "inputs", cmd_ipc_cmd }, - { "marks", cmd_ipc_cmd }, - { "outputs", cmd_ipc_cmd }, - { "tree", cmd_ipc_cmd }, - { "workspaces", cmd_ipc_cmd }, -}; - -static struct cmd_handler ipc_event_handlers[] = { - { "*", cmd_ipc_event_cmd }, - { "binding", cmd_ipc_event_cmd }, - { "input", cmd_ipc_event_cmd }, - { "mode", cmd_ipc_event_cmd }, - { "output", cmd_ipc_event_cmd }, - { "window", cmd_ipc_event_cmd }, - { "workspace", cmd_ipc_event_cmd }, -}; - -static int handler_compare(const void *_a, const void *_b) { - const struct cmd_handler *a = _a; - const struct cmd_handler *b = _b; - return strcasecmp(a->command, b->command); -} - -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); - if (block == CMD_BLOCK_BAR) { - res = bsearch(&d, bar_handlers, - sizeof(bar_handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - } else if (block == CMD_BLOCK_BAR_COLORS){ - res = bsearch(&d, bar_colors_handlers, - sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - } else 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_IPC) { - res = bsearch(&d, ipc_handlers, - sizeof(ipc_handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - } else if (block == CMD_BLOCK_IPC_EVENTS) { - res = bsearch(&d, ipc_event_handlers, - sizeof(ipc_event_handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - } else { - res = bsearch(&d, handlers, - sizeof(handlers) / sizeof(struct cmd_handler), - sizeof(struct cmd_handler), handler_compare); - } - return res; -} - -struct cmd_results *handle_command(char *_exec, enum command_context context) { - // Even though this function will process multiple commands we will only - // return the last error, if any (for now). (Since we have access to an - // error string we could e.g. concatonate all errors there.) - struct cmd_results *results = NULL; - char *exec = strdup(_exec); - char *head = exec; - char *cmdlist; - char *cmd; - list_t *containers = NULL; - - head = exec; - do { - // Extract criteria (valid for this command list only). - if (*head == '[') { - ++head; - char *criteria_string = argsep(&head, "]"); - if (head) { - ++head; - list_t *tokens = create_list(); - char *error; - - if ((error = extract_crit_tokens(tokens, criteria_string))) { - 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); - do { - // Split commands - cmd = argsep(&cmdlist, ","); - cmd += strspn(cmd, whitespace); - if (strcmp(cmd, "") == 0) { - sway_log(L_INFO, "Ignoring empty command."); - continue; - } - sway_log(L_INFO, "Handling command '%s'", cmd); - //TODO better handling of argv - int argc; - char **argv = split_args(cmd, &argc); - if (strcmp(argv[0], "exec") != 0) { - int i; - for (i = 1; i < argc; ++i) { - if (*argv[i] == '\"' || *argv[i] == '\'') { - strip_quotes(argv[i]); - } - } - } - struct cmd_handler *handler = find_handler(argv[0], CMD_BLOCK_END); - if (!handler) { - if (results) { - free_cmd_results(results); - } - results = cmd_results_new(CMD_INVALID, cmd, "Unknown/invalid command"); - free_argv(argc, argv); - goto cleanup; - } - if (!(get_command_policy_mask(argv[0]) & context)) { - if (results) { - free_cmd_results(results); - } - results = cmd_results_new(CMD_INVALID, cmd, - "Permission denied for %s via %s", cmd, - command_policy_str(context)); - free_argv(argc, argv); - goto cleanup; - } - int i = 0; - do { - if (!containers) { - current_container = get_focused_container(&root_container); - } else if (containers->length == 0) { - if (results) { - free_cmd_results(results); - } - results = cmd_results_new(CMD_FAILURE, argv[0], "No matching container"); - goto cleanup; - } else { - current_container = (swayc_t *)containers->items[i]; - } - sway_log(L_INFO, "Running on container '%s'", current_container->name); - - 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); - ++i; - } while(containers && i < containers->length); - - free_argv(argc, argv); - } while(cmdlist); - - if (containers) { - list_free(containers); - containers = NULL; - } - } while(head); - cleanup: - free(exec); - if (containers) { - free(containers); - } - if (!results) { - results = cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - 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 - 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)); - if (!results) { - sway_log(L_ERROR, "Unable to allocate command results"); - return NULL; - } - results->status = status; - if (input) { - results->input = strdup(input); // input is the command name - } else { - results->input = NULL; - } - if (format) { - char *error = malloc(256); - va_list args; - va_start(args, format); - if (error) { - vsnprintf(error, 256, format, args); - } - va_end(args); - results->error = error; - } else { - results->error = NULL; - } - return results; -} - -void free_cmd_results(struct cmd_results *results) { - if (results->input) { - free(results->input); - } - if (results->error) { - free(results->error); - } - free(results); -} - -const char *cmd_results_to_json(struct cmd_results *results) { - json_object *result_array = json_object_new_array(); - json_object *root = json_object_new_object(); - json_object_object_add(root, "success", json_object_new_boolean(results->status == CMD_SUCCESS)); - if (results->input) { - json_object_object_add(root, "input", json_object_new_string(results->input)); - } - if (results->error) { - json_object_object_add(root, "error", json_object_new_string(results->error)); - } - json_object_array_add(result_array, root); - const char *json = json_object_to_json_string(result_array); - free(result_array); - free(root); - return json; -} diff --git a/sway/old/commands/assign.c b/sway/old/commands/assign.c deleted file mode 100644 index c3b03bbc4..000000000 --- a/sway/old/commands/assign.c +++ /dev/null @@ -1,57 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include "sway/commands.h" -#include "sway/criteria.h" -#include "list.h" -#include "log.h" - -struct cmd_results *cmd_assign(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "assign", EXPECTED_AT_LEAST, 2))) { - return error; - } - - char *criteria = *argv++; - - if (strncmp(*argv, "→", strlen("→")) == 0) { - if (argc < 3) { - return cmd_results_new(CMD_INVALID, "assign", "Missing workspace"); - } - argv++; - } - - char *movecmd = "move container to workspace "; - int arglen = strlen(movecmd) + strlen(*argv) + 1; - char *cmdlist = calloc(1, arglen); - if (!cmdlist) { - return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate command list"); - } - snprintf(cmdlist, arglen, "%s%s", movecmd, *argv); - - struct criteria *crit = malloc(sizeof(struct criteria)); - if (!crit) { - free(cmdlist); - return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate criteria"); - } - crit->crit_raw = strdup(criteria); - crit->cmdlist = cmdlist; - crit->tokens = create_list(); - char *err_str = extract_crit_tokens(crit->tokens, crit->crit_raw); - - if (err_str) { - error = cmd_results_new(CMD_INVALID, "assign", err_str); - free(err_str); - free_criteria(crit); - } else if (crit->tokens->length == 0) { - error = cmd_results_new(CMD_INVALID, "assign", "Found no name/value pairs in criteria"); - free_criteria(crit); - } else if (list_seq_find(config->criteria, criteria_cmp, crit) != -1) { - sway_log(L_DEBUG, "assign: Duplicate, skipping."); - free_criteria(crit); - } else { - sway_log(L_DEBUG, "assign: '%s' -> '%s' added", crit->crit_raw, crit->cmdlist); - list_add(config->criteria, crit); - } - return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar.c b/sway/old/commands/bar.c deleted file mode 100644 index 04745a6ef..000000000 --- a/sway/old/commands/bar.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "log.h" -#include "util.h" - -struct cmd_results *cmd_bar(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "bar", EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (config->reading && strcmp("{", argv[0]) != 0) { - return cmd_results_new(CMD_INVALID, "bar", - "Expected '{' at start of bar config definition."); - } - - if (!config->reading) { - if (argc > 1) { - if (strcasecmp("mode", argv[0]) == 0) { - return bar_cmd_mode(argc-1, argv + 1); - } - - if (strcasecmp("hidden_state", argv[0]) == 0) { - return bar_cmd_hidden_state(argc-1, argv + 1); - } - } - - return cmd_results_new(CMD_FAILURE, "bar", "Can only be used in config file."); - } - - // Create new bar with default values - struct bar_config *bar = default_bar_config(); - if (!bar) { - return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar state"); - } - - // set bar id - int i; - for (i = 0; i < config->bars->length; ++i) { - if (bar == config->bars->items[i]) { - const int len = 5 + numlen(i); // "bar-" + i + \0 - bar->id = malloc(len * sizeof(char)); - if (bar->id) { - snprintf(bar->id, len, "bar-%d", i); - } else { - return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar ID"); - } - break; - } - } - - // Set current bar - config->current_bar = bar; - sway_log(L_DEBUG, "Configuring bar %s", bar->id); - return cmd_results_new(CMD_BLOCK_BAR, NULL, NULL); -} diff --git a/sway/old/commands/bar/activate_button.c b/sway/old/commands/bar/activate_button.c deleted file mode 100644 index 32a1d3e51..000000000 --- a/sway/old/commands/bar/activate_button.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_activate_button(int argc, char **argv) { - const char *cmd_name = "activate_button"; -#ifndef ENABLE_TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " - "%s called, but sway was compiled without tray support", - cmd_name, cmd_name); -#else - struct cmd_results *error = NULL; - if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); - } - - // User should be able to prefix with 0x or whatever they want - config->current_bar->secondary_button = strtoul(argv[0], NULL, 0); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -#endif -} diff --git a/sway/old/commands/bar/binding_mode_indicator.c b/sway/old/commands/bar/binding_mode_indicator.c deleted file mode 100644 index 64f5b84f8..000000000 --- a/sway/old/commands/bar/binding_mode_indicator.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "binding_mode_indicator", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "binding_mode_indicator", "No bar defined."); - } - - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->binding_mode_indicator = true; - sway_log(L_DEBUG, "Enabling binding mode indicator on bar: %s", config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->binding_mode_indicator = false; - sway_log(L_DEBUG, "Disabling binding mode indicator on bar: %s", config->current_bar->id); - } else { - error = cmd_results_new(CMD_INVALID, "binding_mode_indicator", "Invalid value %s", argv[0]); - return error; - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/bindsym.c b/sway/old/commands/bar/bindsym.c deleted file mode 100644 index 5f90b51a8..000000000 --- a/sway/old/commands/bar/bindsym.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "list.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1))) { - return error; - } else if (!config->reading) { - return cmd_results_new(CMD_FAILURE, "bindsym", "Can only be used in config file."); - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "bindsym", "No bar defined."); - } - - if (strlen(argv[1]) != 7) { - return cmd_results_new(CMD_INVALID, "bindsym", "Invalid mouse binding %s", argv[1]); - } - uint32_t numbutton = (uint32_t)atoi(argv[1] + 6); - if (numbutton < 1 || numbutton > 5 || strncmp(argv[1], "button", 6) != 0) { - return cmd_results_new(CMD_INVALID, "bindsym", "Invalid mouse binding %s", argv[1]); - } - struct sway_mouse_binding *binding = malloc(sizeof(struct sway_mouse_binding)); - if (!binding) { - return cmd_results_new(CMD_FAILURE, "bindsym", "Unable to allocate binding"); - } - binding->button = numbutton; - binding->command = join_args(argv + 1, argc - 1); - - struct bar_config *bar = config->current_bar; - int i = list_seq_find(bar->bindings, sway_mouse_binding_cmp_buttons, binding); - if (i > -1) { - sway_log(L_DEBUG, "bindsym - '%s' for swaybar already exists, overwriting", argv[0]); - struct sway_mouse_binding *dup = bar->bindings->items[i]; - free_sway_mouse_binding(dup); - list_del(bar->bindings, i); - } - list_add(bar->bindings, binding); - list_qsort(bar->bindings, sway_mouse_binding_cmp_qsort); - - sway_log(L_DEBUG, "bindsym - Bound %s to command %s when clicking swaybar", argv[0], binding->command); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/colors.c b/sway/old/commands/bar/colors.c deleted file mode 100644 index 8b3b0aacb..000000000 --- a/sway/old/commands/bar/colors.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include "sway/commands.h" - -static struct cmd_results *parse_single_color(char **color, const char *cmd_name, int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!*color) { - *color = malloc(10); - if (!*color) { - return cmd_results_new(CMD_FAILURE, cmd_name, "Unable to allocate color"); - } - } - - error = add_color(cmd_name, *color, argv[0]); - if (error) { - return error; - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -static struct cmd_results *parse_three_colors(char ***colors, const char *cmd_name, int argc, char **argv) { - struct cmd_results *error = NULL; - if (argc != 3) { - return cmd_results_new(CMD_INVALID, cmd_name, "Requires exactly three color values"); - } - - int i; - for (i = 0; i < 3; i++) { - if (!*colors[i]) { - *(colors[i]) = malloc(10); - if (!*(colors[i])) { - return cmd_results_new(CMD_FAILURE, cmd_name, "Unable to allocate color"); - } - } - error = add_color(cmd_name, *(colors[i]), argv[i]); - if (error) { - return error; - } - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *bar_cmd_colors(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "colors", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (strcmp("{", argv[0]) != 0) { - return cmd_results_new(CMD_INVALID, "colors", - "Expected '{' at the start of colors config definition."); - } - - return cmd_results_new(CMD_BLOCK_BAR_COLORS, NULL, NULL); -} - -struct cmd_results *bar_colors_cmd_active_workspace(int argc, char **argv) { - char **colors[3] = { - &(config->current_bar->colors.active_workspace_border), - &(config->current_bar->colors.active_workspace_bg), - &(config->current_bar->colors.active_workspace_text) - }; - return parse_three_colors(colors, "active_workspace", argc, argv); -} - -struct cmd_results *bar_colors_cmd_background(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.background), "background", argc, argv); -} - -struct cmd_results *bar_colors_cmd_focused_background(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.focused_background), "focused_background", argc, argv); -} - -struct cmd_results *bar_colors_cmd_binding_mode(int argc, char **argv) { - char **colors[3] = { - &(config->current_bar->colors.binding_mode_border), - &(config->current_bar->colors.binding_mode_bg), - &(config->current_bar->colors.binding_mode_text) - }; - return parse_three_colors(colors, "binding_mode", argc, argv); -} - -struct cmd_results *bar_colors_cmd_focused_workspace(int argc, char **argv) { - char **colors[3] = { - &(config->current_bar->colors.focused_workspace_border), - &(config->current_bar->colors.focused_workspace_bg), - &(config->current_bar->colors.focused_workspace_text) - }; - return parse_three_colors(colors, "focused_workspace", argc, argv); -} - -struct cmd_results *bar_colors_cmd_inactive_workspace(int argc, char **argv) { - char **colors[3] = { - &(config->current_bar->colors.inactive_workspace_border), - &(config->current_bar->colors.inactive_workspace_bg), - &(config->current_bar->colors.inactive_workspace_text) - }; - return parse_three_colors(colors, "inactive_workspace", argc, argv); -} - -struct cmd_results *bar_colors_cmd_separator(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.separator), "separator", argc, argv); -} - -struct cmd_results *bar_colors_cmd_focused_separator(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.focused_separator), "focused_separator", argc, argv); -} - -struct cmd_results *bar_colors_cmd_statusline(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.statusline), "statusline", argc, argv); -} - -struct cmd_results *bar_colors_cmd_focused_statusline(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.focused_separator), "focused_separator", argc, argv); -} - -struct cmd_results *bar_colors_cmd_urgent_workspace(int argc, char **argv) { - char **colors[3] = { - &(config->current_bar->colors.urgent_workspace_border), - &(config->current_bar->colors.urgent_workspace_bg), - &(config->current_bar->colors.urgent_workspace_text) - }; - return parse_three_colors(colors, "urgent_workspace", argc, argv); -} diff --git a/sway/old/commands/bar/context_button.c b/sway/old/commands/bar/context_button.c deleted file mode 100644 index 6d7d7aecc..000000000 --- a/sway/old/commands/bar/context_button.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_context_button(int argc, char **argv) { - const char *cmd_name = "context_button"; -#ifndef ENABLE_TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " - "%s called, but sway was compiled without tray support", - cmd_name, cmd_name); -#else - struct cmd_results *error = NULL; - if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); - } - - // User should be able to prefix with 0x or whatever they want - config->current_bar->context_button = strtoul(argv[0], NULL, 0); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -#endif -} diff --git a/sway/old/commands/bar/font.c b/sway/old/commands/bar/font.c deleted file mode 100644 index c586c5bcc..000000000 --- a/sway/old/commands/bar/font.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include "sway/commands.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *bar_cmd_font(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "font", EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "font", "No bar defined."); - } - - char *font = join_args(argv, argc); - free(config->current_bar->font); - if (strlen(font) > 6 && strncmp("pango:", font, 6) == 0) { - config->current_bar->font = font; - } else { - config->current_bar->font = font; - } - - sway_log(L_DEBUG, "Settings font '%s' for bar: %s", config->current_bar->font, config->current_bar->id); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/height.c b/sway/old/commands/bar/height.c deleted file mode 100644 index eb576ab3d..000000000 --- a/sway/old/commands/bar/height.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_height(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "height", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - int height = atoi(argv[0]); - if (height < 0) { - return cmd_results_new(CMD_INVALID, "height", - "Invalid height value: %s", argv[0]); - } - - config->current_bar->height = height; - sway_log(L_DEBUG, "Setting bar height to %d on bar: %s", height, config->current_bar->id); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/hidden_state.c b/sway/old/commands/bar/hidden_state.c deleted file mode 100644 index 0b49aa6b6..000000000 --- a/sway/old/commands/bar/hidden_state.c +++ /dev/null @@ -1,79 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "sway/ipc-server.h" -#include "log.h" - -static struct cmd_results *bar_set_hidden_state(struct bar_config *bar, const char *hidden_state) { - char *old_state = bar->hidden_state; - if (strcasecmp("toggle", hidden_state) == 0 && !config->reading) { - if (strcasecmp("hide", bar->hidden_state) == 0) { - bar->hidden_state = strdup("show"); - } else if (strcasecmp("show", bar->hidden_state) == 0) { - bar->hidden_state = strdup("hide"); - } - } else if (strcasecmp("hide", hidden_state) == 0) { - bar->hidden_state = strdup("hide"); - } else if (strcasecmp("show", hidden_state) == 0) { - bar->hidden_state = strdup("show"); - } else { - return cmd_results_new(CMD_INVALID, "hidden_state", "Invalid value %s", hidden_state); - } - - if (strcmp(old_state, bar->hidden_state) != 0) { - if (!config->reading) { - ipc_event_barconfig_update(bar); - } - sway_log(L_DEBUG, "Setting hidden_state: '%s' for bar: %s", bar->hidden_state, bar->id); - } - - // free old mode - free(old_state); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "hidden_state", EXPECTED_AT_LEAST, 1))) { - return error; - } - if ((error = checkarg(argc, "hidden_state", EXPECTED_LESS_THAN, 3))) { - return error; - } - - if (config->reading && argc > 1) { - return cmd_results_new(CMD_INVALID, "hidden_state", "Unexpected value %s in config mode", argv[1]); - } - - const char *state = argv[0]; - - if (config->reading) { - return bar_set_hidden_state(config->current_bar, state); - } - - const char *id = NULL; - if (argc == 2) { - id = argv[1]; - } - - int i; - struct bar_config *bar; - for (i = 0; i < config->bars->length; ++i) { - bar = config->bars->items[i]; - if (id && strcmp(id, bar->id) == 0) { - return bar_set_hidden_state(bar, state); - } - - error = bar_set_hidden_state(bar, state); - if (error) { - return error; - } - } - - // active bar modifiers might have changed. - update_active_bar_modifiers(); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/icon_theme.c b/sway/old/commands/bar/icon_theme.c deleted file mode 100644 index cbfc0be50..000000000 --- a/sway/old/commands/bar/icon_theme.c +++ /dev/null @@ -1,25 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/commands.h" - -struct cmd_results *bar_cmd_icon_theme(int argc, char **argv) { - const char *cmd_name = "tray_output"; -#ifndef ENABLE_TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " - "%s called, but sway was compiled without tray support", - cmd_name, cmd_name); -#else - struct cmd_results *error = NULL; - if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); - } - - config->current_bar->icon_theme = strdup(argv[0]); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -#endif -} diff --git a/sway/old/commands/bar/id.c b/sway/old/commands/bar/id.c deleted file mode 100644 index 1221ebf65..000000000 --- a/sway/old/commands/bar/id.c +++ /dev/null @@ -1,33 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_id(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "id", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - const char *name = argv[0]; - const char *oldname = config->current_bar->id; - - // check if id is used by a previously defined bar - int i; - for (i = 0; i < config->bars->length; ++i) { - struct bar_config *find = config->bars->items[i]; - if (strcmp(name, find->id) == 0 && config->current_bar != find) { - return cmd_results_new(CMD_FAILURE, "id", - "Id '%s' already defined for another bar. Id unchanged (%s).", - name, oldname); - } - } - - sway_log(L_DEBUG, "Renaming bar: '%s' to '%s'", oldname, name); - - // free old bar id - free(config->current_bar->id); - - config->current_bar->id = strdup(name); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/mode.c b/sway/old/commands/bar/mode.c deleted file mode 100644 index 36816b939..000000000 --- a/sway/old/commands/bar/mode.c +++ /dev/null @@ -1,81 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "sway/ipc-server.h" -#include "log.h" - -static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode) { - char *old_mode = bar->mode; - if (strcasecmp("toggle", mode) == 0 && !config->reading) { - if (strcasecmp("dock", bar->mode) == 0) { - bar->mode = strdup("hide"); - } else if (strcasecmp("hide", bar->mode) == 0) { - bar->mode = strdup("dock"); - } - } else if (strcasecmp("dock", mode) == 0) { - bar->mode = strdup("dock"); - } else if (strcasecmp("hide", mode) == 0) { - bar->mode = strdup("hide"); - } else if (strcasecmp("invisible", mode) == 0) { - bar->mode = strdup("invisible"); - } else { - return cmd_results_new(CMD_INVALID, "mode", "Invalid value %s", mode); - } - - if (strcmp(old_mode, bar->mode) != 0) { - if (!config->reading) { - ipc_event_barconfig_update(bar); - - // active bar modifiers might have changed. - update_active_bar_modifiers(); - } - sway_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id); - } - - // free old mode - free(old_mode); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *bar_cmd_mode(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "mode", EXPECTED_AT_LEAST, 1))) { - return error; - } - if ((error = checkarg(argc, "mode", EXPECTED_LESS_THAN, 3))) { - return error; - } - - if (config->reading && argc > 1) { - return cmd_results_new(CMD_INVALID, "mode", "Unexpected value %s in config mode", argv[1]); - } - - const char *mode = argv[0]; - - if (config->reading) { - return bar_set_mode(config->current_bar, mode); - } - - const char *id = NULL; - if (argc == 2) { - id = argv[1]; - } - - int i; - struct bar_config *bar; - for (i = 0; i < config->bars->length; ++i) { - bar = config->bars->items[i]; - if (id && strcmp(id, bar->id) == 0) { - return bar_set_mode(bar, mode); - } - - error = bar_set_mode(bar, mode); - if (error) { - return error; - } - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/modifier.c b/sway/old/commands/bar/modifier.c deleted file mode 100644 index 153d87e6f..000000000 --- a/sway/old/commands/bar/modifier.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include "sway/commands.h" -#include "log.h" -#include "stringop.h" -#include "util.h" - -struct cmd_results *bar_cmd_modifier(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "modifier", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "modifier", "No bar defined."); - } - - uint32_t mod = 0; - - list_t *split = split_string(argv[0], "+"); - for (int i = 0; i < split->length; ++i) { - uint32_t tmp_mod; - if ((tmp_mod = get_modifier_mask_by_name(split->items[i])) > 0) { - mod |= tmp_mod; - continue; - } else { - free_flat_list(split); - return cmd_results_new(CMD_INVALID, "modifier", "Unknown modifier '%s'", split->items[i]); - } - } - free_flat_list(split); - - config->current_bar->modifier = mod; - sway_log(L_DEBUG, "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/output.c b/sway/old/commands/bar/output.c deleted file mode 100644 index a5710bc0b..000000000 --- a/sway/old/commands/bar/output.c +++ /dev/null @@ -1,50 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/commands.h" -#include "list.h" -#include "log.h" - -struct cmd_results *bar_cmd_output(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "output", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "output", "No bar defined."); - } - - const char *output = argv[0]; - list_t *outputs = config->current_bar->outputs; - if (!outputs) { - outputs = create_list(); - config->current_bar->outputs = outputs; - } - - int i; - int add_output = 1; - if (strcmp("*", output) == 0) { - // remove all previous defined outputs and replace with '*' - for (i = 0; i < outputs->length; ++i) { - free(outputs->items[i]); - list_del(outputs, i); - } - } else { - // only add output if not already defined with either the same - // name or as '*' - for (i = 0; i < outputs->length; ++i) { - const char *find = outputs->items[i]; - if (strcmp("*", find) == 0 || strcmp(output, find) == 0) { - add_output = 0; - break; - } - } - } - - if (add_output) { - list_add(outputs, strdup(output)); - sway_log(L_DEBUG, "Adding bar: '%s' to output '%s'", config->current_bar->id, output); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/pango_markup.c b/sway/old/commands/bar/pango_markup.c deleted file mode 100644 index f69e882fd..000000000 --- a/sway/old/commands/bar/pango_markup.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "pango_markup", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "pango_markup", "No bar defined."); - } - - if (strcasecmp("enabled", argv[0]) == 0) { - config->current_bar->pango_markup = true; - sway_log(L_DEBUG, "Enabling pango markup for bar: %s", config->current_bar->id); - } else if (strcasecmp("disabled", argv[0]) == 0) { - config->current_bar->pango_markup = false; - sway_log(L_DEBUG, "Disabling pango markup for bar: %s", config->current_bar->id); - } else { - error = cmd_results_new(CMD_INVALID, "pango_markup", "Invalid value %s", argv[0]); - return error; - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/position.c b/sway/old/commands/bar/position.c deleted file mode 100644 index 50de58e25..000000000 --- a/sway/old/commands/bar/position.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_position(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "position", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "position", "No bar defined."); - } - - if (strcasecmp("top", argv[0]) == 0) { - config->current_bar->position = DESKTOP_SHELL_PANEL_POSITION_TOP; - } else if (strcasecmp("bottom", argv[0]) == 0) { - config->current_bar->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM; - } else if (strcasecmp("left", argv[0]) == 0) { - sway_log(L_INFO, "Warning: swaybar currently only supports top and bottom positioning. YMMV"); - config->current_bar->position = DESKTOP_SHELL_PANEL_POSITION_LEFT; - } else if (strcasecmp("right", argv[0]) == 0) { - sway_log(L_INFO, "Warning: swaybar currently only supports top and bottom positioning. YMMV"); - config->current_bar->position = DESKTOP_SHELL_PANEL_POSITION_RIGHT; - } else { - error = cmd_results_new(CMD_INVALID, "position", "Invalid value %s", argv[0]); - return error; - } - - sway_log(L_DEBUG, "Setting bar position '%s' for bar: %s", argv[0], config->current_bar->id); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/secondary_button.c b/sway/old/commands/bar/secondary_button.c deleted file mode 100644 index 745045c5a..000000000 --- a/sway/old/commands/bar/secondary_button.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_secondary_button(int argc, char **argv) { - const char *cmd_name = "secondary_button"; -#ifndef ENABLE_TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " - "%s called, but sway was compiled without tray support", - cmd_name, cmd_name); -#else - struct cmd_results *error = NULL; - if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); - } - - // User should be able to prefix with 0x or whatever they want - config->current_bar->secondary_button = strtoul(argv[0], NULL, 0); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -#endif -} diff --git a/sway/old/commands/bar/separator_symbol.c b/sway/old/commands/bar/separator_symbol.c deleted file mode 100644 index 2766d8a23..000000000 --- a/sway/old/commands/bar/separator_symbol.c +++ /dev/null @@ -1,21 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_separator_symbol(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "separator_symbol", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "separator_symbol", "No bar defined."); - } - - free(config->current_bar->separator_symbol); - config->current_bar->separator_symbol = strdup(argv[0]); - sway_log(L_DEBUG, "Settings separator_symbol '%s' for bar: %s", config->current_bar->separator_symbol, config->current_bar->id); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/status_command.c b/sway/old/commands/bar/status_command.c deleted file mode 100644 index b227ac474..000000000 --- a/sway/old/commands/bar/status_command.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include "sway/commands.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *bar_cmd_status_command(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "status_command", EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "status_command", "No bar defined."); - } - - free(config->current_bar->status_command); - config->current_bar->status_command = join_args(argv, argc); - sway_log(L_DEBUG, "Feeding bar with status command: %s", config->current_bar->status_command); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/strip_workspace_numbers.c b/sway/old/commands/bar/strip_workspace_numbers.c deleted file mode 100644 index 9ac32482c..000000000 --- a/sway/old/commands/bar/strip_workspace_numbers.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "strip_workspace_numbers", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "strip_workspace_numbers", "No bar defined."); - } - - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->strip_workspace_numbers = true; - sway_log(L_DEBUG, "Stripping workspace numbers on bar: %s", config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->strip_workspace_numbers = false; - sway_log(L_DEBUG, "Enabling workspace numbers on bar: %s", config->current_bar->id); - } else { - error = cmd_results_new(CMD_INVALID, "strip_workspace_numbers", "Invalid value %s", argv[0]); - return error; - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/swaybar_command.c b/sway/old/commands/bar/swaybar_command.c deleted file mode 100644 index 452e2df56..000000000 --- a/sway/old/commands/bar/swaybar_command.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include "sway/commands.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *bar_cmd_swaybar_command(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "swaybar_command", EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "swaybar_command", "No bar defined."); - } - - free(config->current_bar->swaybar_command); - config->current_bar->swaybar_command = join_args(argv, argc); - sway_log(L_DEBUG, "Using custom swaybar command: %s", config->current_bar->swaybar_command); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/tray_output.c b/sway/old/commands/bar/tray_output.c deleted file mode 100644 index 012304a96..000000000 --- a/sway/old/commands/bar/tray_output.c +++ /dev/null @@ -1,29 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/commands.h" - -struct cmd_results *bar_cmd_tray_output(int argc, char **argv) { - const char *cmd_name = "tray_output"; -#ifndef ENABLE_TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " - "%s called, but sway was compiled without tray support", - cmd_name, cmd_name); -#else - struct cmd_results *error = NULL; - if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); - } - - if (strcmp(argv[0], "all") == 0) { - // Default behaviour - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - config->current_bar->tray_output = strdup(argv[0]); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -#endif -} diff --git a/sway/old/commands/bar/tray_padding.c b/sway/old/commands/bar/tray_padding.c deleted file mode 100644 index ac0572cec..000000000 --- a/sway/old/commands/bar/tray_padding.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_tray_padding(int argc, char **argv) { - const char *cmd_name = "tray_padding"; -#ifndef ENABLE_TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command" - "%s called, but sway was compiled without tray support", - cmd_name, cmd_name); -#else - struct cmd_results *error = NULL; - if ((error = checkarg(argc, cmd_name, EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); - } - - if (argc == 1 || (argc == 2 && strcasecmp("px", argv[1]) == 0)) { - char *inv; - uint32_t padding = strtoul(argv[0], &inv, 10); - if (*inv == '\0' || strcasecmp(inv, "px") == 0) { - config->current_bar->tray_padding = padding; - sway_log(L_DEBUG, "Enabling tray padding of %d px on bar: %s", padding, config->current_bar->id); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - } - return cmd_results_new(CMD_FAILURE, cmd_name, - "Expected 'tray_padding [px]'"); -#endif -} diff --git a/sway/old/commands/bar/workspace_buttons.c b/sway/old/commands/bar/workspace_buttons.c deleted file mode 100644 index 67dd2d319..000000000 --- a/sway/old/commands/bar/workspace_buttons.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "workspace_buttons", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "workspace_buttons", "No bar defined."); - } - - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->workspace_buttons = true; - sway_log(L_DEBUG, "Enabling workspace buttons on bar: %s", config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->workspace_buttons = false; - sway_log(L_DEBUG, "Disabling workspace buttons on bar: %s", config->current_bar->id); - } else { - error = cmd_results_new(CMD_INVALID, "workspace_buttons", "Invalid value %s", argv[0]); - return error; - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bar/wrap_scroll.c b/sway/old/commands/bar/wrap_scroll.c deleted file mode 100644 index 4ed1f12a6..000000000 --- a/sway/old/commands/bar/wrap_scroll.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "wrap_scroll", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "wrap_scroll", "No bar defined."); - } - - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->wrap_scroll = true; - sway_log(L_DEBUG, "Enabling wrap scroll on bar: %s", config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->wrap_scroll = false; - sway_log(L_DEBUG, "Disabling wrap scroll on bar: %s", config->current_bar->id); - } else { - error = cmd_results_new(CMD_INVALID, "wrap_scroll", "Invalid value %s", argv[0]); - return error; - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/bind.c b/sway/old/commands/bind.c deleted file mode 100644 index d9ea37b71..000000000 --- a/sway/old/commands/bind.c +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "sway/input_state.h" -#include "list.h" -#include "log.h" -#include "stringop.h" -#include "util.h" - -int binding_order = 0; - -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' + M_LEFT_CLICK; - } - 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; - int i = list_seq_find(mode->bindings, sway_binding_cmp_keys, binding); - if (i > -1) { - sway_log(L_DEBUG, "bindsym - '%s' already exists, overwriting", argv[0]); - struct sway_binding *dup = mode->bindings->items[i]; - free_sway_binding(dup); - list_del(mode->bindings, i); - } - binding->order = binding_order++; - list_add(mode->bindings, binding); - list_qsort(mode->bindings, sway_binding_cmp_qsort); - - 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; - int i = list_seq_find(mode->bindings, sway_binding_cmp_keys, binding); - if (i > -1) { - struct sway_binding *dup = mode->bindings->items[i]; - if (dup->bindcode) { - sway_log(L_DEBUG, "bindcode - '%s' already exists, overwriting", argv[0]); - } else { - sway_log(L_DEBUG, "bindcode - '%s' already exists as bindsym, overwriting", argv[0]); - } - free_sway_binding(dup); - list_del(mode->bindings, i); - } - binding->order = binding_order++; - list_add(mode->bindings, binding); - list_qsort(mode->bindings, sway_binding_cmp_qsort); - - 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/old/commands/border.c b/sway/old/commands/border.c deleted file mode 100644 index c888622ee..000000000 --- a/sway/old/commands/border.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include -#include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/focus.h" - -struct cmd_results *cmd_border(int argc, char **argv) { - struct cmd_results *error = NULL; - if (!config->active) { - return cmd_results_new(CMD_FAILURE, "border", "Can only be used when sway is running."); - } - if ((error = checkarg(argc, "border", EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (argc > 2) { - return cmd_results_new(CMD_INVALID, "border", - "Expected 'border []"); - } - - swayc_t *view = current_container; - enum swayc_border_types border = view->border_type; - int thickness = view->border_thickness; - - if (strcasecmp(argv[0], "none") == 0) { - border = B_NONE; - } else if (strcasecmp(argv[0], "normal") == 0) { - border = B_NORMAL; - } else if (strcasecmp(argv[0], "pixel") == 0) { - border = B_PIXEL; - } else if (strcasecmp(argv[0], "toggle") == 0) { - switch (border) { - case B_NONE: - border = B_PIXEL; - break; - case B_NORMAL: - border = B_NONE; - break; - case B_PIXEL: - border = B_NORMAL; - break; - } - } else { - return cmd_results_new(CMD_INVALID, "border", - "Expected 'border "); - } - - if (argc == 2 && (border == B_NORMAL || border == B_PIXEL)) { - thickness = (int)strtol(argv[1], NULL, 10); - if (errno == ERANGE || thickness < 0) { - errno = 0; - return cmd_results_new(CMD_INVALID, "border", "Number is out of range."); - } - } - - if (view) { - view->border_type = border; - view->border_thickness = thickness; - update_geometry(view); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/client.c b/sway/old/commands/client.c deleted file mode 100644 index f3d879cd4..000000000 --- a/sway/old/commands/client.c +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include "sway/commands.h" - -static struct cmd_results *parse_border_color(struct border_colors *border_colors, const char *cmd_name, int argc, char **argv) { - struct cmd_results *error = NULL; - if (argc < 3 || argc > 5) { - return cmd_results_new(CMD_INVALID, cmd_name, "Requires between three and five color values"); - } - - uint32_t *colors[5] = { - &border_colors->border, - &border_colors->background, - &border_colors->text, - &border_colors->indicator, - &border_colors->child_border - }; - int i; - for (i = 0; i < argc; i++) { - char buffer[10]; - error = add_color(cmd_name, buffer, argv[i]); - if (error) { - return error; - } - *colors[i] = strtoul(buffer + 1, NULL, 16); - } - - if (argc < 5) { - border_colors->child_border = border_colors->background; - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *cmd_client_focused(int argc, char **argv) { - return parse_border_color(&config->border_colors.focused, "client.focused", argc, argv); -} - -struct cmd_results *cmd_client_focused_inactive(int argc, char **argv) { - return parse_border_color(&config->border_colors.focused_inactive, "client.focused_inactive", argc, argv); -} - -struct cmd_results *cmd_client_unfocused(int argc, char **argv) { - return parse_border_color(&config->border_colors.unfocused, "client.unfocused", argc, argv); -} - -struct cmd_results *cmd_client_urgent(int argc, char **argv) { - return parse_border_color(&config->border_colors.urgent, "client.urgent", argc, argv); -} - -struct cmd_results *cmd_client_placeholder(int argc, char **argv) { - return parse_border_color(&config->border_colors.placeholder, "client.placeholder", argc, argv); -} - -struct cmd_results *cmd_client_background(int argc, char **argv) { - char buffer[10]; - struct cmd_results *error = NULL; - uint32_t background; - - if (argc != 1) { - return cmd_results_new(CMD_INVALID, "client.background", "Requires exactly one color value"); - } - - error = add_color("client.background", buffer, argv[0]); - if (error) { - return error; - } - - background = strtoul(buffer+1, NULL, 16); - config->border_colors.background = background; - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/clipboard.c b/sway/old/commands/clipboard.c deleted file mode 100644 index 95514e787..000000000 --- a/sway/old/commands/clipboard.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#include "sway/commands.h" -#include "stringop.h" - -static void send_clipboard(void *data, const char *type, int fd) { - if (strcmp(type, "text/plain") != 0 - && strcmp(type, "text/plain;charset=utf-8") != 0) { - close(fd); - return; - } - - const char *str = data; - write(fd, str, strlen(str)); - close(fd); -} - -struct cmd_results *cmd_clipboard(int argc, char **argv) { - static char *current_data = NULL; - - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "clipboard", EXPECTED_AT_LEAST, 1))) { - return error; - } - - static const char *types[2] = { - "text/plain", - "text/plain;charset=utf-8" - }; - - char *str = join_args(argv, argc); - wlc_set_selection(str, types, 2, &send_clipboard); - - free(current_data); - current_data = str; - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/commands.c b/sway/old/commands/commands.c deleted file mode 100644 index 0c64970c9..000000000 --- a/sway/old/commands/commands.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "list.h" -#include "log.h" - -struct cmd_results *cmd_commands(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "commands", EXPECTED_EQUAL_TO, 1))) { - return error; - } - if ((error = check_security_config())) { - return error; - } - - if (strcmp(argv[0], "{") != 0) { - return cmd_results_new(CMD_FAILURE, "commands", "Expected block declaration"); - } - - if (!config->reading) { - return cmd_results_new(CMD_FAILURE, "commands", "Can only be used in config file."); - } - - return cmd_results_new(CMD_BLOCK_COMMANDS, NULL, NULL); -} diff --git a/sway/old/commands/debuglog.c b/sway/old/commands/debuglog.c deleted file mode 100644 index 658d61657..000000000 --- a/sway/old/commands/debuglog.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *cmd_debuglog(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "debuglog", EXPECTED_EQUAL_TO, 1))) { - return error; - } else if (strcasecmp(argv[0], "toggle") == 0) { - if (config->reading) { - return cmd_results_new(CMD_FAILURE, "debuglog toggle", "Can't be used in config file."); - } - if (toggle_debug_logging()) { - sway_log(L_DEBUG, "Debuglog turned on."); - } - } else if (strcasecmp(argv[0], "on") == 0) { - set_log_level(L_DEBUG); - sway_log(L_DEBUG, "Debuglog turned on."); - } else if (strcasecmp(argv[0], "off") == 0) { - reset_log_level(); - } else { - return cmd_results_new(CMD_FAILURE, "debuglog", "Expected 'debuglog on|off|toggle'"); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - diff --git a/sway/old/commands/default_border.c b/sway/old/commands/default_border.c deleted file mode 100644 index 8fbe8d194..000000000 --- a/sway/old/commands/default_border.c +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include -#include "sway/commands.h" -#include "sway/container.h" - -struct cmd_results *cmd_default_border(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "default_border", EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (argc > 2) { - return cmd_results_new(CMD_INVALID, "default_border", - "Expected 'default_border []"); - } - - enum swayc_border_types border = config->border; - int thickness = config->border_thickness; - - if (strcasecmp(argv[0], "none") == 0) { - border = B_NONE; - } else if (strcasecmp(argv[0], "normal") == 0) { - border = B_NORMAL; - } else if (strcasecmp(argv[0], "pixel") == 0) { - border = B_PIXEL; - } else { - return cmd_results_new(CMD_INVALID, "default_border", - "Expected 'default_border []"); - } - - if (argc == 2 && (border == B_NORMAL || border == B_PIXEL)) { - thickness = (int)strtol(argv[1], NULL, 10); - if (errno == ERANGE || thickness < 0) { - errno = 0; - return cmd_results_new(CMD_INVALID, "default_border", "Number is out out of range."); - } - } - - config->border = border; - config->border_thickness = thickness; - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/default_floating_border.c b/sway/old/commands/default_floating_border.c deleted file mode 100644 index fb48c1c07..000000000 --- a/sway/old/commands/default_floating_border.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include -#include "sway/commands.h" -#include "sway/container.h" - -struct cmd_results *cmd_default_floating_border(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "default_floating_border", EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (argc > 2) { - return cmd_results_new(CMD_INVALID, "default_floating_border", - "Expected 'default_floating_border []"); - } - - enum swayc_border_types border = config->floating_border; - int thickness = config->floating_border_thickness; - - if (strcasecmp(argv[0], "none") == 0) { - border = B_NONE; - } else if (strcasecmp(argv[0], "normal") == 0) { - border = B_NORMAL; - } else if (strcasecmp(argv[0], "pixel") == 0) { - border = B_PIXEL; - } else { - return cmd_results_new(CMD_INVALID, "default_floating_border", - "Expected 'default_floating_border []"); - } - - if (argc == 2 && (border == B_NORMAL || border == B_PIXEL)) { - thickness = (int)strtol(argv[1], NULL, 10); - if (errno == ERANGE || thickness < 0) { - errno = 0; - return cmd_results_new(CMD_INVALID, "default_floating_border", - "Number is out out of range."); - } - } - - config->floating_border = border; - config->floating_border_thickness = thickness; - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/exec.c b/sway/old/commands/exec.c deleted file mode 100644 index 58ef5f94f..000000000 --- a/sway/old/commands/exec.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include "sway/commands.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *cmd_exec(int argc, char **argv) { - 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/old/commands/exec_always.c b/sway/old/commands/exec_always.c deleted file mode 100644 index ab2d8622a..000000000 --- a/sway/old/commands/exec_always.c +++ /dev/null @@ -1,85 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *cmd_exec_always(int argc, char **argv) { - struct cmd_results *error = NULL; - if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); - if ((error = checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0))) { - return error; - } - - char *tmp = NULL; - if (strcmp((char*)*argv, "--no-startup-id") == 0) { - sway_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); - if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) { - return error; - } - - tmp = join_args(argv + 1, argc - 1); - } else { - tmp = join_args(argv, argc); - } - - // Put argument into cmd array - char cmd[4096]; - strncpy(cmd, tmp, sizeof(cmd)); - cmd[sizeof(cmd) - 1] = 0; - free(tmp); - sway_log(L_DEBUG, "Executing %s", cmd); - - int fd[2]; - if (pipe(fd) != 0) { - sway_log(L_ERROR, "Unable to create pipe for fork"); - } - - pid_t pid; - pid_t *child = malloc(sizeof(pid_t)); // malloc'd so that Linux can avoid copying the process space - if (!child) { - return cmd_results_new(CMD_FAILURE, "exec_always", "Unable to allocate child pid"); - } - // Fork process - if ((pid = fork()) == 0) { - // Fork child process again - setsid(); - if ((*child = fork()) == 0) { - execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); - /* Not reached */ - } - close(fd[0]); - ssize_t s = 0; - while ((size_t)s < sizeof(pid_t)) { - s += write(fd[1], ((uint8_t *)child) + s, sizeof(pid_t) - s); - } - close(fd[1]); - _exit(0); // Close child process - } else if (pid < 0) { - free(child); - return cmd_results_new(CMD_FAILURE, "exec_always", "fork() failed"); - } - close(fd[1]); // close write - ssize_t s = 0; - while ((size_t)s < sizeof(pid_t)) { - s += read(fd[0], ((uint8_t *)child) + s, sizeof(pid_t) - s); - } - close(fd[0]); - // cleanup child process - wait(0); - swayc_t *ws = swayc_active_workspace(); - if (*child > 0 && ws) { - sway_log(L_DEBUG, "Child process created with pid %d for workspace %s", *child, ws->name); - struct pid_workspace *pw = malloc(sizeof(struct pid_workspace)); - pw->pid = child; - pw->workspace = strdup(ws->name); - pid_workspace_add(pw); - } else { - free(child); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/exit.c b/sway/old/commands/exit.c deleted file mode 100644 index f192f86a8..000000000 --- a/sway/old/commands/exit.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "sway/commands.h" -#include "sway/container.h" - -void sway_terminate(int exit_code); - -struct cmd_results *cmd_exit(int argc, char **argv) { - struct cmd_results *error = NULL; - 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; - } - // Close all views - close_views(&root_container); - sway_terminate(EXIT_SUCCESS); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - diff --git a/sway/old/commands/floating.c b/sway/old/commands/floating.c deleted file mode 100644 index ccfde5326..000000000 --- a/sway/old/commands/floating.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/ipc-server.h" -#include "sway/layout.h" -#include "list.h" -#include "log.h" - -struct cmd_results *cmd_floating(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "floating", "Can't be used in config file."); - if ((error = checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1))) { - return error; - } - swayc_t *view = current_container; - bool wants_floating; - if (strcasecmp(argv[0], "enable") == 0) { - wants_floating = true; - } else if (strcasecmp(argv[0], "disable") == 0) { - wants_floating = false; - } else if (strcasecmp(argv[0], "toggle") == 0) { - wants_floating = !view->is_floating; - } else { - return cmd_results_new(CMD_FAILURE, "floating", - "Expected 'floating "); - } - - // Prevent running floating commands on things like workspaces - if (view->type != C_VIEW) { - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - - // Change from nonfloating to floating - if (!view->is_floating && wants_floating) { - // Remove view from its current location - destroy_container(remove_child(view)); - - // and move it into workspace floating - add_floating(swayc_active_workspace(), view); - view->x = (swayc_active_workspace()->width - view->width)/2; - view->y = (swayc_active_workspace()->height - view->height)/2; - if (view->desired_width != -1) { - view->width = view->desired_width; - } - if (view->desired_height != -1) { - view->height = view->desired_height; - } - arrange_windows(swayc_active_workspace(), -1, -1); - - } else if (view->is_floating && !wants_floating) { - // Delete the view from the floating list and unset its is_floating flag - remove_child(view); - view->is_floating = false; - // Get the properly focused container, and add in the view there - swayc_t *focused = container_under_pointer(); - // If focused is null, it's because the currently focused container is a workspace - if (focused == NULL || focused->is_floating) { - focused = swayc_active_workspace(); - } - set_focused_container(focused); - - sway_log(L_DEBUG, "Non-floating focused container is %p", focused); - - // Case of focused workspace, just create as child of it - if (focused->type == C_WORKSPACE) { - add_child(focused, view); - } - // Regular case, create as sibling of current container - else { - add_sibling(focused, view); - } - // Refocus on the view once its been put back into the layout - view->width = view->height = 0; - arrange_windows(swayc_active_workspace(), -1, -1); - remove_view_from_scratchpad(view); - ipc_event_window(view, "floating"); - } - set_focused_container(view); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/floating_maximum_size.c b/sway/old/commands/floating_maximum_size.c deleted file mode 100644 index 5bca4d7cd..000000000 --- a/sway/old/commands/floating_maximum_size.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *cmd_floating_maximum_size(int argc, char **argv) { - struct cmd_results *error = NULL; - int32_t width; - int32_t height; - char *ptr; - - if ((error = checkarg(argc, "floating_maximum_size", EXPECTED_EQUAL_TO, 3))) { - return error; - } - width = strtol(argv[0], &ptr, 10); - height = strtol(argv[2], &ptr, 10); - - if (width < -1) { - sway_log(L_DEBUG, "floating_maximum_size invalid width value: '%s'", argv[0]); - - } else { - config->floating_maximum_width = width; - - } - - if (height < -1) { - sway_log(L_DEBUG, "floating_maximum_size invalid height value: '%s'", argv[2]); - } - else { - config->floating_maximum_height = height; - - } - - sway_log(L_DEBUG, "New floating_maximum_size: '%d' x '%d'", config->floating_maximum_width, - config->floating_maximum_height); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/floating_minimum_size.c b/sway/old/commands/floating_minimum_size.c deleted file mode 100644 index ba72454c9..000000000 --- a/sway/old/commands/floating_minimum_size.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *cmd_floating_minimum_size(int argc, char **argv) { - struct cmd_results *error = NULL; - int32_t width; - int32_t height; - char *ptr; - - if ((error = checkarg(argc, "floating_minimum_size", EXPECTED_EQUAL_TO, 3))) { - return error; - } - width = strtol(argv[0], &ptr, 10); - height = strtol(argv[2], &ptr, 10); - - if (width <= 0) { - sway_log(L_DEBUG, "floating_minimum_size invalid width value: '%s'", argv[0]); - - } else { - config->floating_minimum_width = width; - - } - - if (height <= 0) { - sway_log(L_DEBUG, "floating_minimum_size invalid height value: '%s'", argv[2]); - } - else { - config->floating_minimum_height = height; - - } - - sway_log(L_DEBUG, "New floating_minimum_size: '%d' x '%d'", config->floating_minimum_width, - config->floating_minimum_height); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/floating_mod.c b/sway/old/commands/floating_mod.c deleted file mode 100644 index b8e81ab92..000000000 --- a/sway/old/commands/floating_mod.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input_state.h" -#include "list.h" -#include "log.h" -#include "stringop.h" -#include "util.h" - -struct cmd_results *cmd_floating_mod(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "floating_modifier", EXPECTED_AT_LEAST, 1))) { - return error; - } - int i; - list_t *split = split_string(argv[0], "+"); - config->floating_mod = 0; - - // set modifier keys - for (i = 0; i < split->length; ++i) { - config->floating_mod |= get_modifier_mask_by_name(split->items[i]); - } - free_flat_list(split); - if (!config->floating_mod) { - error = cmd_results_new(CMD_INVALID, "floating_modifier", "Unknown keys %s", argv[0]); - return error; - } - - if (argc >= 2) { - if (strcasecmp("inverse", argv[1]) == 0) { - config->dragging_key = M_RIGHT_CLICK; - config->resizing_key = M_LEFT_CLICK; - } else if (strcasecmp("normal", argv[1]) == 0) { - config->dragging_key = M_LEFT_CLICK; - config->resizing_key = M_RIGHT_CLICK; - } else { - error = cmd_results_new(CMD_INVALID, "floating_modifier", "Invalid definition %s", argv[1]); - return error; - } - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/floating_scroll.c b/sway/old/commands/floating_scroll.c deleted file mode 100644 index 8c50c5bd5..000000000 --- a/sway/old/commands/floating_scroll.c +++ /dev/null @@ -1,46 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include "sway/commands.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *cmd_floating_scroll(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "floating_scroll", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!strcasecmp("up", argv[0])) { - free(config->floating_scroll_up_cmd); - if (argc < 2) { - config->floating_scroll_up_cmd = strdup(""); - } else { - config->floating_scroll_up_cmd = join_args(argv + 1, argc - 1); - } - } else if (!strcasecmp("down", argv[0])) { - free(config->floating_scroll_down_cmd); - if (argc < 2) { - config->floating_scroll_down_cmd = strdup(""); - } else { - config->floating_scroll_down_cmd = join_args(argv + 1, argc - 1); - } - } else if (!strcasecmp("left", argv[0])) { - free(config->floating_scroll_left_cmd); - if (argc < 2) { - config->floating_scroll_left_cmd = strdup(""); - } else { - config->floating_scroll_left_cmd = join_args(argv + 1, argc - 1); - } - } else if (!strcasecmp("right", argv[0])) { - free(config->floating_scroll_right_cmd); - if (argc < 2) { - config->floating_scroll_right_cmd = strdup(""); - } else { - config->floating_scroll_right_cmd = join_args(argv + 1, argc - 1); - } - } else { - error = cmd_results_new(CMD_INVALID, "floating_scroll", "Unknown command: '%s'", argv[0]); - return error; - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/focus.c b/sway/old/commands/focus.c deleted file mode 100644 index c83157b85..000000000 --- a/sway/old/commands/focus.c +++ /dev/null @@ -1,100 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/focus.h" -#include "sway/input_state.h" -#include "sway/output.h" -#include "sway/workspace.h" - -struct cmd_results *cmd_focus(int argc, char **argv) { - if (config->reading) return cmd_results_new(CMD_FAILURE, "focus", "Can't be used in config file."); - struct cmd_results *error = NULL; - if (argc > 0 && strcasecmp(argv[0], "output") == 0) { - swayc_t *output = NULL; - struct wlc_point abs_pos; - get_absolute_center_position(get_focused_container(&root_container), &abs_pos); - if ((error = checkarg(argc, "focus", EXPECTED_EQUAL_TO, 2))) { - return error; - } else if (!(output = output_by_name(argv[1], &abs_pos))) { - return cmd_results_new(CMD_FAILURE, "focus output", - "Can't find output with name/at direction '%s' @ (%i,%i)", argv[1], abs_pos.x, abs_pos.y); - } else if (!workspace_switch(swayc_active_workspace_for(output))) { - return cmd_results_new(CMD_FAILURE, "focus output", - "Switching to workspace on output '%s' was blocked", argv[1]); - } else if (config->mouse_warping) { - swayc_t *focused = get_focused_view(output); - if (focused && focused->type == C_VIEW) { - center_pointer_on(focused); - } - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } else if (argc == 0) { - set_focused_container(current_container); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } else if ((error = checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1))) { - return error; - } - static int floating_toggled_index = 0; - static int tiled_toggled_index = 0; - if (strcasecmp(argv[0], "left") == 0) { - move_focus(MOVE_LEFT); - } else if (strcasecmp(argv[0], "right") == 0) { - move_focus(MOVE_RIGHT); - } else if (strcasecmp(argv[0], "up") == 0) { - move_focus(MOVE_UP); - } else if (strcasecmp(argv[0], "down") == 0) { - move_focus(MOVE_DOWN); - } else if (strcasecmp(argv[0], "parent") == 0) { - move_focus(MOVE_PARENT); - } else if (strcasecmp(argv[0], "child") == 0) { - move_focus(MOVE_CHILD); - } else if (strcasecmp(argv[0], "next") == 0) { - move_focus(MOVE_NEXT); - } else if (strcasecmp(argv[0], "prev") == 0) { - move_focus(MOVE_PREV); - } else if (strcasecmp(argv[0], "mode_toggle") == 0) { - int i; - swayc_t *workspace = swayc_active_workspace(); - swayc_t *focused = get_focused_view(workspace); - if (focused->is_floating) { - if (workspace->children->length > 0) { - for (i = 0;i < workspace->floating->length; i++) { - if (workspace->floating->items[i] == focused) { - floating_toggled_index = i; - break; - } - } - if (workspace->children->length > tiled_toggled_index) { - set_focused_container(get_focused_view(workspace->children->items[tiled_toggled_index])); - } else { - set_focused_container(get_focused_view(workspace->children->items[0])); - tiled_toggled_index = 0; - } - } - } else { - if (workspace->floating->length > 0) { - for (i = 0;i < workspace->children->length; i++) { - if (workspace->children->items[i] == focused) { - tiled_toggled_index = i; - break; - } - } - if (workspace->floating->length > floating_toggled_index) { - swayc_t *floating = workspace->floating->items[floating_toggled_index]; - set_focused_container(get_focused_view(floating)); - } else { - swayc_t *floating = workspace->floating->items[workspace->floating->length - 1]; - set_focused_container(get_focused_view(floating)); - tiled_toggled_index = workspace->floating->length - 1; - } - } - } - } else { - return cmd_results_new(CMD_INVALID, "focus", - "Expected 'focus ' or 'focus output '"); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/focus_follows_mouse.c b/sway/old/commands/focus_follows_mouse.c deleted file mode 100644 index 7c9c2b133..000000000 --- a/sway/old/commands/focus_follows_mouse.c +++ /dev/null @@ -1,13 +0,0 @@ -#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/old/commands/font.c b/sway/old/commands/font.c deleted file mode 100644 index 32994f8a1..000000000 --- a/sway/old/commands/font.c +++ /dev/null @@ -1,27 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/border.h" -#include "sway/commands.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *cmd_font(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "font", EXPECTED_AT_LEAST, 1))) { - return error; - } - - char *font = join_args(argv, argc); - free(config->font); - if (strlen(font) > 6 && strncmp("pango:", font, 6) == 0) { - config->font = strdup(font + 6); - free(font); - } else { - config->font = font; - } - - config->font_height = get_font_text_height(config->font); - - sway_log(L_DEBUG, "Settings font %s", config->font); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/for_window.c b/sway/old/commands/for_window.c deleted file mode 100644 index d1fd1641a..000000000 --- a/sway/old/commands/for_window.c +++ /dev/null @@ -1,41 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/commands.h" -#include "sway/criteria.h" -#include "list.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *cmd_for_window(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "for_window", EXPECTED_AT_LEAST, 2))) { - return error; - } - // add command to a criteria/command pair that is run against views when they appear. - char *criteria = argv[0], *cmdlist = join_args(argv + 1, argc - 1); - - struct criteria *crit = malloc(sizeof(struct criteria)); - if (!crit) { - return cmd_results_new(CMD_FAILURE, "for_window", "Unable to allocate criteria"); - } - crit->crit_raw = strdup(criteria); - crit->cmdlist = cmdlist; - crit->tokens = create_list(); - char *err_str = extract_crit_tokens(crit->tokens, crit->crit_raw); - - if (err_str) { - error = cmd_results_new(CMD_INVALID, "for_window", err_str); - free(err_str); - free_criteria(crit); - } else if (crit->tokens->length == 0) { - error = cmd_results_new(CMD_INVALID, "for_window", "Found no name/value pairs in criteria"); - free_criteria(crit); - } else if (list_seq_find(config->criteria, criteria_cmp, crit) != -1) { - sway_log(L_DEBUG, "for_window: Duplicate, skipping."); - free_criteria(crit); - } else { - sway_log(L_DEBUG, "for_window: '%s' -> '%s' added", crit->crit_raw, crit->cmdlist); - list_add(config->criteria, crit); - } - return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/force_focus_wrapping.c b/sway/old/commands/force_focus_wrapping.c deleted file mode 100644 index f19dd1631..000000000 --- a/sway/old/commands/force_focus_wrapping.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_force_focus_wrapping(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "force_focus_wrapping", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - config->force_focus_wrapping = !strcasecmp(argv[0], "yes"); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/fullscreen.c b/sway/old/commands/fullscreen.c deleted file mode 100644 index bfff82f97..000000000 --- a/sway/old/commands/fullscreen.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/focus.h" -#include "sway/ipc-server.h" -#include "sway/layout.h" - -struct cmd_results *cmd_fullscreen(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "fullscreen", "Can't be used in config file."); - if (!config->active) return cmd_results_new(CMD_FAILURE, "fullscreen", "Can only be used when sway is running."); - if ((error = checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0))) { - return error; - } - swayc_t *container = current_container; - if(container->type != C_VIEW){ - return cmd_results_new(CMD_INVALID, "fullscreen", "Only views can fullscreen"); - } - swayc_t *workspace = swayc_parent_by_type(container, C_WORKSPACE); - bool current = swayc_is_fullscreen(container); - wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); - - if (container->is_floating) { - if (current) { - // set dimensions back to what they were before we fullscreened this - container->x = container->cached_geometry.origin.x; - container->y = container->cached_geometry.origin.y; - container->width = container->cached_geometry.size.w; - container->height = container->cached_geometry.size.h; - } else { - // cache dimensions so we can reset them after we "unfullscreen" this - struct wlc_geometry geo = { - .origin = { - .x = container->x, - .y = container->y - }, - .size = { - .w = container->width, - .h = container->height - } - }; - container->cached_geometry = geo; - } - } - - // Resize workspace if going from fullscreen -> notfullscreen - // otherwise just resize container - if (!current) { - arrange_windows(workspace, -1, -1); - workspace->fullscreen = container; - } else { - arrange_windows(container, -1, -1); - workspace->fullscreen = NULL; - } - ipc_event_window(container, "fullscreen_mode"); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/gaps.c b/sway/old/commands/gaps.c deleted file mode 100644 index 0a48592da..000000000 --- a/sway/old/commands/gaps.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include -#include -#include -#include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/focus.h" -#include "sway/layout.h" - -struct cmd_results *cmd_gaps(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1))) { - return error; - } - const char *expected_syntax = - "Expected 'gaps edge_gaps ' or " - "'gaps '"; - const char *amount_str = argv[0]; - // gaps amount - if (argc >= 1 && isdigit(*amount_str)) { - int amount = (int)strtol(amount_str, NULL, 10); - if (errno == ERANGE) { - errno = 0; - return cmd_results_new(CMD_INVALID, "gaps", "Number is out out of range."); - } - config->gaps_inner = config->gaps_outer = amount; - arrange_windows(&root_container, -1, -1); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - // gaps inner|outer n - else if (argc >= 2 && isdigit((amount_str = argv[1])[0])) { - int amount = (int)strtol(amount_str, NULL, 10); - if (errno == ERANGE) { - errno = 0; - return cmd_results_new(CMD_INVALID, "gaps", "Number is out out of range."); - } - const char *target_str = argv[0]; - if (strcasecmp(target_str, "inner") == 0) { - config->gaps_inner = amount; - } else if (strcasecmp(target_str, "outer") == 0) { - config->gaps_outer = amount; - } - arrange_windows(&root_container, -1, -1); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } else if (argc == 2 && strcasecmp(argv[0], "edge_gaps") == 0) { - // gaps edge_gaps - if (strcasecmp(argv[1], "toggle") == 0) { - if (config->reading) { - return cmd_results_new(CMD_FAILURE, "gaps edge_gaps toggle", - "Can't be used in config file."); - } - config->edge_gaps = !config->edge_gaps; - } else { - config->edge_gaps = - (strcasecmp(argv[1], "yes") == 0 || strcasecmp(argv[1], "on") == 0); - } - arrange_windows(&root_container, -1, -1); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - // gaps inner|outer current|all set|plus|minus n - if (argc < 4 || config->reading) { - return cmd_results_new(CMD_INVALID, "gaps", expected_syntax); - } - // gaps inner|outer ... - const char *inout_str = argv[0]; - enum {INNER, OUTER} inout; - if (strcasecmp(inout_str, "inner") == 0) { - inout = INNER; - } else if (strcasecmp(inout_str, "outer") == 0) { - inout = OUTER; - } else { - return cmd_results_new(CMD_INVALID, "gaps", expected_syntax); - } - - // gaps ... current|all ... - const char *target_str = argv[1]; - enum {CURRENT, WORKSPACE, ALL} target; - if (strcasecmp(target_str, "current") == 0) { - target = CURRENT; - } else if (strcasecmp(target_str, "all") == 0) { - target = ALL; - } else if (strcasecmp(target_str, "workspace") == 0) { - if (inout == OUTER) { - target = CURRENT; - } else { - // Set gap for views in workspace - target = WORKSPACE; - } - } else { - return cmd_results_new(CMD_INVALID, "gaps", expected_syntax); - } - - // gaps ... n - amount_str = argv[3]; - int amount = (int)strtol(amount_str, NULL, 10); - if (errno == ERANGE) { - errno = 0; - return cmd_results_new(CMD_INVALID, "gaps", "Number is out out of range."); - } - - // gaps ... set|plus|minus ... - const char *method_str = argv[2]; - enum {SET, ADD} method; - if (strcasecmp(method_str, "set") == 0) { - method = SET; - } else if (strcasecmp(method_str, "plus") == 0) { - method = ADD; - } else if (strcasecmp(method_str, "minus") == 0) { - method = ADD; - amount *= -1; - } else { - return cmd_results_new(CMD_INVALID, "gaps", expected_syntax); - } - - if (target == CURRENT) { - swayc_t *cont; - if (inout == OUTER) { - if ((cont = swayc_active_workspace()) == NULL) { - return cmd_results_new(CMD_FAILURE, "gaps", "There's no active workspace."); - } - } else { - if ((cont = get_focused_view(&root_container))->type != C_VIEW) { - return cmd_results_new(CMD_FAILURE, "gaps", "Currently focused item is not a view."); - } - } - cont->gaps = swayc_gap(cont); - if (method == SET) { - cont->gaps = amount; - } else if ((cont->gaps += amount) < 0) { - cont->gaps = 0; - } - arrange_windows(cont->parent, -1, -1); - } else if (inout == OUTER) { - //resize all workspace. - int i,j; - for (i = 0; i < root_container.children->length; ++i) { - swayc_t *op = root_container.children->items[i]; - for (j = 0; j < op->children->length; ++j) { - swayc_t *ws = op->children->items[j]; - if (method == SET) { - ws->gaps = amount; - } else if ((ws->gaps += amount) < 0) { - ws->gaps = 0; - } - } - } - arrange_windows(&root_container, -1, -1); - } else { - // Resize gaps for all views in workspace - swayc_t *top; - if (target == WORKSPACE) { - if ((top = swayc_active_workspace()) == NULL) { - return cmd_results_new(CMD_FAILURE, "gaps", "There's currently no active workspace."); - } - } else { - top = &root_container; - } - int top_gap = top->gaps; - container_map(top, method == SET ? set_gaps : add_gaps, &amount); - top->gaps = top_gap; - arrange_windows(top, -1, -1); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/hide_edge_borders.c b/sway/old/commands/hide_edge_borders.c deleted file mode 100644 index ee2a2644f..000000000 --- a/sway/old/commands/hide_edge_borders.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "hide_edge_borders", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (strcasecmp(argv[0], "none") == 0) { - config->hide_edge_borders = E_NONE; - } else if (strcasecmp(argv[0], "vertical") == 0) { - config->hide_edge_borders = E_VERTICAL; - } else if (strcasecmp(argv[0], "horizontal") == 0) { - config->hide_edge_borders = E_HORIZONTAL; - } else if (strcasecmp(argv[0], "both") == 0) { - config->hide_edge_borders = E_BOTH; - } else if (strcasecmp(argv[0], "smart") == 0) { - config->hide_edge_borders = E_SMART; - } else { - return cmd_results_new(CMD_INVALID, "hide_edge_borders", - "Expected 'hide_edge_borders '"); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/include.c b/sway/old/commands/include.c deleted file mode 100644 index 1ba9a10d2..000000000 --- a/sway/old/commands/include.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "sway/commands.h" -#include "sway/config.h" - -struct cmd_results *cmd_include(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "include", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (!load_include_configs(argv[0], config)) { - return cmd_results_new(CMD_INVALID, "include", "Failed to include sub configuration file: %s", argv[0]); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input.c b/sway/old/commands/input.c deleted file mode 100644 index ad53d2721..000000000 --- a/sway/old/commands/input.c +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" -#include "log.h" - -struct cmd_results *cmd_input(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { - return error; - } - - if (config->reading && strcmp("{", argv[1]) == 0) { - current_input_config = new_input_config(argv[0]); - sway_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); - return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); - } - - if (argc > 2) { - int argc_new = argc-2; - char **argv_new = argv+2; - - struct cmd_results *res; - current_input_config = new_input_config(argv[0]); - if (strcasecmp("accel_profile", argv[1]) == 0) { - res = input_cmd_accel_profile(argc_new, argv_new); - } else if (strcasecmp("click_method", argv[1]) == 0) { - res = input_cmd_click_method(argc_new, argv_new); - } else if (strcasecmp("drag_lock", argv[1]) == 0) { - res = input_cmd_drag_lock(argc_new, argv_new); - } else if (strcasecmp("dwt", argv[1]) == 0) { - res = input_cmd_dwt(argc_new, argv_new); - } else if (strcasecmp("events", argv[1]) == 0) { - res = input_cmd_events(argc_new, argv_new); - } else if (strcasecmp("left_handed", argv[1]) == 0) { - res = input_cmd_left_handed(argc_new, argv_new); - } else if (strcasecmp("middle_emulation", argv[1]) == 0) { - res = input_cmd_middle_emulation(argc_new, argv_new); - } else if (strcasecmp("natural_scroll", argv[1]) == 0) { - res = input_cmd_natural_scroll(argc_new, argv_new); - } else if (strcasecmp("pointer_accel", argv[1]) == 0) { - res = input_cmd_pointer_accel(argc_new, argv_new); - } else if (strcasecmp("scroll_method", argv[1]) == 0) { - res = input_cmd_scroll_method(argc_new, argv_new); - } else if (strcasecmp("tap", argv[1]) == 0) { - res = input_cmd_tap(argc_new, argv_new); - } else { - res = cmd_results_new(CMD_INVALID, "input ", "Unknown command %s", argv[1]); - } - current_input_config = NULL; - return res; - } - - return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); -} diff --git a/sway/old/commands/input/accel_profile.c b/sway/old/commands/input/accel_profile.c deleted file mode 100644 index 8288c1ada..000000000 --- a/sway/old/commands/input/accel_profile.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" - -struct cmd_results *input_cmd_accel_profile(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "accel_profile", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "accel_profile", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "adaptive") == 0) { - new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; - } else if (strcasecmp(argv[0], "flat") == 0) { - new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; - } else { - return cmd_results_new(CMD_INVALID, "accel_profile", - "Expected 'accel_profile '"); - } - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/click_method.c b/sway/old/commands/input/click_method.c deleted file mode 100644 index 5e9d3dcb1..000000000 --- a/sway/old/commands/input/click_method.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" -#include "log.h" - -struct cmd_results *input_cmd_click_method(int argc, char **argv) { - sway_log(L_DEBUG, "click_method for device: %d %s", current_input_config==NULL, current_input_config->identifier); - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "click_method", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "click_method", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "none") == 0) { - new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE; - } else if (strcasecmp(argv[0], "button_areas") == 0) { - new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; - } else if (strcasecmp(argv[0], "clickfinger") == 0) { - new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; - } else { - return cmd_results_new(CMD_INVALID, "click_method", "Expected 'click_method -#include -#include "sway/commands.h" -#include "sway/input.h" - -struct cmd_results *input_cmd_drag_lock(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "drag_lock", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "drag_lock", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "enabled") == 0) { - new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; - } else if (strcasecmp(argv[0], "disabled") == 0) { - new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; - } else { - return cmd_results_new(CMD_INVALID, "drag_lock", "Expected 'drag_lock '"); - } - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/dwt.c b/sway/old/commands/input/dwt.c deleted file mode 100644 index 557b22073..000000000 --- a/sway/old/commands/input/dwt.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" - -struct cmd_results *input_cmd_dwt(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "dwt", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "dwt", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "enabled") == 0) { - new_config->dwt = LIBINPUT_CONFIG_DWT_ENABLED; - } else if (strcasecmp(argv[0], "disabled") == 0) { - new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED; - } else { - return cmd_results_new(CMD_INVALID, "dwt", "Expected 'dwt '"); - } - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/events.c b/sway/old/commands/input/events.c deleted file mode 100644 index 9d54287a7..000000000 --- a/sway/old/commands/input/events.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" -#include "log.h" - -struct cmd_results *input_cmd_events(int argc, char **argv) { - sway_log(L_DEBUG, "events for device: %s", current_input_config->identifier); - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "events", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "enabled") == 0) { - new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; - } else if (strcasecmp(argv[0], "disabled") == 0) { - new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; - } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) { - new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; - } else { - return cmd_results_new(CMD_INVALID, "events", "Expected 'events '"); - } - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/left_handed.c b/sway/old/commands/input/left_handed.c deleted file mode 100644 index 6c913e703..000000000 --- a/sway/old/commands/input/left_handed.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" - -struct cmd_results *input_cmd_left_handed(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "left_handed", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "left_handed", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "enabled") == 0) { - new_config->left_handed = 1; - } else if (strcasecmp(argv[0], "disabled") == 0) { - new_config->left_handed = 0; - } else { - return cmd_results_new(CMD_INVALID, "left_handed", "Expected 'left_handed '"); - } - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/middle_emulation.c b/sway/old/commands/input/middle_emulation.c deleted file mode 100644 index 33cdd7d60..000000000 --- a/sway/old/commands/input/middle_emulation.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" - -struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "middle_emulation", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "middle_emulation", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "enabled") == 0) { - new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED; - } else if (strcasecmp(argv[0], "disabled") == 0) { - new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; - } else { - return cmd_results_new(CMD_INVALID, "middle_emulation", "Expected 'middle_emulation '"); - } - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/natural_scroll.c b/sway/old/commands/input/natural_scroll.c deleted file mode 100644 index 7bc8b8d07..000000000 --- a/sway/old/commands/input/natural_scroll.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" - -struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "natural_scroll", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "natural_scoll", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "enabled") == 0) { - new_config->natural_scroll = 1; - } else if (strcasecmp(argv[0], "disabled") == 0) { - new_config->natural_scroll = 0; - } else { - return cmd_results_new(CMD_INVALID, "natural_scroll", "Expected 'natural_scroll '"); - } - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/pointer_accel.c b/sway/old/commands/input/pointer_accel.c deleted file mode 100644 index 94f595d15..000000000 --- a/sway/old/commands/input/pointer_accel.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" - -struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "pointer_accel", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "pointer_accel", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - float pointer_accel = atof(argv[0]); - if (pointer_accel < -1 || pointer_accel > 1) { - return cmd_results_new(CMD_INVALID, "pointer_accel", "Input out of range [-1, 1]"); - } - new_config->pointer_accel = pointer_accel; - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/scroll_method.c b/sway/old/commands/input/scroll_method.c deleted file mode 100644 index 5c6c3d7af..000000000 --- a/sway/old/commands/input/scroll_method.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" - -struct cmd_results *input_cmd_scroll_method(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "scroll_method", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "scroll_method", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "none") == 0) { - new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; - } else if (strcasecmp(argv[0], "two_finger") == 0) { - new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; - } else if (strcasecmp(argv[0], "edge") == 0) { - new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE; - } else if (strcasecmp(argv[0], "on_button_down") == 0) { - new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; - } else { - return cmd_results_new(CMD_INVALID, "scroll_method", "Expected 'scroll_method '"); - } - - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/input/tap.c b/sway/old/commands/input/tap.c deleted file mode 100644 index 9e3ca2af8..000000000 --- a/sway/old/commands/input/tap.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/input.h" -#include "log.h" - -struct cmd_results *input_cmd_tap(int argc, char **argv) { - sway_log(L_DEBUG, "tap for device: %s", current_input_config->identifier); - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "tap", EXPECTED_AT_LEAST, 1))) { - return error; - } - if (!current_input_config) { - return cmd_results_new(CMD_FAILURE, "tap", "No input device defined."); - } - struct input_config *new_config = new_input_config(current_input_config->identifier); - - if (strcasecmp(argv[0], "enabled") == 0) { - new_config->tap = LIBINPUT_CONFIG_TAP_ENABLED; - } else if (strcasecmp(argv[0], "disabled") == 0) { - new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED; - } else { - return cmd_results_new(CMD_INVALID, "tap", "Expected 'tap '"); - } - - sway_log(L_DEBUG, "apply-tap for device: %s", current_input_config->identifier); - input_cmd_apply(new_config); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/ipc.c b/sway/old/commands/ipc.c deleted file mode 100644 index 0c6789611..000000000 --- a/sway/old/commands/ipc.c +++ /dev/null @@ -1,162 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include "sway/security.h" -#include "sway/commands.h" -#include "sway/config.h" -#include "ipc.h" -#include "log.h" -#include "util.h" - -static struct ipc_policy *current_policy = NULL; - -struct cmd_results *cmd_ipc(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 2))) { - return error; - } - if ((error = check_security_config())) { - return error; - } - - char *program = NULL; - - if (!strcmp(argv[0], "*")) { - program = strdup(argv[0]); - } else if (!(program = resolve_path(argv[0]))) { - return cmd_results_new( - CMD_INVALID, "ipc", "Unable to resolve IPC Policy target."); - } - if (config->reading && strcmp("{", argv[1]) != 0) { - return cmd_results_new(CMD_INVALID, "ipc", - "Expected '{' at start of IPC config definition."); - } - - if (!config->reading) { - return cmd_results_new(CMD_FAILURE, "ipc", "Can only be used in config file."); - } - - current_policy = alloc_ipc_policy(program); - list_add(config->ipc_policies, current_policy); - - free(program); - return cmd_results_new(CMD_BLOCK_IPC, NULL, NULL); -} - -struct cmd_results *cmd_ipc_events(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "events", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (config->reading && strcmp("{", argv[0]) != 0) { - return cmd_results_new(CMD_INVALID, "events", - "Expected '{' at start of IPC event config definition."); - } - - if (!config->reading) { - return cmd_results_new(CMD_FAILURE, "events", "Can only be used in config file."); - } - - return cmd_results_new(CMD_BLOCK_IPC_EVENTS, NULL, NULL); -} - -struct cmd_results *cmd_ipc_cmd(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - bool enabled; - if (strcmp(argv[0], "enabled") == 0) { - enabled = true; - } else if (strcmp(argv[0], "disabled") == 0) { - enabled = false; - } else { - return cmd_results_new(CMD_INVALID, argv[-1], - "Argument must be one of 'enabled' or 'disabled'"); - } - - struct { - char *name; - enum ipc_feature type; - } types[] = { - { "*", IPC_FEATURE_ALL_COMMANDS }, - { "command", IPC_FEATURE_COMMAND }, - { "workspaces", IPC_FEATURE_GET_WORKSPACES }, - { "outputs", IPC_FEATURE_GET_OUTPUTS }, - { "tree", IPC_FEATURE_GET_TREE }, - { "marks", IPC_FEATURE_GET_MARKS }, - { "bar-config", IPC_FEATURE_GET_BAR_CONFIG }, - { "inputs", IPC_FEATURE_GET_INPUTS }, - { "clipboard", IPC_FEATURE_GET_CLIPBOARD }, - }; - - uint32_t type = 0; - - for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) { - if (strcmp(types[i].name, argv[-1]) == 0) { - type = types[i].type; - break; - } - } - - if (enabled) { - current_policy->features |= type; - sway_log(L_DEBUG, "Enabled IPC %s feature", argv[-1]); - } else { - current_policy->features &= ~type; - sway_log(L_DEBUG, "Disabled IPC %s feature", argv[-1]); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *cmd_ipc_event_cmd(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - bool enabled; - if (strcmp(argv[0], "enabled") == 0) { - enabled = true; - } else if (strcmp(argv[0], "disabled") == 0) { - enabled = false; - } else { - return cmd_results_new(CMD_INVALID, argv[-1], - "Argument must be one of 'enabled' or 'disabled'"); - } - - struct { - char *name; - enum ipc_feature type; - } types[] = { - { "*", IPC_FEATURE_ALL_EVENTS }, - { "workspace", IPC_FEATURE_EVENT_WORKSPACE }, - { "output", IPC_FEATURE_EVENT_OUTPUT }, - { "mode", IPC_FEATURE_EVENT_MODE }, - { "window", IPC_FEATURE_EVENT_WINDOW }, - { "binding", IPC_FEATURE_EVENT_BINDING }, - { "input", IPC_FEATURE_EVENT_INPUT }, - }; - - uint32_t type = 0; - - for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) { - if (strcmp(types[i].name, argv[-1]) == 0) { - type = types[i].type; - break; - } - } - - if (enabled) { - current_policy->features |= type; - sway_log(L_DEBUG, "Enabled IPC %s event", argv[-1]); - } else { - current_policy->features &= ~type; - sway_log(L_DEBUG, "Disabled IPC %s event", argv[-1]); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/kill.c b/sway/old/commands/kill.c deleted file mode 100644 index 742e2b86b..000000000 --- a/sway/old/commands/kill.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/focus.h" - -struct cmd_results *cmd_kill(int argc, char **argv) { - if (config->reading) return cmd_results_new(CMD_FAILURE, "kill", "Can't be used in config file."); - if (!config->active) return cmd_results_new(CMD_FAILURE, "kill", "Can only be used when sway is running."); - - swayc_t *container = current_container; - close_views(container); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/layout.c b/sway/old/commands/layout.c deleted file mode 100644 index 57a865654..000000000 --- a/sway/old/commands/layout.c +++ /dev/null @@ -1,196 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/layout.h" - -/** - * handle "layout auto" command group - */ -static struct cmd_results *cmd_layout_auto(swayc_t *container, int argc, char **argv); - -struct cmd_results *cmd_layout(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "layout", "Can't be used in config file."); - if (!config->active) return cmd_results_new(CMD_FAILURE, "layout", "Can only be used when sway is running."); - if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { - return error; - } - swayc_t *parent = current_container; - if (parent->is_floating) { - return cmd_results_new(CMD_FAILURE, "layout", "Unable to change layout of floating windows"); - } - - while (parent->type == C_VIEW) { - parent = parent->parent; - } - - enum swayc_layouts old_layout = parent->layout; - - 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); - swayc_change_layout(parent, default_layout(output)); - } - } else { - if (parent->layout != L_TABBED && parent->layout != L_STACKED) { - parent->prev_layout = parent->layout; - } - - if (strcasecmp(argv[0], "tabbed") == 0) { - if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){ - parent = new_container(parent, L_TABBED); - } - - swayc_change_layout(parent, L_TABBED); - } else if (strcasecmp(argv[0], "stacking") == 0) { - if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)) { - parent = new_container(parent, L_STACKED); - } - - swayc_change_layout(parent, L_STACKED); - } else if (strcasecmp(argv[0], "splith") == 0) { - swayc_change_layout(parent, L_HORIZ); - } else if (strcasecmp(argv[0], "splitv") == 0) { - 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)) { - swayc_change_layout(parent, L_VERT); - } else { - swayc_change_layout(parent, L_HORIZ); - } - } else if (strcasecmp(argv[0], "auto") == 0) { - return cmd_layout_auto(parent, argc, argv); - } - } - - update_layout_geometry(parent, old_layout); - update_geometry(parent); - - arrange_windows(parent, parent->width, parent->height); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -static struct cmd_results *cmd_layout_auto(swayc_t *container, int argc, char **argv) { - // called after checking that argv[0] is auto, so just continue parsing from there - struct cmd_results *error = NULL; - const char *cmd_name = "layout auto"; - const char *set_inc_cmd_name = "layout auto [master|ncol] [set|inc]"; - const char *err_msg = "Allowed arguments are "; - - bool need_layout_update = false; - enum swayc_layouts old_layout = container->layout; - enum swayc_layouts layout = old_layout; - - if ((error = checkarg(argc, "layout auto", EXPECTED_MORE_THAN, 1))) { - return error; - } - - if (strcasecmp(argv[1], "left") == 0) { - layout = L_AUTO_LEFT; - } else if (strcasecmp(argv[1], "right") == 0) { - layout = L_AUTO_RIGHT; - } else if (strcasecmp(argv[1], "top") == 0) { - layout = L_AUTO_TOP; - } else if (strcasecmp(argv[1], "bottom") == 0) { - layout = L_AUTO_BOTTOM; - } else if (strcasecmp(argv[1], "next") == 0) { - if (is_auto_layout(container->layout) && container->layout < L_AUTO_LAST) { - layout = container->layout + 1; - } else { - layout = L_AUTO_FIRST; - } - } else if (strcasecmp(argv[1], "prev") == 0) { - if (is_auto_layout(container->layout) && container->layout > L_AUTO_FIRST) { - layout = container->layout - 1; - } else { - layout = L_AUTO_LAST; - } - } else { - bool is_nmaster; - bool is_set; - if (strcasecmp(argv[1], "master") == 0) { - is_nmaster = true; - } else if (strcasecmp(argv[1], "ncol") == 0) { - is_nmaster = false; - } else { - return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command. %s", - cmd_name, err_msg); - } - if ((error = checkarg(argc, "auto ", EXPECTED_EQUAL_TO, 4))) { - return error; - } - if (strcasecmp(argv[2], "set") == 0) { - is_set = true; - } else if (strcasecmp(argv[2], "inc") == 0) { - is_set = false; - } else { - return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command. %s, " - "Argument must be on of ", - set_inc_cmd_name); - } - char *end; - int n = (int)strtol(argv[3], &end, 10); - if (*end) { - return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command " - "(argument must be an integer)", set_inc_cmd_name); - } - if (is_auto_layout(container->layout)) { - int inc = 0; /* difference between current master/ncol and requested value */ - if (is_nmaster) { - if (is_set) { - if (n < 0) { - return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command " - "(master must be >= 0)", set_inc_cmd_name); - } - inc = n - (int)container->nb_master; - } else { /* inc command */ - if ((int)container->nb_master + n >= 0) { - inc = n; - } - } - if (inc) { - for (int i = container->nb_master; - i >= 0 && i < container->children->length - && i != (int)container->nb_master + inc;) { - ((swayc_t *)container->children->items[i])->height = -1; - ((swayc_t *)container->children->items[i])->width = -1; - i += inc > 0 ? 1 : -1; - } - container->nb_master += inc; - need_layout_update = true; - } - } else { /* ncol modification */ - if (is_set) { - if (n <= 0) { - return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command " - "(ncol must be > 0)", set_inc_cmd_name); - } - inc = n - (int)container->nb_slave_groups; - } else { /* inc command */ - if ((int)container->nb_slave_groups + n > 0) { - inc = n; - } - } - if (inc) { - container->nb_slave_groups += inc; - need_layout_update = true; - } - } - } - } - - if (layout != old_layout) { - swayc_change_layout(container, layout); - update_layout_geometry(container, old_layout); - need_layout_update = true; - } - if (need_layout_update) { - update_geometry(container); - arrange_windows(container, container->width, container->height); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/log_colors.c b/sway/old/commands/log_colors.c deleted file mode 100644 index 815d1942d..000000000 --- a/sway/old/commands/log_colors.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *cmd_log_colors(int argc, char **argv) { - struct cmd_results *error = NULL; - if (!config->reading) return cmd_results_new(CMD_FAILURE, "log_colors", "Can only be used in config file."); - if ((error = checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1))) { - return error; - } - if (strcasecmp(argv[0], "no") == 0) { - sway_log_colors(0); - } else if (strcasecmp(argv[0], "yes") == 0) { - sway_log_colors(1); - } else { - error = cmd_results_new(CMD_FAILURE, "log_colors", - "Invalid log_colors command (expected `yes` or `no`, got '%s')", argv[0]); - return error; - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/mark.c b/sway/old/commands/mark.c deleted file mode 100644 index c1d959df5..000000000 --- a/sway/old/commands/mark.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include -#include "sway/commands.h" -#include "list.h" -#include "stringop.h" - -static void find_marks_callback(swayc_t *container, void *_mark) { - char *mark = (char *)_mark; - - int index; - if (container->marks && ((index = list_seq_find(container->marks, (int (*)(const void *, const void *))strcmp, mark)) != -1)) { - list_del(container->marks, index); - } -} - -struct cmd_results *cmd_mark(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "mark", "Can't be used in config file."); - if ((error = checkarg(argc, "mark", EXPECTED_AT_LEAST, 1))) { - return error; - } - - swayc_t *view = current_container; - bool add = false; - bool toggle = false; - - if (strcmp(argv[0], "--add") == 0) { - --argc; ++argv; - add = true; - } else if (strcmp(argv[0], "--replace") == 0) { - --argc; ++argv; - } - - if (argc && strcmp(argv[0], "--toggle") == 0) { - --argc; ++argv; - toggle = true; - } - - if (argc) { - char *mark = join_args(argv, argc); - - // Remove all existing marks of this type - container_map(&root_container, find_marks_callback, mark); - - if (view->marks) { - if (add) { - int index; - if ((index = list_seq_find(view->marks, (int (*)(const void *, const void *))strcmp, mark)) != -1) { - if (toggle) { - free(view->marks->items[index]); - list_del(view->marks, index); - - if (0 == view->marks->length) { - list_free(view->marks); - view->marks = NULL; - } - } - free(mark); - } else { - list_add(view->marks, mark); - } - } else { - if (toggle && list_seq_find(view->marks, (int (*)(const void *, const void *))strcmp, mark) != -1) { - // Delete the list - list_foreach(view->marks, free); - list_free(view->marks); - view->marks = NULL; - } else { - // Delete and replace with a new list - list_foreach(view->marks, free); - list_free(view->marks); - - view->marks = create_list(); - list_add(view->marks, mark); - } - } - } else { - view->marks = create_list(); - list_add(view->marks, mark); - } - } else { - return cmd_results_new(CMD_FAILURE, "mark", - "Expected 'mark [--add|--replace] [--toggle] '"); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/mode.c b/sway/old/commands/mode.c deleted file mode 100644 index d2985c54d..000000000 --- a/sway/old/commands/mode.c +++ /dev/null @@ -1,57 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "sway/ipc-server.h" -#include "list.h" -#include "log.h" - -struct cmd_results *cmd_mode(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "mode", EXPECTED_AT_LEAST, 1))) { - return error; - } - - const char *mode_name = argv[0]; - bool mode_make = (argc == 2 && strcmp(argv[1], "{") == 0); - if (mode_make) { - if (!config->reading) - return cmd_results_new(CMD_FAILURE, "mode", "Can only be used in config file."); - } - struct sway_mode *mode = NULL; - // Find mode - int i, len = config->modes->length; - for (i = 0; i < len; ++i) { - struct sway_mode *find = config->modes->items[i]; - if (strcasecmp(find->name, mode_name) == 0) { - mode = find; - break; - } - } - // Create mode if it doesn't exist - if (!mode && mode_make) { - mode = malloc(sizeof(struct sway_mode)); - if (!mode) { - return cmd_results_new(CMD_FAILURE, "mode", "Unable to allocate mode"); - } - mode->name = strdup(mode_name); - mode->bindings = create_list(); - list_add(config->modes, mode); - } - if (!mode) { - error = cmd_results_new(CMD_INVALID, "mode", "Unknown mode `%s'", mode_name); - return error; - } - if ((config->reading && mode_make) || (!config->reading && !mode_make)) { - sway_log(L_DEBUG, "Switching to mode `%s'",mode->name); - } - // Set current mode - config->current_mode = mode; - if (!mode_make) { - // trigger IPC mode event - ipc_event_mode(config->current_mode->name); - } - return cmd_results_new(mode_make ? CMD_BLOCK_MODE : CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/mouse_warping.c b/sway/old/commands/mouse_warping.c deleted file mode 100644 index 5596d4836..000000000 --- a/sway/old/commands/mouse_warping.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_mouse_warping(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) { - return error; - } else if (strcasecmp(argv[0], "output") == 0) { - config->mouse_warping = true; - } else if (strcasecmp(argv[0], "none") == 0) { - config->mouse_warping = false; - } else { - return cmd_results_new(CMD_FAILURE, "mouse_warping", "Expected 'mouse_warping output|none'"); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/move.c b/sway/old/commands/move.c deleted file mode 100644 index 52c73e22c..000000000 --- a/sway/old/commands/move.c +++ /dev/null @@ -1,189 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/layout.h" -#include "sway/output.h" -#include "sway/workspace.h" -#include "list.h" -#include "stringop.h" - -struct cmd_results *cmd_move(int argc, char **argv) { - struct cmd_results *error = NULL; - int move_amt = 10; - - if (config->reading) return cmd_results_new(CMD_FAILURE, "move", "Can't be used in config file."); - if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { - return error; - } - const char* expected_syntax = "Expected 'move <[px] px>' or " - "'move to workspace ' or " - "'move to output ' or " - "'move position mouse'"; - swayc_t *view = current_container; - - if (argc == 2 || (argc == 3 && strcasecmp(argv[2], "px") == 0 )) { - char *inv; - move_amt = (int)strtol(argv[1], &inv, 10); - if (*inv != '\0' && strcasecmp(inv, "px") != 0) { - move_amt = 10; - } - } - - if (strcasecmp(argv[0], "left") == 0) { - move_container(view, MOVE_LEFT, move_amt); - } else if (strcasecmp(argv[0], "right") == 0) { - move_container(view, MOVE_RIGHT, move_amt); - } else if (strcasecmp(argv[0], "up") == 0) { - move_container(view, MOVE_UP, move_amt); - } else if (strcasecmp(argv[0], "down") == 0) { - move_container(view, MOVE_DOWN, move_amt); - } else if (strcasecmp(argv[0], "next") == 0) { - move_container(view, MOVE_NEXT, move_amt); - } else if (strcasecmp(argv[0], "prev") == 0) { - move_container(view, MOVE_PREV, move_amt); - } else if (strcasecmp(argv[0], "first") == 0) { - move_container(view, MOVE_FIRST, move_amt); - } else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) { - // "move container ... - if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) { - return error; - } else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "workspace") == 0) { - // move container to workspace x - if (view->type == C_WORKSPACE) { - if (!view->children || view->children->length == 0) { - return cmd_results_new(CMD_FAILURE, "move", "Cannot move an empty workspace"); - } - view = new_container(view, view->workspace_layout); - } if (view->type != C_CONTAINER && view->type != C_VIEW) { - return cmd_results_new(CMD_FAILURE, "move", "Can only move containers and views."); - } - - swayc_t *ws; - const char *num_name = NULL; - char *ws_name = NULL; - if (argc == 5 && strcasecmp(argv[3], "number") == 0) { - // move "container to workspace number x" - num_name = argv[4]; - ws = workspace_by_number(num_name); - } else { - ws_name = join_args(argv + 3, argc - 3); - ws = workspace_by_name(ws_name); - } - - if (ws == NULL) { - ws = workspace_create(ws_name ? ws_name : num_name); - } - if (ws_name) { - free(ws_name); - } - move_container_to(view, get_focused_container(ws)); - } else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "output") == 0) { - // move container to output x - swayc_t *output = NULL; - struct wlc_point abs_pos; - get_absolute_center_position(view, &abs_pos); - if (view->type == C_WORKSPACE) { - if (!view->children || view->children->length == 0) { - return cmd_results_new(CMD_FAILURE, "move", "Cannot move an empty workspace"); - } - view = new_container(view, view->workspace_layout); - } else if (view->type != C_CONTAINER && view->type != C_VIEW) { - return cmd_results_new(CMD_FAILURE, "move", "Can only move containers and views."); - } else if (!(output = output_by_name(argv[3], &abs_pos))) { - return cmd_results_new(CMD_FAILURE, "move", - "Can't find output with name/direction '%s' @ (%i,%i)", argv[3], abs_pos.x, abs_pos.y); - } - - swayc_t *container = get_focused_container(output); - if (container->is_floating) { - move_container_to(view, container->parent); - } else { - move_container_to(view, container); - } - } else { - return cmd_results_new(CMD_INVALID, "move", expected_syntax); - } - } else if (strcasecmp(argv[0], "workspace") == 0) { - // move workspace (to output x) - swayc_t *output = NULL; - struct wlc_point abs_pos; - get_absolute_center_position(view, &abs_pos); - if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) { - return error; - } else if (strcasecmp(argv[1], "to") != 0 || strcasecmp(argv[2], "output") != 0) { - return cmd_results_new(CMD_INVALID, "move", expected_syntax); - } else if (!(output = output_by_name(argv[3], &abs_pos))) { - return cmd_results_new(CMD_FAILURE, "move workspace", - "Can't find output with name/direction '%s' @ (%i,%i)", argv[3], abs_pos.x, abs_pos.y); - } - if (view->type == C_WORKSPACE) { - // This probably means we're moving an empty workspace, but - // that's fine. - move_workspace_to(view, output); - } else { - swayc_t *workspace = swayc_parent_by_type(view, C_WORKSPACE); - move_workspace_to(workspace, output); - } - } else if (strcasecmp(argv[0], "scratchpad") == 0 || (strcasecmp(argv[0], "to") == 0 && strcasecmp(argv[1], "scratchpad") == 0)) { - // move scratchpad ... - if (view->type != C_CONTAINER && view->type != C_VIEW) { - return cmd_results_new(CMD_FAILURE, "move scratchpad", "Can only move containers and views."); - } - swayc_t *view = current_container; - int i; - for (i = 0; i < scratchpad->length; i++) { - if (scratchpad->items[i] == view) { - hide_view_in_scratchpad(view); - sp_view = NULL; - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - } - list_add(scratchpad, view); - if (!view->is_floating) { - destroy_container(remove_child(view)); - } else { - remove_child(view); - } - wlc_view_set_mask(view->handle, 0); - arrange_windows(swayc_active_workspace(), -1, -1); - swayc_t *focused = container_under_pointer(); - if (focused == NULL) { - focused = swayc_active_workspace(); - } - set_focused_container(focused); - } else if (strcasecmp(argv[0], "position") == 0) { - if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 2))) { - return error; - } - if (strcasecmp(argv[1], "mouse")) { - return cmd_results_new(CMD_INVALID, "move", expected_syntax); - } - - if (view->is_floating) { - swayc_t *output = swayc_parent_by_type(view, C_OUTPUT); - struct wlc_geometry g; - wlc_view_get_visible_geometry(view->handle, &g); - const struct wlc_size *size = wlc_output_get_resolution(output->handle); - - double x_pos, y_pos; - wlc_pointer_get_position_v2(&x_pos, &y_pos); - - int32_t x = x_pos - g.size.w / 2; - int32_t y = y_pos - g.size.h / 2; - - uint32_t w = size->w - g.size.w; - uint32_t h = size->h - g.size.h; - - view->x = g.origin.x = MIN((int32_t)w, MAX(x, 0)); - view->y = g.origin.y = MIN((int32_t)h, MAX(y, 0)); - - wlc_view_set_geometry(view->handle, 0, &g); - } - } else { - return cmd_results_new(CMD_INVALID, "move", expected_syntax); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/new_float.c b/sway/old/commands/new_float.c deleted file mode 100644 index d0f960930..000000000 --- a/sway/old/commands/new_float.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "log.h" -#include "sway/commands.h" - -struct cmd_results *cmd_new_float(int argc, char **argv) { - sway_log(L_INFO, "`new_float` is deprecated and will be removed in the future. " - "Please use `default_floating_border` instead."); - return cmd_default_floating_border(argc, argv); -} diff --git a/sway/old/commands/new_window.c b/sway/old/commands/new_window.c deleted file mode 100644 index 574a45272..000000000 --- a/sway/old/commands/new_window.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "log.h" -#include "sway/commands.h" - -struct cmd_results *cmd_new_window(int argc, char **argv) { - sway_log(L_INFO, "`new_window` is deprecated and will be removed in the future. " - "Please use `default_border` instead."); - return cmd_default_border(argc, argv); -} diff --git a/sway/old/commands/no_focus.c b/sway/old/commands/no_focus.c deleted file mode 100644 index b3b88e5aa..000000000 --- a/sway/old/commands/no_focus.c +++ /dev/null @@ -1,41 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/commands.h" -#include "sway/criteria.h" -#include "list.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *cmd_no_focus(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "no_focus", EXPECTED_EQUAL_TO, 1))) { - return error; - } - // add command to a criteria/command pair that is run against views when they appear. - char *criteria = argv[0]; - - struct criteria *crit = malloc(sizeof(struct criteria)); - if (!crit) { - return cmd_results_new(CMD_FAILURE, "no_focus", "Unable to allocate criteria"); - } - crit->crit_raw = strdup(criteria); - crit->tokens = create_list(); - crit->cmdlist = NULL; - char *err_str = extract_crit_tokens(crit->tokens, crit->crit_raw); - - if (err_str) { - error = cmd_results_new(CMD_INVALID, "no_focus", err_str); - free(err_str); - free_criteria(crit); - } else if (crit->tokens->length == 0) { - error = cmd_results_new(CMD_INVALID, "no_focus", "Found no name/value pairs in criteria"); - free_criteria(crit); - } else if (list_seq_find(config->no_focus, criteria_cmp, crit) != -1) { - sway_log(L_DEBUG, "no_focus: Duplicate, skipping."); - free_criteria(crit); - } else { - sway_log(L_DEBUG, "no_focus: '%s' added", crit->crit_raw); - list_add(config->no_focus, crit); - } - return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/orientation.c b/sway/old/commands/orientation.c deleted file mode 100644 index e54b60ee5..000000000 --- a/sway/old/commands/orientation.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_orientation(int argc, char **argv) { - struct cmd_results *error = NULL; - if (!config->reading) return cmd_results_new(CMD_FAILURE, "orientation", "Can only be used in config file."); - if ((error = checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1))) { - return error; - } - if (strcasecmp(argv[0], "horizontal") == 0) { - config->default_orientation = L_HORIZ; - } else if (strcasecmp(argv[0], "vertical") == 0) { - config->default_orientation = L_VERT; - } else if (strcasecmp(argv[0], "auto") == 0) { - // Do nothing - } else { - return cmd_results_new(CMD_INVALID, "orientation", "Expected 'orientation '"); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/output.c b/sway/old/commands/output.c deleted file mode 100644 index 911391d2f..000000000 --- a/sway/old/commands/output.c +++ /dev/null @@ -1,219 +0,0 @@ -#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, "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, "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) (bg %s %s)", - output->name, output->enabled, output->width, - output->height, output->x, output->y, output->scale, - 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/old/commands/permit.c b/sway/old/commands/permit.c deleted file mode 100644 index 7a5e06f7c..000000000 --- a/sway/old/commands/permit.c +++ /dev/null @@ -1,108 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "sway/security.h" -#include "util.h" -#include "log.h" - -static enum secure_feature get_features(int argc, char **argv, - struct cmd_results **error) { - enum secure_feature features = 0; - - struct { - char *name; - enum secure_feature feature; - } feature_names[] = { - { "lock", FEATURE_LOCK }, - { "panel", FEATURE_PANEL }, - { "background", FEATURE_BACKGROUND }, - { "screenshot", FEATURE_SCREENSHOT }, - { "fullscreen", FEATURE_FULLSCREEN }, - { "keyboard", FEATURE_KEYBOARD }, - { "mouse", FEATURE_MOUSE }, - }; - - for (int i = 1; i < argc; ++i) { - size_t j; - for (j = 0; j < sizeof(feature_names) / sizeof(feature_names[0]); ++j) { - if (strcmp(feature_names[j].name, argv[i]) == 0) { - break; - } - } - if (j == sizeof(feature_names) / sizeof(feature_names[0])) { - *error = cmd_results_new(CMD_INVALID, - "permit", "Invalid feature grant %s", argv[i]); - return 0; - } - features |= feature_names[j].feature; - } - return features; -} - -struct cmd_results *cmd_permit(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "permit", EXPECTED_MORE_THAN, 1))) { - return error; - } - if ((error = check_security_config())) { - return error; - } - - bool assign_perms = true; - char *program = NULL; - - if (!strcmp(argv[0], "*")) { - program = strdup(argv[0]); - } else { - program = resolve_path(argv[0]); - } - if (!program) { - sway_assert(program, "Unable to resolve IPC permit target '%s'." - " will issue empty policy", argv[0]); - assign_perms = false; - program = strdup(argv[0]); - } - - struct feature_policy *policy = get_feature_policy(program); - if (policy && assign_perms) { - policy->features |= get_features(argc, argv, &error); - sway_log(L_DEBUG, "Permissions granted to %s for features %d", - policy->program, policy->features); - } - - free(program); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *cmd_reject(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "reject", EXPECTED_MORE_THAN, 1))) { - return error; - } - if ((error = check_security_config())) { - return error; - } - - char *program = NULL; - if (!strcmp(argv[0], "*")) { - program = strdup(argv[0]); - } else { - program = resolve_path(argv[0]); - } - if (!program) { - // Punt - sway_log(L_INFO, "Unable to resolve IPC reject target '%s'." - " Will use provided path", argv[0]); - program = strdup(argv[0]); - } - - struct feature_policy *policy = get_feature_policy(program); - policy->features &= ~get_features(argc, argv, &error); - - sway_log(L_DEBUG, "Permissions granted to %s for features %d", - policy->program, policy->features); - - free(program); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/reload.c b/sway/old/commands/reload.c deleted file mode 100644 index 01fcc5ba5..000000000 --- a/sway/old/commands/reload.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "sway/commands.h" -#include "sway/config.h" -#include "sway/layout.h" - -struct cmd_results *cmd_reload(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "reload", "Can't be used in config file."); - if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { - return error; - } - if (!load_main_config(config->current_config, true)) { - return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); - } - - load_swaybars(); - - arrange_windows(&root_container, -1, -1); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/resize.c b/sway/old/commands/resize.c deleted file mode 100644 index ef52bb077..000000000 --- a/sway/old/commands/resize.c +++ /dev/null @@ -1,375 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "sway/commands.h" -#include "sway/layout.h" -#include "sway/focus.h" -#include "sway/input_state.h" -#include "sway/handlers.h" -#include "log.h" - -enum resize_dim_types { - RESIZE_DIM_PX, - RESIZE_DIM_PPT, - RESIZE_DIM_DEFAULT, -}; - -static bool set_size_floating(int new_dimension, bool use_width) { - swayc_t *view = current_container; - if (view) { - if (use_width) { - int current_width = view->width; - view->desired_width = new_dimension; - floating_view_sane_size(view); - - int new_x = view->x + (int)(((view->desired_width - current_width) / 2) * -1); - view->width = view->desired_width; - view->x = new_x; - - update_geometry(view); - } else { - int current_height = view->height; - view->desired_height = new_dimension; - floating_view_sane_size(view); - - int new_y = view->y + (int)(((view->desired_height - current_height) / 2) * -1); - view->height = view->desired_height; - view->y = new_y; - - update_geometry(view); - } - - return true; - } - - return false; -} - -static bool resize_floating(int amount, bool use_width) { - swayc_t *view = current_container; - - if (view) { - if (use_width) { - return set_size_floating(view->width + amount, true); - } else { - return set_size_floating(view->height + amount, false); - } - } - - return false; -} - -static bool resize_tiled(int amount, bool use_width) { - swayc_t *container = current_container; - swayc_t *parent = container->parent; - int idx_focused = 0; - bool use_major = false; - size_t nb_before = 0; - size_t nb_after = 0; - - // 1. Identify a container ancestor that will allow the focused child to grow in the requested - // direction. - while (container->parent) { - parent = container->parent; - if ((parent->children && parent->children->length > 1) - && (is_auto_layout(parent->layout) - || (use_width ? parent->layout == L_HORIZ : parent->layout == L_VERT))) { - // check if container has siblings that can provide/absorb the space needed for - // the resize operation. - use_major = use_width - ? parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT - : parent->layout == L_AUTO_TOP || parent->layout == L_AUTO_BOTTOM; - // Note: use_major will be false for L_HORIZ and L_VERT - - idx_focused = index_child(container); - if (idx_focused < 0) { - sway_log(L_ERROR, "Something weird is happening, child container not " - "present in its parent's children list."); - continue; - } - if (use_major) { - nb_before = auto_group_index(parent, idx_focused); - nb_after = auto_group_count(parent) - nb_before - 1; - } else { - nb_before = idx_focused - auto_group_start_index(parent, idx_focused); - nb_after = auto_group_end_index(parent, idx_focused) - idx_focused - 1; - sway_log(L_DEBUG, "+++ focused: %d, start: %d, end: %d, before: %d, after: %d", - idx_focused, - (int)auto_group_start_index(parent, idx_focused), - (int)auto_group_end_index(parent, idx_focused), - (int)nb_before, (int)nb_after); - - } - if (nb_before || nb_after) { - break; - } - } - container = parent; /* continue up the tree to the next ancestor */ - } - if (parent == &root_container) { - return true; - } - sway_log(L_DEBUG, "Found the proper parent: %p. It has %zu before conts, " - "and %zu after conts", parent, nb_before, nb_after); - // 2. Ensure that the resize operation will not make one of the resized containers drop - // below the "sane" size threshold. - bool valid = true; - swayc_t *focused = parent->children->items[idx_focused]; - int start = use_major ? 0 : auto_group_start_index(parent, idx_focused); - int end = use_major ? parent->children->length : auto_group_end_index(parent, idx_focused); - sway_log(L_DEBUG, "Check children of container %p [%d,%d[", container, start, end); - for (int i = start; i < end; ) { - swayc_t *sibling = parent->children->items[i]; - double pixels = amount; - bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; - bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; - if (is_before || is_after) { - pixels = -pixels; - pixels /= is_before ? nb_before : nb_after; - if (nb_after != 0 && nb_before != 0) { - pixels /= 2; - } - } - sway_log(L_DEBUG, "Check container %p: width %g vs %d, height %g vs %d", sibling, sibling->width + pixels, min_sane_w, sibling->height + pixels, min_sane_h); - if (use_width ? - sibling->width + pixels < min_sane_w : - sibling->height + pixels < min_sane_h) { - valid = false; - sway_log(L_DEBUG, "Container size no longer sane"); - break; - } - i = use_major ? auto_group_end_index(parent, i) : (i + 1); - sway_log(L_DEBUG, "+++++ check %i", i); - } - // 3. Apply the size change - if (valid) { - for (int i = start; i < end; ) { - int next_i = use_major ? auto_group_end_index(parent, i) : (i + 1); - swayc_t *sibling = parent->children->items[i]; - double pixels = amount; - bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; - bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; - if (is_before || is_after) { - pixels = -pixels; - pixels /= is_before ? nb_before : nb_after; - if (nb_after != 0 && nb_before != 0) { - pixels /= 2; - } - sway_log(L_DEBUG, "%p: %s", sibling, is_before ? "before" : "after"); - if (use_major) { - for (int j = i; j < next_i; ++j) { - recursive_resize(parent->children->items[j], pixels, - use_width ? - (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : - (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); - } - } else { - recursive_resize(sibling, pixels, - use_width ? - (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : - (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); - } - } else { - if (use_major) { - for (int j = i; j < next_i; ++j) { - recursive_resize(parent->children->items[j], pixels / 2, - use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); - recursive_resize(parent->children->items[j], pixels / 2, - use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); - } - } else { - recursive_resize(sibling, pixels / 2, - use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); - recursive_resize(sibling, pixels / 2, - use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); - } - } - i = next_i; - } - // Recursive resize does not handle positions, let arrange_windows - // take care of that. - arrange_windows(swayc_active_workspace(), -1, -1); - } - return true; -} - -static bool set_size_tiled(int amount, bool use_width) { - int desired; - swayc_t *focused = current_container; - - if (use_width) { - desired = amount - focused->width; - } else { - desired = amount - focused->height; - } - - return resize_tiled(desired, use_width); -} - -static bool set_size(int dimension, bool use_width) { - swayc_t *focused = current_container; - - if (focused) { - if (focused->is_floating) { - return set_size_floating(dimension, use_width); - } else { - return set_size_tiled(dimension, use_width); - } - } - - return false; -} - -static bool resize(int dimension, bool use_width, enum resize_dim_types dim_type) { - swayc_t *focused = current_container; - - // translate "10 ppt" (10%) to appropriate # of pixels in case we need it - float ppt_dim = (float)dimension / 100; - - if (use_width) { - ppt_dim = focused->width * ppt_dim; - } else { - ppt_dim = focused->height * ppt_dim; - } - - if (focused) { - if (focused->is_floating) { - // floating view resize dimensions should default to px, so only - // use ppt if specified - if (dim_type == RESIZE_DIM_PPT) { - dimension = (int)ppt_dim; - } - - return resize_floating(dimension, use_width); - } else { - // tiled view resize dimensions should default to ppt, so only use - // px if specified - if (dim_type != RESIZE_DIM_PX) { - dimension = (int)ppt_dim; - } - - return resize_tiled(dimension, use_width); - } - } - - return false; -} - -static struct cmd_results *cmd_resize_set(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "resize set", EXPECTED_AT_LEAST, 2))) { - return error; - } - - if (strcasecmp(argv[0], "width") == 0 || strcasecmp(argv[0], "height") == 0) { - // handle `reset set width 100 px height 100 px` syntax, also allows - // specifying only one dimension for a `resize set` - int cmd_num = 0; - int dim; - - while ((cmd_num + 1) < argc) { - dim = (int)strtol(argv[cmd_num + 1], NULL, 10); - if (errno == ERANGE || dim == 0) { - errno = 0; - return cmd_results_new(CMD_INVALID, "resize set", - "Expected 'resize set [px] [ [px]]'"); - } - - if (strcasecmp(argv[cmd_num], "width") == 0) { - set_size(dim, true); - } else if (strcasecmp(argv[cmd_num], "height") == 0) { - set_size(dim, false); - } else { - return cmd_results_new(CMD_INVALID, "resize set", - "Expected 'resize set [px] [ [px]]'"); - } - - cmd_num += 2; - - if (cmd_num < argc && strcasecmp(argv[cmd_num], "px") == 0) { - // if this was `resize set width 400 px height 300 px`, disregard the `px` arg - cmd_num++; - } - } - } else { - // handle `reset set 100 px 100 px` syntax - int width = (int)strtol(argv[0], NULL, 10); - if (errno == ERANGE || width == 0) { - errno = 0; - return cmd_results_new(CMD_INVALID, "resize set", - "Expected 'resize set [px] [px]'"); - } - - int height_arg = 1; - if (strcasecmp(argv[1], "px") == 0) { - height_arg = 2; - } - - int height = (int)strtol(argv[height_arg], NULL, 10); - if (errno == ERANGE || height == 0) { - errno = 0; - return cmd_results_new(CMD_INVALID, "resize set", - "Expected 'resize set [px] [px]'"); - } - - set_size(width, true); - set_size(height, false); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *cmd_resize(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "resize", "Can't be used in config file."); - if (!config->active) return cmd_results_new(CMD_FAILURE, "resize", "Can only be used when sway is running."); - - if (strcasecmp(argv[0], "set") == 0) { - return cmd_resize_set(argc - 1, &argv[1]); - } - - if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { - return error; - } - - int dim_arg = argc - 1; - - enum resize_dim_types dim_type = RESIZE_DIM_DEFAULT; - if (strcasecmp(argv[dim_arg], "ppt") == 0) { - dim_type = RESIZE_DIM_PPT; - dim_arg--; - } else if (strcasecmp(argv[dim_arg], "px") == 0) { - dim_type = RESIZE_DIM_PX; - dim_arg--; - } - - int amount = (int)strtol(argv[dim_arg], NULL, 10); - if (errno == ERANGE || amount == 0) { - errno = 0; - amount = 10; // this is the default resize dimension used by i3 for both px and ppt - sway_log(L_DEBUG, "Tried to get resize dimension out of '%s' but failed; setting dimension to default %d", - argv[dim_arg], amount); - } - - bool use_width = false; - if (strcasecmp(argv[1], "width") == 0) { - use_width = true; - } else if (strcasecmp(argv[1], "height") != 0) { - return cmd_results_new(CMD_INVALID, "resize", - "Expected 'resize [] [px|ppt]'"); - } - - if (strcasecmp(argv[0], "shrink") == 0) { - amount *= -1; - } else if (strcasecmp(argv[0], "grow") != 0) { - return cmd_results_new(CMD_INVALID, "resize", - "Expected 'resize [] [px|ppt]'"); - } - - resize(amount, use_width, dim_type); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/scratchpad.c b/sway/old/commands/scratchpad.c deleted file mode 100644 index 6c5c92df2..000000000 --- a/sway/old/commands/scratchpad.c +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/focus.h" -#include "sway/layout.h" - -static swayc_t *fetch_view_from_scratchpad() { - sp_index = (sp_index + 1) % scratchpad->length; - swayc_t *view = scratchpad->items[sp_index]; - - if (wlc_view_get_output(view->handle) != swayc_active_output()->handle) { - wlc_view_set_output(view->handle, swayc_active_output()->handle); - } - if (!view->is_floating) { - view->width = swayc_active_workspace()->width * 0.5; - view->height = swayc_active_workspace()->height * 0.75; - view->x = (swayc_active_workspace()->width - view->width)/2; - view->y = (swayc_active_workspace()->height - view->height)/2; - } - if (swayc_active_workspace()->width < view->x + 20 || view->x + view->width < 20) { - view->x = (swayc_active_workspace()->width - view->width)/2; - } - if (swayc_active_workspace()->height < view->y + 20 || view->y + view->height < 20) { - view->y = (swayc_active_workspace()->height - view->height)/2; - } - - add_floating(swayc_active_workspace(), view); - wlc_view_set_mask(view->handle, VISIBLE); - view->visible = true; - arrange_windows(swayc_active_workspace(), -1, -1); - set_focused_container(view); - return view; -} - -struct cmd_results *cmd_scratchpad(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "scratchpad", "Can't be used in config file."); - if (!config->active) return cmd_results_new(CMD_FAILURE, "scratchpad", "Can only be used when sway is running."); - if ((error = checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (strcasecmp(argv[0], "show") == 0 && scratchpad->length > 0) { - if (!sp_view) { - if (current_container) { - // Haxor the scratchpad index if criteria'd - for (int i = 0; i < scratchpad->length; ++i) { - if (scratchpad->items[i] == current_container) { - sp_index = (i - 1) % scratchpad->length; - } - } - } - sp_view = fetch_view_from_scratchpad(); - } else { - if (swayc_active_workspace() != sp_view->parent) { - hide_view_in_scratchpad(sp_view); - if (sp_index == 0) { - sp_index = scratchpad->length; - } - sp_index--; - sp_view = fetch_view_from_scratchpad(); - } else { - hide_view_in_scratchpad(sp_view); - sp_view = NULL; - } - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - return cmd_results_new(CMD_FAILURE, "scratchpad", "Expected 'scratchpad show' when scratchpad is not empty."); -} diff --git a/sway/old/commands/seamless_mouse.c b/sway/old/commands/seamless_mouse.c deleted file mode 100644 index 7760e88d0..000000000 --- a/sway/old/commands/seamless_mouse.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_seamless_mouse(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "seamless_mouse", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - config->seamless_mouse = (strcasecmp(argv[0], "on") == 0 || strcasecmp(argv[0], "yes") == 0); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/set.c b/sway/old/commands/set.c deleted file mode 100644 index 46fc6d388..000000000 --- a/sway/old/commands/set.c +++ /dev/null @@ -1,61 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "list.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); -} - -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/old/commands/show_marks.c b/sway/old/commands/show_marks.c deleted file mode 100644 index ed56d9e50..000000000 --- a/sway/old/commands/show_marks.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_show_marks(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "show_marks", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - config->show_marks = !strcasecmp(argv[0], "on"); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/smart_gaps.c b/sway/old/commands/smart_gaps.c deleted file mode 100644 index 815fc501b..000000000 --- a/sway/old/commands/smart_gaps.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_smart_gaps(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "smart_gaps", EXPECTED_EQUAL_TO, 1))) { - return error; - } - - if (strcasecmp(argv[0], "on") == 0) { - config->smart_gaps = true; - } else if (strcasecmp(argv[0], "off") == 0) { - config->smart_gaps = false; - } else { - return cmd_results_new(CMD_INVALID, "smart_gaps", "Expected 'smart_gaps '"); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/split.c b/sway/old/commands/split.c deleted file mode 100644 index e3045a4f0..000000000 --- a/sway/old/commands/split.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include "sway/border.h" -#include "sway/commands.h" -#include "sway/container.h" -#include "sway/focus.h" -#include "sway/layout.h" -#include "log.h" - -static struct cmd_results *_do_split(int argc, char **argv, int layout) { - char *name = layout == L_VERT ? "splitv" : - layout == L_HORIZ ? "splith" : "split"; - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, name, "Can't be used in config file."); - if (!config->active) return cmd_results_new(CMD_FAILURE, name, "Can only be used when sway is running."); - if ((error = checkarg(argc, name, EXPECTED_EQUAL_TO, 0))) { - return error; - } - swayc_t *focused = current_container; - - // Case of floating window, don't split - if (focused->is_floating) { - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - /* Case that focus is on an workspace with 0/1 children.change its layout */ - if (focused->type == C_WORKSPACE && focused->children->length <= 1) { - sway_log(L_DEBUG, "changing workspace layout"); - swayc_change_layout(focused, layout); - } else if (focused->type != C_WORKSPACE && focused->parent->children->length == 1) { - /* Case of no siblings. change parent layout */ - sway_log(L_DEBUG, "changing container layout"); - swayc_change_layout(focused->parent, layout); - } else { - /* regular case where new split container is build around focused container - * or in case of workspace, container inherits its children */ - sway_log(L_DEBUG, "Adding new container around current focused container"); - sway_log(L_INFO, "FOCUSED SIZE: %.f %.f", focused->width, focused->height); - swayc_t *parent = new_container(focused, layout); - set_focused_container(focused); - arrange_windows(parent, -1, -1); - } - - // update container every time - // if it is tabbed/stacked then the title must change - // if the indicator color is different then the border must change - update_container_border(focused); - swayc_t *output = swayc_parent_by_type(focused, C_OUTPUT); - // schedule render to make changes take effect right away, - // otherwise we would have to wait for the view to render, - // which is unpredictable. - wlc_output_schedule_render(output->handle); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *cmd_split(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "split", "Can't be used in config file."); - if (!config->active) return cmd_results_new(CMD_FAILURE, "split", "Can only be used when sway is running."); - if ((error = checkarg(argc, "split", EXPECTED_EQUAL_TO, 1))) { - return error; - } - if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { - _do_split(argc - 1, argv + 1, L_VERT); - } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { - _do_split(argc - 1, argv + 1, L_HORIZ); - } else if (strcasecmp(argv[0], "t") == 0 || strcasecmp(argv[0], "toggle") == 0) { - swayc_t *focused = current_container; - if (focused->parent->layout == L_VERT) { - _do_split(argc - 1, argv + 1, L_HORIZ); - } else { - _do_split(argc - 1, argv + 1, L_VERT); - } - } else { - error = cmd_results_new(CMD_FAILURE, "split", - "Invalid split command (expected either horizontal or vertical)."); - return error; - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} - -struct cmd_results *cmd_splitv(int argc, char **argv) { - return _do_split(argc, argv, L_VERT); -} - -struct cmd_results *cmd_splith(int argc, char **argv) { - return _do_split(argc, argv, L_HORIZ); -} - -struct cmd_results *cmd_splitt(int argc, char **argv) { - swayc_t *focused = current_container; - if (focused->parent->layout == L_VERT) { - return _do_split(argc, argv, L_HORIZ); - } else { - return _do_split(argc, argv, L_VERT); - } -} diff --git a/sway/old/commands/sticky.c b/sway/old/commands/sticky.c deleted file mode 100644 index 4899e061a..000000000 --- a/sway/old/commands/sticky.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include "sway/commands.h" -#include "sway/focus.h" - -struct cmd_results *cmd_sticky(int argc, char **argv) { - struct cmd_results *error = NULL; - if (config->reading) return cmd_results_new(CMD_FAILURE, "sticky", "Can't be used in config file."); - if (!config->active) return cmd_results_new(CMD_FAILURE, "sticky", "Can only be used when sway is running."); - if ((error = checkarg(argc, "sticky", EXPECTED_EQUAL_TO, 1))) { - return error; - } - char *action = argv[0]; - swayc_t *cont = get_focused_view(&root_container); - if (strcmp(action, "toggle") == 0) { - cont->sticky = !cont->sticky; - } else if (strcmp(action, "enable") == 0) { - cont->sticky = true; - } else if (strcmp(action, "disable") == 0) { - cont->sticky = false; - } else { - return cmd_results_new(CMD_FAILURE, "sticky", - "Expected 'sticky enable|disable|toggle'"); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/unmark.c b/sway/old/commands/unmark.c deleted file mode 100644 index ac2132613..000000000 --- a/sway/old/commands/unmark.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include "sway/commands.h" -#include "list.h" -#include "stringop.h" - -struct cmd_results *cmd_unmark(int argc, char **argv) { - swayc_t *view = current_container; - - if (view->marks) { - if (argc) { - char *mark = join_args(argv, argc); - int index; - if ((index = list_seq_find(view->marks, (int (*)(const void *, const void *))strcmp, mark)) != -1) { - free(view->marks->items[index]); - list_del(view->marks, index); - - if (view->marks->length == 0) { - list_free(view->marks); - view->marks = NULL; - } - } - free(mark); - } else { - list_foreach(view->marks, free); - list_free(view->marks); - view->marks = NULL; - } - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/workspace.c b/sway/old/commands/workspace.c deleted file mode 100644 index a78397466..000000000 --- a/sway/old/commands/workspace.c +++ /dev/null @@ -1,92 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include "sway/commands.h" -#include "sway/config.h" -#include "sway/input_state.h" -#include "sway/workspace.h" -#include "list.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *cmd_workspace(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) { - return error; - } - - int output_location = -1; - - for (int i = 0; i < argc; ++i) { - if (strcasecmp(argv[i], "output") == 0) { - output_location = i; - break; - } - } - if (output_location >= 0) { - if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { - return error; - } - struct workspace_output *wso = calloc(1, sizeof(struct workspace_output)); - if (!wso) { - return cmd_results_new(CMD_FAILURE, "workspace output", - "Unable to allocate workspace output"); - } - wso->workspace = join_args(argv, argc - 2); - wso->output = strdup(argv[output_location + 1]); - int i = -1; - if ((i = list_seq_find(config->workspace_outputs, workspace_output_cmp_workspace, wso)) != -1) { - struct workspace_output *old = config->workspace_outputs->items[i]; - free(old); // workspaces can only be assigned to a single output - list_del(config->workspace_outputs, i); - } - sway_log(L_DEBUG, "Assigning workspace %s to output %s", wso->workspace, wso->output); - list_add(config->workspace_outputs, wso); - } else { - if (config->reading || !config->active) { - return cmd_results_new(CMD_DEFER, "workspace", 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); - ws = workspace_create(name); - free(name); - } - } else if (strcasecmp(argv[0], "next") == 0) { - ws = workspace_next(); - } else if (strcasecmp(argv[0], "prev") == 0) { - ws = workspace_prev(); - } else if (strcasecmp(argv[0], "next_on_output") == 0) { - ws = workspace_output_next(); - } else if (strcasecmp(argv[0], "prev_on_output") == 0) { - ws = workspace_output_prev(); - } else if (strcasecmp(argv[0], "back_and_forth") == 0) { - // if auto_back_and_forth is enabled, workspace_switch will swap - // the workspaces. If we created prev_workspace here, workspace_switch - // would put us back on original workspace. - if (config->auto_back_and_forth) { - ws = swayc_active_workspace(); - } else if (prev_workspace_name && !(ws = workspace_by_name(prev_workspace_name))) { - ws = workspace_create(prev_workspace_name); - } - } else { - char *name = join_args(argv, argc); - if (!(ws = workspace_by_name(name))) { - ws = workspace_create(name); - } - free(name); - } - swayc_t *old_output = swayc_active_output(); - workspace_switch(ws); - swayc_t *new_output = swayc_active_output(); - - if (config->mouse_warping && old_output != new_output) { - swayc_t *focused = get_focused_view(ws); - if (focused && focused->type == C_VIEW) { - center_pointer_on(focused); - } - } - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/workspace_auto_back_and_forth.c b/sway/old/commands/workspace_auto_back_and_forth.c deleted file mode 100644 index d58ae5c84..000000000 --- a/sway/old/commands/workspace_auto_back_and_forth.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1))) { - return error; - } - if (strcasecmp(argv[0], "yes") == 0) { - config->auto_back_and_forth = true; - } else if (strcasecmp(argv[0], "no") == 0) { - config->auto_back_and_forth = false; - } else { - return cmd_results_new(CMD_INVALID, "workspace_auto_back_and_forth", "Expected 'workspace_auto_back_and_forth '"); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/commands/workspace_layout.c b/sway/old/commands/workspace_layout.c deleted file mode 100644 index 9ac84be23..000000000 --- a/sway/old/commands/workspace_layout.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include "sway/commands.h" - -struct cmd_results *cmd_workspace_layout(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "workspace_layout", EXPECTED_AT_LEAST, 1))) { - return error; - } - - if (strcasecmp(argv[0], "default") == 0) { - config->default_layout = L_NONE; - } else if (strcasecmp(argv[0], "stacking") == 0) { - config->default_layout = L_STACKED; - } else if (strcasecmp(argv[0], "tabbed") == 0) { - config->default_layout = L_TABBED; - } else if (strcasecmp(argv[0], "auto") == 0) { - if (argc == 1) { - config->default_layout = L_AUTO_FIRST; - } else { - if ((error = checkarg(argc, "workspace_layout auto", EXPECTED_EQUAL_TO, 2))) { - return error; - } - if (strcasecmp(argv[1], "left") == 0) { - config->default_layout = L_AUTO_LEFT; - } else if (strcasecmp(argv[1], "right") == 0) { - config->default_layout = L_AUTO_RIGHT; - } else if (strcasecmp(argv[1], "top") == 0) { - config->default_layout = L_AUTO_TOP; - } else if (strcasecmp(argv[1], "bottom") == 0) { - config->default_layout = L_AUTO_BOTTOM; - } else { - return cmd_results_new(CMD_INVALID, "workspace_layout auto", "Expected 'workspace_layout auto '"); - } - } - } else { - return cmd_results_new(CMD_INVALID, "workspace_layout", "Expected 'workspace_layout '"); - } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/old/config.c b/sway/old/config.c deleted file mode 100644 index d14653e30..000000000 --- a/sway/old/config.c +++ /dev/null @@ -1,1313 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "wayland-desktop-shell-server-protocol.h" -#include "sway/commands.h" -#include "sway/config.h" -#include "sway/layout.h" -#include "sway/input_state.h" -#include "sway/criteria.h" -#include "sway/input.h" -#include "sway/border.h" -#include "readline.h" -#include "stringop.h" -#include "list.h" -#include "log.h" - -struct sway_config *config = NULL; - -static void terminate_swaybar(pid_t pid); - -static void free_variable(struct sway_variable *var) { - if (!var) { - return; - } - free(var->name); - free(var->value); - free(var); -} - -static void free_binding(struct sway_binding *bind) { - if (!bind) { - return; - } - free_flat_list(bind->keys); - free(bind->command); - free(bind); -} - -static void free_mode(struct sway_mode *mode) { - if (!mode) { - return; - } - free(mode->name); - int i; - for (i = 0; mode->bindings && i < mode->bindings->length; ++i) { - free_binding(mode->bindings->items[i]); - } - list_free(mode->bindings); - free(mode); -} - -static void free_bar(struct bar_config *bar) { - if (!bar) { - return; - } - free(bar->mode); - free(bar->hidden_state); -#ifdef ENABLE_TRAY - free(bar->tray_output); - free(bar->icon_theme); -#endif - free(bar->status_command); - free(bar->font); - free(bar->separator_symbol); - int i; - for (i = 0; bar->bindings && i < bar->bindings->length; ++i) { - free_sway_mouse_binding(bar->bindings->items[i]); - } - list_free(bar->bindings); - - if (bar->outputs) { - free_flat_list(bar->outputs); - } - - if (bar->pid != 0) { - 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); -} - -void free_input_config(struct input_config *ic) { - if (!ic) { - return; - } - free(ic->identifier); - free(ic); -} - -void free_output_config(struct output_config *oc) { - if (!oc) { - return; - } - free(oc->name); - free(oc->background); - free(oc->background_option); - free(oc); -} - -static void free_workspace_output(struct workspace_output *wo) { - if (!wo) { - return; - } - free(wo->output); - free(wo->workspace); - free(wo); -} - -static void pid_workspace_cleanup() { - struct timespec ts; - struct pid_workspace *pw = NULL; - - clock_gettime(CLOCK_MONOTONIC, &ts); - - // work backwards through list and remove any entries - // older than PID_WORKSPACE_TIMEOUT - for (int i = config->pid_workspaces->length - 1; i > -1; i--) { - pw = config->pid_workspaces->items[i]; - - if (difftime(ts.tv_sec, *pw->time_added) >= PID_WORKSPACE_TIMEOUT) { - free_pid_workspace(config->pid_workspaces->items[i]); - list_del(config->pid_workspaces, i); - } - } -} - -// de-dupe pid_workspaces to ensure pid uniqueness -void pid_workspace_add(struct pid_workspace *pw) { - struct pid_workspace *list_pw = NULL; - struct timespec ts; - time_t *now = malloc(sizeof(time_t)); - if (!now) { - sway_log(L_ERROR, "Allocating time for pid_workspace failed"); - return; - } - - pid_workspace_cleanup(); - - // add current time to pw - clock_gettime(CLOCK_MONOTONIC, &ts); - *now = ts.tv_sec; - - pw->time_added = now; - - // work backwards through list and delete any entries that - // have the same pid as that in our new pid_workspace - for (int i = config->pid_workspaces->length - 1; i > -1; i--) { - list_pw = config->pid_workspaces->items[i]; - - if (pw->pid == list_pw->pid) { - free_pid_workspace(config->pid_workspaces->items[i]); - list_del(config->pid_workspaces, i); - } - } - - list_add(config->pid_workspaces, pw); -} - -void free_pid_workspace(struct pid_workspace *pw) { - if (!pw) { - return; - } - free(pw->pid); - free(pw->workspace); - free(pw->time_added); - free(pw); -} - -void free_command_policy(struct command_policy *policy) { - if (!policy) { - return; - } - free(policy->command); - free(policy); -} - -void free_feature_policy(struct feature_policy *policy) { - if (!policy) { - return; - } - free(policy->program); - free(policy); -} - -void free_config(struct sway_config *config) { - if (!config) { - return; - } - int i; - for (i = 0; config->symbols && i < config->symbols->length; ++i) { - free_variable(config->symbols->items[i]); - } - list_free(config->symbols); - - for (i = 0; config->modes && i < config->modes->length; ++i) { - free_mode(config->modes->items[i]); - } - list_free(config->modes); - - for (i = 0; config->bars && i < config->bars->length; ++i) { - free_bar(config->bars->items[i]); - } - list_free(config->bars); - - free_flat_list(config->cmd_queue); - - for (i = 0; config->workspace_outputs && i < config->workspace_outputs->length; ++i) { - free_workspace_output(config->workspace_outputs->items[i]); - } - list_free(config->workspace_outputs); - - for (i = 0; config->pid_workspaces && i < config->pid_workspaces->length; ++i) { - free_pid_workspace(config->pid_workspaces->items[i]); - } - list_free(config->pid_workspaces); - - for (i = 0; config->criteria && i < config->criteria->length; ++i) { - free_criteria(config->criteria->items[i]); - } - list_free(config->criteria); - - for (i = 0; config->no_focus && i < config->no_focus->length; ++i) { - free_criteria(config->no_focus->items[i]); - } - list_free(config->no_focus); - - for (i = 0; config->input_configs && i < config->input_configs->length; ++i) { - free_input_config(config->input_configs->items[i]); - } - list_free(config->input_configs); - - for (i = 0; config->output_configs && i < config->output_configs->length; ++i) { - free_output_config(config->output_configs->items[i]); - } - list_free(config->output_configs); - - for (i = 0; config->command_policies && i < config->command_policies->length; ++i) { - free_command_policy(config->command_policies->items[i]); - } - list_free(config->command_policies); - - for (i = 0; config->feature_policies && i < config->feature_policies->length; ++i) { - free_feature_policy(config->feature_policies->items[i]); - } - list_free(config->feature_policies); - - list_free(config->active_bar_modifiers); - free_flat_list(config->config_chain); - free(config->font); - free(config->floating_scroll_up_cmd); - free(config->floating_scroll_down_cmd); - free(config->floating_scroll_left_cmd); - free(config->floating_scroll_right_cmd); - free(config); -} - - -static bool file_exists(const char *path) { - return path && access(path, R_OK) != -1; -} - -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 = M_LEFT_CLICK; - config->resizing_key = M_RIGHT_CLICK; - 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; - 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 int compare_modifiers(const void *left, const void *right) { - uint32_t a = *(uint32_t *)left; - uint32_t b = *(uint32_t *)right; - - return a - b; -} - -void update_active_bar_modifiers() { - if (config->active_bar_modifiers->length > 0) { - list_free(config->active_bar_modifiers); - config->active_bar_modifiers = create_list(); - } - - struct bar_config *bar; - int i; - for (i = 0; i < config->bars->length; ++i) { - bar = config->bars->items[i]; - if (strcmp(bar->mode, "hide") == 0 && strcmp(bar->hidden_state, "hide") == 0) { - if (list_seq_find(config->active_bar_modifiers, compare_modifiers, &bar->modifier) < 0) { - list_add(config->active_bar_modifiers, &bar->modifier); - } - } - } -} - -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) { - input_init(); - - 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) { - update_active_bar_modifiers(); - } - - return success; -} - -static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { - // save parent config - const char *parent_config = config->current_config; - - char *full_path = strdup(path); - int len = strlen(path); - if (len >= 1 && path[0] != '/') { - len = len + strlen(parent_dir) + 2; - full_path = malloc(len * sizeof(char)); - if (!full_path) { - sway_log(L_ERROR, "Unable to allocate full path to included config"); - return false; - } - snprintf(full_path, len, "%s/%s", parent_dir, path); - } - - char *real_path = realpath(full_path, NULL); - free(full_path); - - if (real_path == NULL) { - sway_log(L_DEBUG, "%s not found.", path); - return false; - } - - // check if config has already been included - int j; - for (j = 0; j < config->config_chain->length; ++j) { - char *old_path = config->config_chain->items[j]; - if (strcmp(real_path, old_path) == 0) { - sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path); - free(real_path); - return false; - } - } - - config->current_config = real_path; - list_add(config->config_chain, real_path); - int index = config->config_chain->length - 1; - - if (!load_config(real_path, config)) { - free(real_path); - config->current_config = parent_config; - list_del(config->config_chain, index); - return false; - } - - // restore current_config - config->current_config = parent_config; - return true; -} - -bool load_include_configs(const char *path, struct sway_config *config) { - char *wd = getcwd(NULL, 0); - char *parent_path = strdup(config->current_config); - const char *parent_dir = dirname(parent_path); - - if (chdir(parent_dir) < 0) { - free(parent_path); - free(wd); - return false; - } - - wordexp_t p; - - if (wordexp(path, &p, 0) < 0) { - free(parent_path); - free(wd); - return false; - } - - char **w = p.we_wordv; - size_t i; - for (i = 0; i < p.we_wordc; ++i) { - load_include_config(w[i], parent_dir, config); - } - free(parent_path); - wordfree(&p); - - // restore wd - if (chdir(wd) < 0) { - free(wd); - sway_log(L_ERROR, "failed to restore working directory"); - return false; - } - - free(wd); - return true; -} - -struct cmd_results *check_security_config() { - if (!current_config_path || strncmp(SYSCONFDIR "/sway/security.d/", current_config_path, - strlen(SYSCONFDIR "/sway/security.d/")) != 0) { - return cmd_results_new(CMD_INVALID, "permit", - "This command is only permitted to run from " SYSCONFDIR "/sway/security.d/*"); - } - return NULL; -} - -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"); - 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; -} - -int input_identifier_cmp(const void *item, const void *data) { - const struct input_config *ic = item; - const char *identifier = data; - return strcmp(ic->identifier, identifier); -} - -int output_name_cmp(const void *item, const void *data) { - const struct output_config *output = item; - const char *name = data; - - return strcmp(output->name, name); -} - -void merge_input_config(struct input_config *dst, struct input_config *src) { - if (src->identifier) { - if (dst->identifier) { - free(dst->identifier); - } - dst->identifier = strdup(src->identifier); - } - if (src->accel_profile != INT_MIN) { - dst->accel_profile = src->accel_profile; - } - if (src->click_method != INT_MIN) { - dst->click_method = src->click_method; - } - if (src->drag_lock != INT_MIN) { - dst->drag_lock = src->drag_lock; - } - if (src->dwt != INT_MIN) { - dst->dwt = src->dwt; - } - if (src->middle_emulation != INT_MIN) { - dst->middle_emulation = src->middle_emulation; - } - if (src->natural_scroll != INT_MIN) { - dst->natural_scroll = src->natural_scroll; - } - if (src->pointer_accel != FLT_MIN) { - dst->pointer_accel = src->pointer_accel; - } - if (src->scroll_method != INT_MIN) { - dst->scroll_method = src->scroll_method; - } - if (src->send_events != INT_MIN) { - dst->send_events = src->send_events; - } - if (src->tap != INT_MIN) { - dst->tap = src->tap; - } -} - -void merge_output_config(struct output_config *dst, struct output_config *src) { - 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 invoke_swaybar(struct bar_config *bar) { - return; // TODO WLR - sway_log(L_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); - // Pipe to communicate errors - int filedes[2]; - if (pipe(filedes) == -1) { - sway_log(L_ERROR, "Pipe setup failed! Cannot fork into bar"); - return; - } - - bar->pid = fork(); - if (bar->pid == 0) { - close(filedes[0]); - if (!bar->swaybar_command) { - char *const cmd[] = { - "swaybar", - "-b", - bar->id, - NULL, - }; - - close(filedes[1]); - execvp(cmd[0], cmd); - _exit(EXIT_SUCCESS); - } else { - // run custom swaybar - int len = strlen(bar->swaybar_command) + strlen(bar->id) + 5; - char *command = malloc(len * sizeof(char)); - if (!command) { - const char msg[] = "Unable to allocate swaybar command string"; - int len = sizeof(msg); - if (write(filedes[1], &len, sizeof(int))) {}; - if (write(filedes[1], msg, len)) {}; - close(filedes[1]); - _exit(EXIT_FAILURE); - } - snprintf(command, len, "%s -b %s", bar->swaybar_command, bar->id); - - char *const cmd[] = { - "sh", - "-c", - command, - NULL, - }; - - close(filedes[1]); - execvp(cmd[0], cmd); - free(command); - _exit(EXIT_SUCCESS); - } - } - close(filedes[0]); - int len; - if(read(filedes[1], &len, sizeof(int)) == sizeof(int)) { - char *buf = malloc(len); - if(!buf) { - sway_log(L_ERROR, "Cannot allocate error string"); - return; - } - if(read(filedes[1], buf, len)) { - sway_log(L_ERROR, "%s", buf); - } - free(buf); - } - close(filedes[1]); -} - -static void terminate_swaybar(pid_t pid) { - return; // TODO WLR - int ret = kill(pid, SIGTERM); - if (ret != 0) { - sway_log(L_ERROR, "Unable to terminate swaybar [pid: %d]", pid); - } else { - int status; - waitpid(pid, &status, 0); - } -} - -void terminate_swaybg(pid_t pid) { - int ret = kill(pid, SIGTERM); - if (ret != 0) { - sway_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid); - } else { - int status; - waitpid(pid, &status, 0); - } -} - -static bool active_output(const char *name) { - int i; - swayc_t *cont = NULL; - for (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() { - // Check for bars - list_t *bars = create_list(); - struct bar_config *bar = NULL; - int i; - for (i = 0; i < config->bars->length; ++i) { - bar = config->bars->items[i]; - bool apply = false; - if (bar->outputs) { - int j; - for (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) { - list_add(bars, bar); - } - } - - for (i = 0; i < bars->length; ++i) { - bar = bars->items[i]; - if (bar->pid != 0) { - terminate_swaybar(bar->pid); - } - invoke_swaybar(bar); - } - - list_free(bars); -} - -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; -} - -// the naming is intentional (albeit long): a workspace_output_cmp function -// would compare two structs in full, while this method only compares the -// workspace. -int workspace_output_cmp_workspace(const void *a, const void *b) { - const struct workspace_output *wsa = a, *wsb = b; - return lenient_strcmp(wsa->workspace, wsb->workspace); -} - -int sway_binding_cmp_keys(const void *a, const void *b) { - const struct sway_binding *binda = a, *bindb = b; - - // Count keys pressed for this binding. important so we check long before - // short ones. for example mod+a+b before mod+a - unsigned int moda = 0, modb = 0, i; - - // Count how any modifiers are pressed - for (i = 0; i < 8 * sizeof(binda->modifiers); ++i) { - moda += (binda->modifiers & 1 << i) != 0; - modb += (bindb->modifiers & 1 << i) != 0; - } - if (bindb->keys->length + modb != binda->keys->length + moda) { - return (bindb->keys->length + modb) - (binda->keys->length + moda); - } - - // Otherwise compare keys - if (binda->modifiers > bindb->modifiers) { - return 1; - } else if (binda->modifiers < bindb->modifiers) { - return -1; - } - struct wlc_modifiers no_mods = { 0, 0 }; - for (int i = 0; i < binda->keys->length; i++) { - xkb_keysym_t ka = *(xkb_keysym_t *)binda->keys->items[i], - kb = *(xkb_keysym_t *)bindb->keys->items[i]; - if (binda->bindcode) { - uint32_t *keycode = binda->keys->items[i]; - ka = wlc_keyboard_get_keysym_for_key(*keycode, &no_mods); - } - - if (bindb->bindcode) { - uint32_t *keycode = bindb->keys->items[i]; - kb = wlc_keyboard_get_keysym_for_key(*keycode, &no_mods); - } - - if (ka > kb) { - return 1; - } else if (ka < kb) { - return -1; - } - } - - return 0; -} - -int sway_binding_cmp(const void *a, const void *b) { - int cmp = 0; - if ((cmp = sway_binding_cmp_keys(a, b)) != 0) { - return cmp; - } - const struct sway_binding *binda = a, *bindb = b; - return lenient_strcmp(binda->command, bindb->command); -} - -int sway_binding_cmp_qsort(const void *a, const void *b) { - return sway_binding_cmp(*(void **)a, *(void **)b); -} - -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); -} - -int sway_mouse_binding_cmp_buttons(const void *a, const void *b) { - const struct sway_mouse_binding *binda = a, *bindb = b; - if (binda->button > bindb->button) { - return 1; - } - if (binda->button < bindb->button) { - return -1; - } - return 0; -} - -int sway_mouse_binding_cmp(const void *a, const void *b) { - int cmp = 0; - if ((cmp = sway_binding_cmp_keys(a, b)) != 0) { - return cmp; - } - const struct sway_mouse_binding *binda = a, *bindb = b; - return lenient_strcmp(binda->command, bindb->command); -} - -int sway_mouse_binding_cmp_qsort(const void *a, const void *b) { - return sway_mouse_binding_cmp(*(void **)a, *(void **)b); -} - -void free_sway_mouse_binding(struct sway_mouse_binding *binding) { - if (binding->command) { - free(binding->command); - } - free(binding); -} - -struct sway_binding *sway_binding_dup(struct sway_binding *sb) { - struct sway_binding *new_sb = malloc(sizeof(struct sway_binding)); - if (!new_sb) { - return NULL; - } - - new_sb->order = sb->order; - new_sb->modifiers = sb->modifiers; - new_sb->command = strdup(sb->command); - - new_sb->keys = create_list(); - int i; - for (i = 0; i < sb->keys->length; ++i) { - xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); - if (!key) { - free_sway_binding(new_sb); - return NULL; - } - *key = *(xkb_keysym_t *)sb->keys->items[i]; - list_add(new_sb->keys, key); - } - - return new_sb; -} - -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->modifier = WLC_BIT_MOD_LOGO; - bar->outputs = NULL; - bar->position = DESKTOP_SHELL_PANEL_POSITION_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; -#ifdef ENABLE_TRAY - bar->tray_output = NULL; - bar->icon_theme = NULL; - bar->tray_padding = 2; - bar->activate_button = 0x110; /* BTN_LEFT */ - bar->context_button = 0x111; /* BTN_RIGHT */ - bar->secondary_button = 0x112; /* BTN_MIDDLE */ -#endif - 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; -} diff --git a/sway/old/container.c b/sway/old/container.c deleted file mode 100644 index 82c0d8770..000000000 --- a/sway/old/container.c +++ /dev/null @@ -1,1024 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include -#include "sway/config.h" -#include "sway/container.h" -#include "sway/workspace.h" -#include "sway/focus.h" -#include "sway/border.h" -#include "sway/layout.h" -#include "sway/input_state.h" -#include "sway/ipc-server.h" -#include "sway/output.h" -#include "sway/view.h" -#include "log.h" -#include "stringop.h" - -#define ASSERT_NONNULL(PTR) \ - sway_assert (PTR, #PTR "must be non-null") - -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; - swayc_t *c = calloc(1, sizeof(swayc_t)); - if (!c) { - return NULL; - } - c->id = next_id++; - c->handle = -1; - c->gaps = -1; - 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(); - } - return c; -} - -static void free_swayc(swayc_t *cont) { - if (!ASSERT_NONNULL(cont)) { - return; - } - 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->unmanaged) { - list_free(cont->unmanaged); - } - if (cont->floating) { - while (cont->floating->length) { - free_swayc(cont->floating->items[0]); - } - list_free(cont->floating); - } - if (cont->marks) { - list_foreach(cont->marks, free); - list_free(cont->marks); - } - if (cont->parent) { - remove_child(cont); - } - if (cont->name) { - free(cont->name); - } - if (cont->class) { - free(cont->class); - } - if (cont->instance) { - free(cont->instance); - } - if (cont->app_id) { - free(cont->app_id); - } - if (cont->bg_pid != 0) { - terminate_swaybg(cont->bg_pid); - } - if (cont->border) { - if (cont->border->buffer) { - free(cont->border->buffer); - } - free(cont->border); - } - free(cont); -} - -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; -} - -// New containers - -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; - // Find current outputs to see if this already exists - { - int i, len = root_container.children->length; - for (i = 0; i < len; ++i) { - swayc_t *op = root_container.children->items[i]; - const char *op_name = op->name; - if (op_name && name && strcmp(op_name, name) == 0) { - sway_log(L_DEBUG, "restoring output %p: %s", - sway_output, op_name); - return op; - } - } - } - - struct output_config *oc = NULL, *all = NULL; - int i; - for (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->_handle.output = sway_output; - output->name = name ? strdup(name) : NULL; - output->width = size.width; - output->height = size.width; - output->unmanaged = create_list(); - output->bg_pid = 0; - - apply_output_config(oc, output); - add_child(&root_container, output); - load_swaybars(); - - // Create workspace - char *ws_name = NULL; - swayc_t *ws = NULL; - - if (name) { - for (i = 0; i < config->workspace_outputs->length; ++i) { - struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcasecmp(wso->output, name) == 0) { - sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); - // Check if any other workspaces are using this name - if ((ws = workspace_by_name(wso->workspace))) { - // if yes, move those to this output, because they should be here - move_workspace_to(ws, output); - } else if (!ws_name) { - // set a workspace name in case we need to create a default one - ws_name = strdup(wso->workspace); - } - } - } - } - - if (output->children->length == 0) { - if (!ws_name) { - ws_name = workspace_next_name(output->name); - } - // create and initialize default workspace - sway_log(L_DEBUG, "Creating default workspace %s", ws_name); - ws = new_workspace(output, ws_name); - ws->is_focused = true; - } else { - sort_workspaces(output); - set_focused_container(output->children->items[0]); - } - - free(ws_name); - update_root_geometry(); - return output; -} - -swayc_t *new_workspace(swayc_t *output, const char *name) { - if (!ASSERT_NONNULL(output)) { - return NULL; - } - sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle); - swayc_t *workspace = new_swayc(C_WORKSPACE); - - workspace->prev_layout = L_NONE; - workspace->layout = default_layout(output); - workspace->workspace_layout = default_layout(output); - - workspace->x = output->x; - workspace->y = output->y; - workspace->width = output->width; - workspace->height = output->height; - workspace->name = !name ? NULL : strdup(name); - workspace->visible = false; - workspace->floating = create_list(); - - add_child(output, workspace); - sort_workspaces(output); - - return workspace; -} - -swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { - if (!ASSERT_NONNULL(child) - && !sway_assert(!child->is_floating, "cannot create container around floating window")) { - return NULL; - } - swayc_t *cont = new_swayc(C_CONTAINER); - - sway_log(L_DEBUG, "creating container %p around %p", cont, child); - - cont->prev_layout = L_NONE; - cont->layout = layout; - cont->width = child->width; - cont->height = child->height; - cont->x = child->x; - cont->y = child->y; - cont->visible = child->visible; - cont->cached_geometry = child->cached_geometry; - cont->gaps = child->gaps; - - /* Container inherits all of workspaces children, layout and whatnot */ - if (child->type == C_WORKSPACE) { - swayc_t *workspace = child; - // reorder focus - cont->focused = workspace->focused; - workspace->focused = cont; - // set all children focu to container - int i; - for (i = 0; i < workspace->children->length; ++i) { - ((swayc_t *)workspace->children->items[i])->parent = cont; - } - // Swap children - list_t *tmp_list = workspace->children; - workspace->children = cont->children; - cont->children = tmp_list; - // add container to workspace chidren - add_child(workspace, cont); - // give them proper layouts - cont->layout = workspace->workspace_layout; - cont->prev_layout = workspace->prev_layout; - /* TODO: might break shit in move_container!!! workspace->layout = layout; */ - set_focused_container_for(workspace, get_focused_view(workspace)); - } else { // Or is built around container - swayc_t *parent = replace_child(child, cont); - if (parent) { - add_child(cont, child); - } - } - return cont; -} - -swayc_t *new_view(swayc_t *sibling, struct sway_view *view) { - if (!ASSERT_NONNULL(sibling)) { - return NULL; - } - const char *title = view->iface.get_prop(view, VIEW_PROP_TITLE); - swayc_t *swayc = new_swayc(C_VIEW); - sway_log(L_DEBUG, "Adding new view %p:%s to container %p %d", - swayc, title, sibling, sibling ? sibling->type : 0); - // Setup values - swayc->_handle.view = view; - - swayc->name = title ? strdup(title) : NULL; - - const char *class = view->iface.get_prop(view, VIEW_PROP_CLASS); - swayc->class = class ? strdup(class) : NULL; - - const char *instance = view->iface.get_prop(view, VIEW_PROP_INSTANCE); - swayc->instance = instance ? strdup(instance) : NULL; - - const char *app_id = view->iface.get_prop(view, VIEW_PROP_APP_ID); - swayc->app_id = app_id ? strdup(app_id) : NULL; - - swayc->visible = true; - swayc->is_focused = true; - swayc->sticky = false; - swayc->width = 0; - swayc->height = 0; - swayc->desired_width = -1; - swayc->desired_height = -1; - // setup border - swayc->border_type = config->border; - swayc->border_thickness = config->border_thickness; - - swayc->is_floating = false; - - if (sibling->type == C_WORKSPACE) { - // Case of focused workspace, just create as child of it - add_child(sibling, swayc); - } else { - // Regular case, create as sibling of current container - add_sibling(sibling, swayc); - } - return swayc; -} - -swayc_t *new_floating_view(wlc_handle handle) { - if (swayc_active_workspace() == NULL) { - return NULL; - } - const char *title = wlc_view_get_title(handle); - swayc_t *view = new_swayc(C_VIEW); - sway_log(L_DEBUG, "Adding new view %" PRIuPTR ":%x:%s as a floating view", - handle, wlc_view_get_type(handle), title); - // Setup values - view->handle = handle; - view->name = title ? strdup(title) : NULL; - const char *class = wlc_view_get_class(handle); - view->class = class ? strdup(class) : NULL; - const char *instance = wlc_view_get_instance(handle); - view->instance = instance ? strdup(instance) : NULL; - const char *app_id = wlc_view_get_app_id(handle); - view->app_id = app_id ? strdup(app_id) : NULL; - view->visible = true; - view->sticky = false; - - // Set the geometry of the floating view - const struct wlc_geometry *geometry = wlc_view_get_geometry(handle); - - // give it requested geometry, but place in center if possible - // in top left otherwise - if (geometry->size.w != 0) { - view->x = (swayc_active_workspace()->width - geometry->size.w) / 2; - } else { - view->x = 0; - } - if (geometry->size.h != 0) { - view->y = (swayc_active_workspace()->height - geometry->size.h) / 2; - } else { - view->y = 0; - } - - view->width = geometry->size.w; - view->height = geometry->size.h; - - view->desired_width = view->width; - view->desired_height = view->height; - - // setup border - view->border_type = config->floating_border; - view->border_thickness = config->floating_border_thickness; - - view->is_floating = true; - - // Case of focused workspace, just create as child of it - list_add(swayc_active_workspace()->floating, view); - view->parent = swayc_active_workspace(); - if (swayc_active_workspace()->focused == NULL) { - set_focused_container_for(swayc_active_workspace(), view); - } - return view; -} - -void floating_view_sane_size(swayc_t *view) { - // floating_minimum is used as sane value. - // floating_maximum has priority in case of conflict - // TODO: implement total_outputs_dimensions() - if (config->floating_minimum_height != -1 && - view->desired_height < config->floating_minimum_height) { - view->desired_height = config->floating_minimum_height; - } - if (config->floating_minimum_width != -1 && - view->desired_width < config->floating_minimum_width) { - view->desired_width = config->floating_minimum_width; - } - - // if 0 do not resize, only enforce max value - if (config->floating_maximum_height == 0) { - // Missing total_outputs_dimensions() using swayc_active_workspace() - config->floating_maximum_height = swayc_active_workspace()->height; - - } else if (config->floating_maximum_height != -1 && - view->desired_height > config->floating_maximum_height) { - view->desired_height = config->floating_maximum_height; - } - - // if 0 do not resize, only enforce max value - if (config->floating_maximum_width == 0) { - // Missing total_outputs_dimensions() using swayc_active_workspace() - config->floating_maximum_width = swayc_active_workspace()->width; - - } else if (config->floating_maximum_width != -1 && - view->desired_width > config->floating_maximum_width) { - view->desired_width = config->floating_maximum_width; - } - - sway_log(L_DEBUG, "Sane values for view to %d x %d @ %.f, %.f", - view->desired_width, view->desired_height, view->x, view->y); - - return; -} - - -// Destroy container - -swayc_t *destroy_output(swayc_t *output) { - if (!ASSERT_NONNULL(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]); - update_visibility(root_container.children->items[p]); - arrange_windows(root_container.children->items[p], -1, -1); - } - } - sway_log(L_DEBUG, "OUTPUT: Destroying output '%" PRIuPTR "'", output->handle); - free_swayc(output); - update_root_geometry(); - return &root_container; -} - -swayc_t *destroy_workspace(swayc_t *workspace) { - if (!ASSERT_NONNULL(workspace)) { - return NULL; - } - - // Do not destroy this if it's the last workspace on this output - swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); - if (output && output->children->length == 1) { - return NULL; - } - - swayc_t *parent = workspace->parent; - // destroy the WS if there are no children - if (workspace->children->length == 0 && workspace->floating->length == 0) { - sway_log(L_DEBUG, "destroying workspace '%s'", workspace->name); - ipc_event_workspace(workspace, NULL, "empty"); - } else { - // Move children to a different workspace on this output - swayc_t *new_workspace = NULL; - int i; - for(i = 0; i < output->children->length; i++) { - if(output->children->items[i] != workspace) { - break; - } - } - new_workspace = output->children->items[i]; - - sway_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", - workspace->name, new_workspace->name); - - for(i = 0; i < workspace->children->length; i++) { - move_container_to(workspace->children->items[i], new_workspace); - } - - for(i = 0; i < workspace->floating->length; i++) { - move_container_to(workspace->floating->items[i], new_workspace); - } - } - - free_swayc(workspace); - return parent; -} - -swayc_t *destroy_container(swayc_t *container) { - if (!ASSERT_NONNULL(container)) { - return NULL; - } - while (container->children->length == 0 && container->type == C_CONTAINER) { - sway_log(L_DEBUG, "Container: Destroying container '%p'", container); - swayc_t *parent = container->parent; - free_swayc(container); - container = parent; - } - return container; -} - -swayc_t *destroy_view(swayc_t *view) { - if (!ASSERT_NONNULL(view)) { - return NULL; - } - sway_log(L_DEBUG, "Destroying view '%p'", view); - swayc_t *parent = view->parent; - free_swayc(view); - - // Destroy empty containers - if (parent && parent->type == C_CONTAINER) { - return destroy_container(parent); - } - return parent; -} - -// Container lookup - - -swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { - if (!container->children) { - return NULL; - } - // Special case for checking floating stuff - int i; - if (container->type == C_WORKSPACE) { - for (i = 0; i < container->floating->length; ++i) { - swayc_t *child = container->floating->items[i]; - if (test(child, data)) { - return child; - } - } - } - for (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; -} - -static bool test_name(swayc_t *view, void *data) { - if (!view || !view->name) { - return false; - } - return strcmp(view->name, data) == 0; -} - -swayc_t *swayc_by_name(const char *name) { - return swayc_by_test(&root_container, test_name, (void *)name); -} - -swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { - if (!ASSERT_NONNULL(container)) { - return NULL; - } - if (!sway_assert(type < C_TYPES && type >= C_ROOT, "invalid type")) { - return NULL; - } - do { - container = container->parent; - } while (container && container->type != type); - return container; -} - -swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts layout) { - if (!ASSERT_NONNULL(container)) { - return NULL; - } - if (!sway_assert(layout < L_LAYOUTS && layout >= L_NONE, "invalid layout")) { - return NULL; - } - do { - container = container->parent; - } while (container && container->layout != layout); - return container; -} - -swayc_t *swayc_focus_by_type(swayc_t *container, enum swayc_types type) { - if (!ASSERT_NONNULL(container)) { - return NULL; - } - if (!sway_assert(type < C_TYPES && type >= C_ROOT, "invalid type")) { - return NULL; - } - do { - container = container->focused; - } while (container && container->type != type); - return container; -} - -swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts layout) { - if (!ASSERT_NONNULL(container)) { - return NULL; - } - if (!sway_assert(layout < L_LAYOUTS && layout >= L_NONE, "invalid layout")) { - return NULL; - } - do { - container = container->focused; - } while (container && container->layout != layout); - return container; -} - - -static swayc_t *_swayc_by_handle_helper(wlc_handle handle, swayc_t *parent) { - if (!parent || !parent->children) { - return NULL; - } - int i, len; - swayc_t **child; - if (parent->type == C_WORKSPACE) { - len = parent->floating->length; - child = (swayc_t **)parent->floating->items; - for (i = 0; i < len; ++i, ++child) { - if ((*child)->handle == handle) { - return *child; - } - } - } - - len = parent->children->length; - child = (swayc_t**)parent->children->items; - for (i = 0; i < len; ++i, ++child) { - if ((*child)->handle == handle) { - return *child; - } else { - swayc_t *res; - if ((res = _swayc_by_handle_helper(handle, *child))) { - return res; - } - } - } - return NULL; -} - -swayc_t *swayc_by_handle(wlc_handle handle) { - return _swayc_by_handle_helper(handle, &root_container); -} - -swayc_t *swayc_active_output(void) { - return root_container.focused; -} - -swayc_t *swayc_active_workspace(void) { - return root_container.focused ? root_container.focused->focused : NULL; -} - -swayc_t *swayc_active_workspace_for(swayc_t *cont) { - if (!cont) { - return NULL; - } - switch (cont->type) { - case C_ROOT: - cont = cont->focused; - /* Fallthrough */ - - case C_OUTPUT: - cont = cont ? cont->focused : NULL; - /* Fallthrough */ - - case C_WORKSPACE: - return cont; - - default: - return swayc_parent_by_type(cont, C_WORKSPACE); - } -} - -static bool pointer_test(swayc_t *view, void *_origin) { - const struct wlc_point *origin = _origin; - // Determine the output that the view is under - swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); - if (origin->x >= view->x && origin->y >= view->y - && origin->x < view->x + view->width && origin->y < view->y + view->height - && view->visible && parent == root_container.focused) { - return true; - } - return false; -} - -swayc_t *container_under_pointer(void) { - // root.output->workspace - if (!root_container.focused) { - return NULL; - } - swayc_t *lookup = root_container.focused; - // Case of empty workspace - if (lookup->children && !lookup->unmanaged) { - return NULL; - } - double x, y; - wlc_pointer_get_position_v2(&x, &y); - struct wlc_point origin = { .x = x, .y = y }; - - while (lookup && lookup->type != C_VIEW) { - int i; - int len; - for (int _i = 0; lookup->unmanaged && _i < lookup->unmanaged->length; ++_i) { - wlc_handle *handle = lookup->unmanaged->items[_i]; - const struct wlc_geometry *geo = wlc_view_get_geometry(*handle); - if (origin.x >= geo->origin.x && origin.y >= geo->origin.y - && origin.x < geo->origin.x + (int)geo->size.w - && origin.y < geo->origin.y + (int)geo->size.h) { - // Hack: we force focus upon unmanaged views here - wlc_view_focus(*handle); - return NULL; - } - } - // if tabbed/stacked go directly to focused container, otherwise search - // children - if (lookup->layout == L_TABBED || lookup->layout == L_STACKED) { - lookup = lookup->focused; - continue; - } - // if workspace, search floating - if (lookup->type == C_WORKSPACE) { - i = len = lookup->floating->length; - bool got_floating = false; - while (--i > -1) { - if (pointer_test(lookup->floating->items[i], &origin)) { - lookup = lookup->floating->items[i]; - got_floating = true; - break; - } - } - if (got_floating) { - continue; - } - } - // search children - len = lookup->children->length; - for (i = 0; i < len; ++i) { - if (pointer_test(lookup->children->items[i], &origin)) { - lookup = lookup->children->items[i]; - break; - } - } - // when border and titles are done, this could happen - if (i == len) { - break; - } - } - return lookup; -} - -swayc_t *container_find(swayc_t *container, bool (*f)(swayc_t *, const void *), const void *data) { - if (container->children == NULL || container->children->length == 0) { - return NULL; - } - - swayc_t *con; - if (container->type == C_WORKSPACE) { - for (int i = 0; i < container->floating->length; ++i) { - con = container->floating->items[i]; - if (f(con, data)) { - return con; - } - con = container_find(con, f, data); - if (con != NULL) { - return con; - } - } - } - - for (int i = 0; i < container->children->length; ++i) { - con = container->children->items[i]; - if (f(con, data)) { - return con; - } - - con = container_find(con, f, data); - if (con != NULL) { - return con; - } - } - - return NULL; -} - -// Container information - -bool swayc_is_fullscreen(swayc_t *view) { - return view && view->type == C_VIEW && (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN); -} - -bool swayc_is_active(swayc_t *view) { - return view && view->type == C_VIEW && (wlc_view_get_state(view->handle) & WLC_BIT_ACTIVATED); -} - -bool swayc_is_parent_of(swayc_t *parent, swayc_t *child) { - while (child != &root_container) { - child = child->parent; - if (child == parent) { - return true; - } - } - return false; -} - -bool swayc_is_child_of(swayc_t *child, swayc_t *parent) { - return swayc_is_parent_of(parent, child); -} - -bool swayc_is_empty_workspace(swayc_t *container) { - return container->type == C_WORKSPACE && container->children->length == 0; -} - -int swayc_gap(swayc_t *container) { - if (container->type == C_VIEW || container->type == C_CONTAINER) { - return container->gaps >= 0 ? container->gaps : config->gaps_inner; - } else if (container->type == C_WORKSPACE) { - int base = container->gaps >= 0 ? container->gaps : config->gaps_outer; - if (config->edge_gaps && !(config->smart_gaps && container->children->length == 1)) { - // the inner gap is created via a margin around each window which - // is half the gap size, so the workspace also needs half a gap - // size to make the outermost gap the same size (excluding the - // actual "outer gap" size which is handled independently) - return base + config->gaps_inner / 2; - } else if (config->smart_gaps && container->children->length == 1) { - return 0; - } else { - return base; - } - } else { - return 0; - } -} - -// Mapping - -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); - } - } - 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 update_visibility_output(swayc_t *container, wlc_handle output) { - // Inherit visibility - swayc_t *parent = container->parent; - container->visible = parent->visible; - // special cases where visibility depends on focus - if (parent->type == C_OUTPUT || parent->layout == L_TABBED || - parent->layout == L_STACKED) { - container->visible = parent->focused == container && parent->visible; - } - // Set visibility and output for view - if (container->type == C_VIEW) { - wlc_view_set_output(container->handle, output); - wlc_view_set_mask(container->handle, container->visible ? VISIBLE : 0); - } - // Update visibility for children - else { - if (container->children) { - int i, len = container->children->length; - for (i = 0; i < len; ++i) { - update_visibility_output(container->children->items[i], output); - } - } - if (container->floating) { - int i, len = container->floating->length; - for (i = 0; i < len; ++i) { - update_visibility_output(container->floating->items[i], output); - } - } - } -} - -void update_visibility(swayc_t *container) { - if (!container) return; - switch (container->type) { - case C_ROOT: - container->visible = true; - if (container->children) { - int i, len = container->children->length; - for (i = 0; i < len; ++i) { - update_visibility(container->children->items[i]); - } - } - return; - - case C_OUTPUT: - container->visible = true; - if (container->children) { - int i, len = container->children->length; - for (i = 0; i < len; ++i) { - update_visibility_output(container->children->items[i], container->handle); - } - } - return; - - default: - { - swayc_t *op = swayc_parent_by_type(container, C_OUTPUT); - update_visibility_output(container, op->handle); - } - } -} - -void set_gaps(swayc_t *view, void *_data) { - int *data = _data; - if (!ASSERT_NONNULL(view)) { - return; - } - if (view->type == C_WORKSPACE || view->type == C_VIEW) { - view->gaps = *data; - } -} - -void add_gaps(swayc_t *view, void *_data) { - int *data = _data; - if (!ASSERT_NONNULL(view)) { - return; - } - if (view->type == C_WORKSPACE || view->type == C_VIEW) { - if ((view->gaps += *data) < 0) { - view->gaps = 0; - } - } -} - -static void close_view(swayc_t *container, void *data) { - if (container->type == C_VIEW) { - wlc_view_close(container->handle); - } -} - -void close_views(swayc_t *container) { - container_map(container, close_view, NULL); -} - -swayc_t *swayc_tabbed_stacked_ancestor(swayc_t *view) { - swayc_t *parent = NULL; - if (!ASSERT_NONNULL(view)) { - return NULL; - } - while (view->type != C_WORKSPACE && view->parent && view->parent->type != C_WORKSPACE) { - view = view->parent; - if (view->layout == L_TABBED || view->layout == L_STACKED) { - parent = view; - } - } - - return parent; -} - -swayc_t *swayc_tabbed_stacked_parent(swayc_t *con) { - if (!ASSERT_NONNULL(con)) { - return NULL; - } - if (con->parent && (con->parent->layout == L_TABBED || con->parent->layout == L_STACKED)) { - return con->parent; - } - return NULL; -} - -swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) { - // if layout change modifies the auto layout's major axis, swap width and height - // to preserve current ratios. - if (is_auto_layout(layout) && is_auto_layout(container->layout)) { - enum swayc_layouts prev_major = - container->layout == L_AUTO_LEFT || container->layout == L_AUTO_RIGHT - ? L_HORIZ : L_VERT; - enum swayc_layouts new_major = - layout == L_AUTO_LEFT || layout == L_AUTO_RIGHT - ? L_HORIZ : L_VERT; - if (new_major != prev_major) { - for (int i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - double h = child->height; - child->height = child->width; - child->width = h; - } - } - } - if (container->type == C_WORKSPACE) { - container->workspace_layout = layout; - if (layout == L_HORIZ || layout == L_VERT || is_auto_layout(layout)) { - container->layout = layout; - } - } else { - container->layout = layout; - } - return container; -} diff --git a/sway/old/criteria.c b/sway/old/criteria.c deleted file mode 100644 index e8978ebef..000000000 --- a/sway/old/criteria.c +++ /dev/null @@ -1,451 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include "sway/criteria.h" -#include "sway/container.h" -#include "sway/config.h" -#include "stringop.h" -#include "list.h" -#include "log.h" - -enum criteria_type { // *must* keep in sync with criteria_strings[] - 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_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) { - sway_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)) { - sway_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 { - sway_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; - } - int matches = 0; - for (int i = 0; i < tokens->length; i++) { - struct crit_token *crit = tokens->items[i]; - switch (crit->type) { - case CRIT_CLASS: - if (!cont->class) { - // ignore - } else if (crit_is_focused(crit->raw)) { - swayc_t *focused = get_focused_view(&root_container); - if (focused->class && strcmp(cont->class, focused->class) == 0) { - matches++; - } - } else if (crit->regex && regex_cmp(cont->class, crit->regex) == 0) { - matches++; - } - 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: - if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) { - // Make sure it isn't matching the NUL string - if ((strcmp(crit->raw, "") == 0) == (list_seq_find(cont->marks, (int (*)(const void *, const void *))strcmp, "") != -1)) { - ++matches; - } - } - break; - case CRIT_FLOATING: - if (cont->is_floating) { - matches++; - } - break; - case CRIT_ID: - if (!cont->app_id) { - // ignore - } else if (crit->regex && regex_cmp(cont->app_id, crit->regex) == 0) { - matches++; - } - break; - case CRIT_INSTANCE: - if (!cont->instance) { - // ignore - } else if (crit_is_focused(crit->raw)) { - swayc_t *focused = get_focused_view(&root_container); - if (focused->instance && strcmp(cont->instance, focused->instance) == 0) { - matches++; - } - } else if (crit->regex && regex_cmp(cont->instance, crit->regex) == 0) { - matches++; - } - break; - case CRIT_TILING: - if (!cont->is_floating) { - matches++; - } - break; - case CRIT_TITLE: - if (!cont->name) { - // ignore - } else if (crit_is_focused(crit->raw)) { - swayc_t *focused = get_focused_view(&root_container); - if (focused->name && strcmp(cont->name, focused->name) == 0) { - matches++; - } - } 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: - // TODO wlc indeed exposes this information - break; - case CRIT_WORKSPACE: ; - swayc_t *cont_ws = swayc_parent_by_type(cont, C_WORKSPACE); - if (!cont_ws || !cont_ws->name) { - // ignore - } else if (crit_is_focused(crit->raw)) { - swayc_t *focused_ws = swayc_active_workspace(); - if (focused_ws->name && strcmp(cont_ws->name, focused_ws->name) == 0) { - matches++; - } - } else if (crit->regex && regex_cmp(cont_ws->name, crit->regex) == 0) { - matches++; - } - 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); - - for (int i = 0; i < scratchpad->length; ++i) { - swayc_t *c = scratchpad->items[i]; - if (criteria_test(c, tokens)) { - list_add(list_tokens.list, c); - } - } - - return list_tokens.list; -} diff --git a/sway/old/focus.c b/sway/old/focus.c deleted file mode 100644 index 66f7ee17f..000000000 --- a/sway/old/focus.c +++ /dev/null @@ -1,278 +0,0 @@ -#include "stdbool.h" -#include -#include "sway/focus.h" -#include "sway/workspace.h" -#include "sway/layout.h" -#include "sway/config.h" -#include "sway/input_state.h" -#include "sway/ipc-server.h" -#include "sway/border.h" -#include "log.h" - -bool locked_container_focus = false; -bool suspend_workspace_cleanup = false; - -// switches parent focus to c. will switch it accordingly -static void update_focus(swayc_t *c) { - // Handle if focus switches - swayc_t *parent = c->parent; - if (!parent) return; - if (parent->focused != c) { - // Get previous focus - swayc_t *prev = parent->focused; - // Set new focus - parent->focused = c; - - switch (c->type) { - // Shouldn't happen - case C_ROOT: return; - - // Case where output changes - case C_OUTPUT: - wlc_output_focus(c->handle); - break; - - // Case where workspace changes - case C_WORKSPACE: - if (prev) { - ipc_event_workspace(prev, c, "focus"); - - // if the old workspace has no children, destroy it - if(prev->children->length == 0 && prev->floating->length == 0 && !suspend_workspace_cleanup) { - destroy_workspace(prev); - } else { - // update visibility of old workspace - update_visibility(prev); - } - } - // Update visibility of newly focused workspace - update_visibility(c); - break; - - default: - case C_VIEW: - case C_CONTAINER: - break; - } - } -} - -bool move_focus(enum movement_direction direction) { - swayc_t *old_view = get_focused_container(&root_container); - swayc_t *new_view = get_swayc_in_direction(old_view, direction); - if (!new_view) { - return false; - } else if (new_view->type == C_ROOT) { - sway_log(L_DEBUG, "Not setting focus above the workspace level"); - return false; - } else if (new_view->type == C_OUTPUT) { - return set_focused_container(swayc_active_workspace_for(new_view)); - } else if (direction == MOVE_PARENT || direction == MOVE_CHILD) { - return set_focused_container(new_view); - } else if (config->mouse_warping) { - swayc_t *old_op = old_view->type == C_OUTPUT ? - old_view : swayc_parent_by_type(old_view, C_OUTPUT); - swayc_t *focused = get_focused_view(new_view); - if (set_focused_container(focused)) { - if (old_op != swayc_active_output() && focused && focused->type == C_VIEW) { - center_pointer_on(focused); - } - return true; - } - } else { - return set_focused_container(get_focused_view(new_view)); - } - return false; -} - -swayc_t *get_focused_container(swayc_t *parent) { - if (!parent) { - return swayc_active_workspace(); - } - while (!parent->is_focused && parent->focused) { - parent = parent->focused; - } - return parent; -} - -bool set_focused_container(swayc_t *c) { - if (locked_container_focus || !c || !c->parent) { - return false; - } - - // current ("old") workspace for sending workspace change event later - swayc_t *old_ws = swayc_active_workspace(); - // keep track of child count so we can determine if it gets destroyed - int old_ws_child_count = 0; - if (old_ws) { - old_ws_child_count = old_ws->children->length + old_ws->floating->length; - } - - // current ("old") focused container - swayc_t *old_focus = get_focused_container(&root_container); - // if old_focus is a workspace, then it's the same workspace as - // old_ws, and we'll need to null its pointer too, since it will - // be destroyed in the update_focus() call - bool old_focus_was_ws = (old_focus->type == C_WORKSPACE); - - // workspace of new focused container - swayc_t *workspace = swayc_active_workspace_for(c); - - if (swayc_is_fullscreen(get_focused_container(workspace))) { - // if switching to a workspace with a fullscreen view, - // focus on the fullscreen view - c = get_focused_container(workspace); - } - - swayc_log(L_DEBUG, c, "Setting focus to %p:%" PRIuPTR, c, c->handle); - - if (c->type == C_VIEW) { - // dispatch a window event - ipc_event_window(c, "focus"); - } - - // update the global pointer - current_focus = c; - - // update container focus from here to root, making necessary changes along - // the way - swayc_t *p = c; - if (p->type != C_OUTPUT && p->type != C_ROOT) { - p->is_focused = true; - } - while (p != &root_container) { - update_focus(p); - p = p->parent; - p->is_focused = false; - } - - if (old_focus_was_ws && old_ws_child_count == 0) { - // this workspace was destroyed in update_focus(), so null the pointers - old_focus = NULL; - old_ws = NULL; - } - - if (!(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { - if (old_focus) { - if (old_focus->type == C_VIEW) { - wlc_view_set_state(old_focus->handle, WLC_BIT_ACTIVATED, false); - } - update_container_border(old_focus); - } - if (c->type == C_VIEW) { - wlc_view_set_state(c->handle, WLC_BIT_ACTIVATED, true); - } - /* TODO WLR - if (!desktop_shell.is_locked) { - // If the system is locked, we do everything _but_ actually setting - // focus. This includes making our internals think that this view is - // focused. - wlc_view_focus(c->handle); - } - */ - if (c->parent->layout != L_TABBED && c->parent->layout != L_STACKED) { - update_container_border(c); - } - - swayc_t *parent = swayc_tabbed_stacked_ancestor(c); - if (parent != NULL) { - arrange_backgrounds(); - arrange_windows(parent, -1, -1); - } - } - - if (old_ws != workspace) { - // old_ws might be NULL here but that's ok - ipc_event_workspace(old_ws, workspace, "focus"); - } - - return true; -} - -bool set_focused_container_for(swayc_t *a, swayc_t *c) { - if (locked_container_focus || !c) { - return false; - } - swayc_t *find = c; - while (find != a && (find = find->parent)) { - if (find == &root_container) { - return false; - } - } - - // Get workspace for c, get that workspaces current focused container. - swayc_t *workspace = swayc_active_workspace_for(c); - swayc_t *focused = get_focused_view(workspace); - // if the workspace we are changing focus to has a fullscreen view return - if (swayc_is_fullscreen(focused) && c != focused) { - return false; - } - - // Check if we are changing a parent container that will see change - bool effective = true; - while (find != &root_container) { - if (find->parent->focused != find) { - effective = false; - } - find = find->parent; - } - if (effective) { - // Go to set_focused_container - return set_focused_container(c); - } - - sway_log(L_DEBUG, "Setting focus for %p:%" PRIuPTR " to %p:%" PRIuPTR, - a, a->handle, c, c->handle); - - c->is_focused = true; - swayc_t *p = c; - while (p != a) { - update_focus(p); - p = p->parent; - p->is_focused = false; - } - return true; -} - -swayc_t *get_focused_view(swayc_t *parent) { - swayc_t *c = parent; - while (c && c->type != C_VIEW) { - if (c->type == C_WORKSPACE && c->focused == NULL) { - return c; - } - c = c->focused; - } - if (c == NULL) { - c = swayc_active_workspace_for(parent); - } - return c; -} - -swayc_t *get_focused_float(swayc_t *ws) { - if(!sway_assert(ws->type == C_WORKSPACE, "must be of workspace type")) { - ws = swayc_active_workspace(); - } - if (ws->floating->length) { - return ws->floating->items[ws->floating->length - 1]; - } - return NULL; -} - -swayc_t *get_focused_view_include_floating(swayc_t *parent) { - swayc_t *c = parent; - swayc_t *f = NULL; - - while (c && c->type != C_VIEW) { - if (c->type == C_WORKSPACE && c->focused == NULL) { - return ((f = get_focused_float(c))) ? f : c; - } - - c = c->focused; - } - - if (c == NULL) { - c = swayc_active_workspace_for(parent); - } - - return c; -} diff --git a/sway/old/handlers.c b/sway/old/handlers.c deleted file mode 100644 index 33e75d6b0..000000000 --- a/sway/old/handlers.c +++ /dev/null @@ -1,1143 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sway/handlers.h" -#include "sway/border.h" -#include "sway/layout.h" -#include "sway/config.h" -#include "sway/commands.h" -#include "sway/workspace.h" -#include "sway/container.h" -#include "sway/output.h" -#include "sway/focus.h" -#include "sway/input_state.h" -#include "sway/extensions.h" -#include "sway/criteria.h" -#include "sway/ipc-server.h" -#include "sway/input.h" -#include "sway/security.h" -#include "list.h" -#include "stringop.h" -#include "log.h" - -// Event should be sent to client -#define EVENT_PASSTHROUGH false - -// Event handled by sway and should not be sent to client -#define EVENT_HANDLED true - -static struct panel_config *if_panel_find_config(struct wl_client *client) { - int i; - for (i = 0; i < desktop_shell.panels->length; i++) { - struct panel_config *config = desktop_shell.panels->items[i]; - if (config->client == client) { - return config; - } - } - return NULL; -} - -static struct background_config *if_background_find_config(struct wl_client *client) { - int i; - for (i = 0; i < desktop_shell.backgrounds->length; i++) { - struct background_config *config = desktop_shell.backgrounds->items[i]; - if (config->client == client) { - return config; - } - } - return NULL; -} - -static struct wlc_geometry compute_panel_geometry(struct panel_config *config) { - struct wlc_size resolution; - output_get_scaled_size(config->output, &resolution); - const struct wlc_geometry *old = wlc_view_get_geometry(config->handle); - struct wlc_geometry new; - - switch (config->panel_position) { - case DESKTOP_SHELL_PANEL_POSITION_TOP: - new.origin.x = 0; - new.origin.y = 0; - new.size.w = resolution.w; - new.size.h = old->size.h; - break; - case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: - new.origin.x = 0; - new.origin.y = resolution.h - old->size.h; - new.size.w = resolution.w; - new.size.h = old->size.h; - break; - case DESKTOP_SHELL_PANEL_POSITION_LEFT: - new.origin.x = 0; - new.origin.y = 0; - new.size.w = old->size.w; - new.size.h = resolution.h; - break; - case DESKTOP_SHELL_PANEL_POSITION_RIGHT: - new.origin.x = resolution.w - old->size.w; - new.origin.y = 0; - new.size.w = old->size.w; - new.size.h = resolution.h; - break; - } - - return new; -} - -static void update_panel_geometry(struct panel_config *config) { - struct wlc_geometry geometry = compute_panel_geometry(config); - wlc_view_set_geometry(config->handle, 0, &geometry); -} - -static void update_panel_geometries(wlc_handle output) { - for (int i = 0; i < desktop_shell.panels->length; i++) { - struct panel_config *config = desktop_shell.panels->items[i]; - if (config->output == output) { - update_panel_geometry(config); - } - } -} - -static void update_background_geometry(struct background_config *config) { - struct wlc_geometry geometry = wlc_geometry_zero; - output_get_scaled_size(config->output, &geometry.size); - wlc_view_set_geometry(config->handle, 0, &geometry); -} - -static void update_background_geometries(wlc_handle output) { - for (int i = 0; i < desktop_shell.backgrounds->length; i++) { - struct background_config *config = desktop_shell.backgrounds->items[i]; - if (config->output == output) { - update_background_geometry(config); - } - } -} - -/* Handles */ - -static bool handle_input_created(struct libinput_device *device) { - const char *identifier = libinput_dev_unique_id(device); - if (!identifier) { - sway_log(L_ERROR, "Unable to allocate unique name for input device %p", - device); - return true; - } - sway_log(L_INFO, "Found input device (%s)", identifier); - - list_add(input_devices, device); - - struct input_config *ic = NULL; - int i; - for (i = 0; i < config->input_configs->length; ++i) { - struct input_config *cur = config->input_configs->items[i]; - if (strcasecmp(identifier, cur->identifier) == 0) { - sway_log(L_DEBUG, "Matched input config for %s", - identifier); - ic = cur; - break; - } - if (strcasecmp("*", cur->identifier) == 0) { - sway_log(L_DEBUG, "Matched wildcard input config for %s", - identifier); - ic = cur; - break; - } - } - - apply_input_config(ic, device); - return true; -} - -static void handle_input_destroyed(struct libinput_device *device) { - int i; - list_t *list = input_devices; - for (i = 0; i < list->length; ++i) { - if(((struct libinput_device *)list->items[i]) == device) { - list_del(list, i); - break; - } - } -} - -static bool handle_output_created(wlc_handle output) { - swayc_t *op = new_output(output); - - // Visibility mask to be able to make view invisible - wlc_output_set_mask(output, VISIBLE); - - if (!op) { - return false; - } - - // Switch to workspace if we need to - if (swayc_active_workspace() == NULL) { - swayc_t *ws = op->children->items[0]; - workspace_switch(ws); - } - - // Fixes issues with backgrounds and wlc - wlc_handle prev = wlc_get_focused_output(); - wlc_output_focus(output); - wlc_output_focus(prev); - return true; -} - -static void handle_output_destroyed(wlc_handle output) { - int i; - list_t *list = root_container.children; - for (i = 0; i < list->length; ++i) { - if (((swayc_t *)list->items[i])->handle == output) { - break; - } - } - if (i < list->length) { - destroy_output(list->items[i]); - } else { - return; - } - if (list->length > 0) { - // switch to other outputs active workspace - workspace_switch(((swayc_t *)root_container.children->items[0])->focused); - } -} - -static void handle_output_post_render(wlc_handle output) { - ipc_get_pixels(output); -} - -static void handle_view_pre_render(wlc_handle view) { - render_view_borders(view); -} - -static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { - sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); - - swayc_t *c = swayc_by_handle(output); - if (!c) { - return; - } - c->width = to->w; - c->height = to->h; - - update_panel_geometries(output); - update_background_geometries(output); - - arrange_windows(&root_container, -1, -1); -} - -static void handle_output_focused(wlc_handle output, bool focus) { - swayc_t *c = swayc_by_handle(output); - // if for some reason this output doesn't exist, create it. - if (!c) { - handle_output_created(output); - } - if (focus) { - set_focused_container(get_focused_container(c)); - } -} - -static void ws_cleanup() { - swayc_t *op, *ws; - int i = 0, j; - if (!root_container.children) - return; - while (i < root_container.children->length) { - op = root_container.children->items[i++]; - if (!op->children) - continue; - j = 0; - while (j < op->children->length) { - ws = op->children->items[j++]; - if (ws->children->length == 0 && ws->floating->length == 0 && ws != op->focused) { - if (destroy_workspace(ws)) { - j--; - } - } - } - } -} - -static void positioner_place_window(wlc_handle handle) { - const struct wlc_geometry *anchor = wlc_view_positioner_get_anchor_rect(handle); - const struct wlc_size *sr = wlc_view_positioner_get_size(handle); - // a positioner is required to have a non-null anchor and a non-negative size - if (!anchor || !sr || - sr->w <= 0 || sr->h <= 0 || - anchor->size.w <= 0 || anchor->size.h <= 0) { - return; - } - const struct wlc_point offset = *wlc_view_positioner_get_offset(handle); - enum wlc_positioner_anchor_bit anchors = wlc_view_positioner_get_anchor(handle); - enum wlc_positioner_gravity_bit gravity = wlc_view_positioner_get_gravity(handle); - struct wlc_geometry geo = { - .origin = offset, - .size = *sr - }; - - if (anchors & WLC_BIT_ANCHOR_TOP) { - geo.origin.y += anchor->origin.y; - } else if (anchors & WLC_BIT_ANCHOR_BOTTOM) { - geo.origin.y += anchor->origin.y + anchor->size.h; - } else { - geo.origin.y += anchor->origin.y + anchor->size.h / 2; - } - if (anchors & WLC_BIT_ANCHOR_LEFT) { - geo.origin.x += anchor->origin.x; - } else if (anchors & WLC_BIT_ANCHOR_RIGHT) { - geo.origin.x += anchor->origin.x + anchor->size.w; - } else { - geo.origin.x += anchor->origin.x + anchor->size.w / 2; - } - - if (gravity & WLC_BIT_GRAVITY_TOP) { - geo.origin.y -= geo.size.h; - } else if (gravity & WLC_BIT_GRAVITY_BOTTOM) { - /* default */ - } else { - geo.origin.y -= geo.size.h / 2; - } - if (gravity & WLC_BIT_GRAVITY_LEFT) { - geo.origin.x -= geo.size.w; - } else if (gravity & WLC_BIT_GRAVITY_RIGHT) { - /* default */ - } else { - geo.origin.x -= geo.size.w / 2; - } - - sway_log(L_DEBUG, "xdg-positioner: placing window %" PRIuPTR " " - "sized (%u,%u) offset by (%d,%d), " - "anchor rectangle sized (%u,%u) at (%d,%d), " - "anchor edges: %s %s, gravity: %s %s", - handle, - sr->w, sr->h, offset.x, offset.y, - anchor->size.w, anchor->size.h, anchor->origin.x, anchor->origin.y, - anchors & WLC_BIT_ANCHOR_TOP ? "top" : - (anchors & WLC_BIT_ANCHOR_BOTTOM ? "bottom" : "middle"), - anchors & WLC_BIT_ANCHOR_LEFT ? "left" : - (anchors & WLC_BIT_ANCHOR_RIGHT ? "right" : "center"), - gravity & WLC_BIT_GRAVITY_TOP ? "top" : - (gravity & WLC_BIT_GRAVITY_BOTTOM ? "bottom" : "middle"), - gravity & WLC_BIT_GRAVITY_LEFT ? "left" : - (gravity & WLC_BIT_GRAVITY_RIGHT ? "right" : "center")); - - wlc_handle parent = wlc_view_get_parent(handle); - if (parent) { - const struct wlc_geometry *pg = wlc_view_get_geometry(parent); - geo.origin.x += pg->origin.x; - geo.origin.y += pg->origin.y; - } - wlc_view_set_geometry(handle, 0, &geo); -} - -static bool handle_view_created(wlc_handle handle) { - // if view is child of another view, the use that as focused container - wlc_handle parent = wlc_view_get_parent(handle); - swayc_t *focused = NULL; - swayc_t *newview = NULL; - swayc_t *current_ws = swayc_active_workspace(); - bool return_to_workspace = false; - struct wl_client *client = wlc_view_get_wl_client(handle); - struct wl_resource *resource = wlc_surface_get_wl_resource( - wlc_view_get_surface(handle)); - pid_t pid; - struct panel_config *panel_config = NULL; - struct background_config *background_config = NULL; - - panel_config = if_panel_find_config(client); - if (panel_config) { - panel_config->handle = handle; - update_panel_geometry(panel_config); - wlc_view_set_mask(handle, VISIBLE); - wlc_view_set_output(handle, panel_config->output); - wlc_view_bring_to_front(handle); - arrange_windows(&root_container, -1, -1); - return true; - } - - background_config = if_background_find_config(client); - if (background_config) { - background_config->handle = handle; - update_background_geometry(background_config); - wlc_view_set_mask(handle, VISIBLE); - wlc_view_set_output(handle, background_config->output); - wlc_view_send_to_back(handle); - return true; - } - - // Get parent container, to add view in - if (parent) { - focused = swayc_by_handle(parent); - } - - if (client) { - pid = wlc_view_get_pid(handle); - - if (pid) { - // using newview as a temp storage location here, - // rather than adding yet another workspace var - newview = workspace_for_pid(pid); - if (newview) { - focused = get_focused_container(newview); - return_to_workspace = true; - } - newview = NULL; - } - } - - swayc_t *prev_focus = get_focused_container(&root_container); - - if (!focused || focused->type == C_OUTPUT) { - focused = prev_focus; - // Move focus from floating view - if (focused->is_floating) { - // To workspace if there are no children - if (focused->parent->children->length == 0) { - focused = focused->parent; - } - // TODO find a better way of doing this - // Or to focused container - else { - focused = get_focused_container(focused->parent->children->items[0]); - } - } - } - - positioner_place_window(handle); - - sway_log(L_DEBUG, "handle:%" PRIuPTR " type:%x state:%x parent:%" PRIuPTR " " - "mask:%d (x:%d y:%d w:%d h:%d) title:%s " - "class:%s appid:%s", - handle, wlc_view_get_type(handle), wlc_view_get_state(handle), parent, - wlc_view_get_mask(handle), wlc_view_get_geometry(handle)->origin.x, - wlc_view_get_geometry(handle)->origin.y,wlc_view_get_geometry(handle)->size.w, - wlc_view_get_geometry(handle)->size.h, wlc_view_get_title(handle), - wlc_view_get_class(handle), wlc_view_get_app_id(handle)); - - // TODO properly figure out how each window should be handled. - switch (wlc_view_get_type(handle)) { - // regular view created regularly - case 0: - if (parent) { - newview = new_floating_view(handle); - } else { - newview = new_view(focused, handle); - wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); - } - break; - - // Dmenu keeps viewfocus, but others with this flag don't, for now simulate - // dmenu - case WLC_BIT_OVERRIDE_REDIRECT: - wlc_view_focus(handle); - wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); - wlc_view_bring_to_front(handle); - break; - - // Firefox popups have this flag set. - case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: - wlc_view_bring_to_front(handle); - locked_container_focus = true; - break; - - // Modals, get focus, popups do not - case WLC_BIT_MODAL: - wlc_view_focus(handle); - wlc_view_bring_to_front(handle); - newview = new_floating_view(handle); - /* fallthrough */ - case WLC_BIT_POPUP: - wlc_view_bring_to_front(handle); - break; - } - - // Prevent current ws from being destroyed, if empty - suspend_workspace_cleanup = true; - - if (newview) { - ipc_event_window(newview, "new"); - set_focused_container(newview); - wlc_view_set_mask(handle, VISIBLE); - swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT); - arrange_windows(output, -1, -1); - // check if it matches for_window in config and execute if so - list_t *criteria = criteria_for(newview); - for (int i = 0; i < criteria->length; i++) { - struct criteria *crit = criteria->items[i]; - sway_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'", - crit->crit_raw, newview, crit->cmdlist); - struct cmd_results *res = handle_command(crit->cmdlist, CONTEXT_CRITERIA); - if (res->status != CMD_SUCCESS) { - sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); - } - free_cmd_results(res); - // view must be focused for commands to affect it, so always - // refocus in-between command lists - set_focused_container(newview); - } - swayc_t *workspace = swayc_parent_by_type(focused, C_WORKSPACE); - if (workspace && workspace->fullscreen) { - set_focused_container(workspace->fullscreen); - } - for (int i = 0; i < decoration_state.csd_resources->length; ++i) { - struct wl_resource *res = decoration_state.csd_resources->items[i]; - if (res == resource) { - list_del(decoration_state.csd_resources, i); - server_decoration_enable_csd(handle); - break; - } - } - } else { - swayc_t *output = swayc_parent_by_type(focused, C_OUTPUT); - wlc_handle *h = malloc(sizeof(wlc_handle)); - if (!h) { - sway_log(L_ERROR, "Unable to allocate window handle, view handler bailing out"); - return true; - } - *h = handle; - sway_log(L_DEBUG, "Adding unmanaged window %p to %p", h, output->unmanaged); - list_add(output->unmanaged, h); - wlc_view_set_mask(handle, VISIBLE); - } - - if (return_to_workspace && current_ws != swayc_active_workspace()) { - // we were on one workspace, switched to another to add this view, - // now let's return to where we were - workspace_switch(current_ws); - set_focused_container(get_focused_container(current_ws)); - } - if (prev_focus && prev_focus->type == C_VIEW - && newview && criteria_any(newview, config->no_focus)) { - // Restore focus - swayc_t *ws = swayc_parent_by_type(newview, C_WORKSPACE); - if (!ws || ws != newview->parent - || ws->children->length + ws->floating->length != 1) { - sway_log(L_DEBUG, "no_focus: restoring focus to %s", prev_focus->name); - set_focused_container(prev_focus); - } - } - - suspend_workspace_cleanup = false; - ws_cleanup(); - return true; -} - -static void handle_view_destroyed(wlc_handle handle) { - sway_log(L_DEBUG, "Destroying window %" PRIuPTR, handle); - swayc_t *view = swayc_by_handle(handle); - - // destroy views by type - switch (wlc_view_get_type(handle)) { - // regular view created regularly - case 0: - case WLC_BIT_MODAL: - case WLC_BIT_POPUP: - break; - // DMENU has this flag, and takes view_focus, but other things with this - // flag don't - case WLC_BIT_OVERRIDE_REDIRECT: - break; - case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: - locked_container_focus = false; - break; - } - - if (view) { - bool fullscreen = swayc_is_fullscreen(view); - remove_view_from_scratchpad(view); - swayc_t *parent = destroy_view(view), *iter = NULL; - if (parent) { - ipc_event_window(parent, "close"); - - // Destroy empty workspaces - if (parent->type == C_WORKSPACE && - parent->children->length == 0 && - parent->floating->length == 0 && - swayc_active_workspace() != parent && - !parent->visible) { - parent = destroy_workspace(parent); - } - - if (fullscreen) { - iter = parent; - while (iter) { - if (iter->fullscreen) { - iter->fullscreen = NULL; - break; - } - iter = iter->parent; - } - } - - - arrange_windows(iter ? iter : parent, -1, -1); - } - } else { - // Is it unmanaged? - int i; - for (i = 0; i < root_container.children->length; ++i) { - swayc_t *output = root_container.children->items[i]; - int j; - for (j = 0; j < output->unmanaged->length; ++j) { - wlc_handle *_handle = output->unmanaged->items[j]; - if (*_handle == handle) { - list_del(output->unmanaged, j); - free(_handle); - break; - } - } - } - // Is it in the scratchpad? - for (i = 0; i < scratchpad->length; ++i) { - swayc_t *item = scratchpad->items[i]; - if (item->handle == handle) { - list_del(scratchpad, i); - destroy_view(item); - break; - } - } - } - set_focused_container(get_focused_view(&root_container)); -} - -static void handle_view_focus(wlc_handle view, bool focus) { - return; -} - -static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry *geometry) { - sway_log(L_DEBUG, "geometry request for %" PRIuPTR " %dx%d @ %d,%d", handle, - geometry->size.w, geometry->size.h, geometry->origin.x, geometry->origin.y); - // If the view is floating, then apply the geometry. - // Otherwise save the desired width/height for the view. - // This will not do anything for the time being as WLC improperly sends geometry requests - swayc_t *view = swayc_by_handle(handle); - if (view) { - view->desired_width = geometry->size.w; - view->desired_height = geometry->size.h; - - if (view->is_floating) { - floating_view_sane_size(view); - view->width = view->desired_width; - view->height = view->desired_height; - view->x = geometry->origin.x; - view->y = geometry->origin.y; - update_geometry(view); - } - } else { - wlc_view_set_geometry(handle, 0, geometry); - } -} - -static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { - swayc_t *c = swayc_by_handle(view); - pid_t pid = wlc_view_get_pid(view); - switch (state) { - case WLC_BIT_FULLSCREEN: - if (!(get_feature_policy_mask(pid) & FEATURE_FULLSCREEN)) { - sway_log(L_INFO, "Denying fullscreen to %d (%s)", pid, c->name); - break; - } - // i3 just lets it become fullscreen - wlc_view_set_state(view, state, toggle); - if (c) { - sway_log(L_DEBUG, "setting view %" PRIuPTR " %s, fullscreen %d", view, c->name, toggle); - arrange_windows(c->parent, -1, -1); - // Set it as focused window for that workspace if its going fullscreen - swayc_t *ws = swayc_parent_by_type(c, C_WORKSPACE); - if (toggle) { - // Set ws focus to c - set_focused_container_for(ws, c); - ws->fullscreen = c; - } else { - ws->fullscreen = NULL; - } - } - break; - case WLC_BIT_MAXIMIZED: - case WLC_BIT_RESIZING: - case WLC_BIT_MOVING: - break; - case WLC_BIT_ACTIVATED: - sway_log(L_DEBUG, "View %p requested to be activated", c); - break; - } - return; -} - -static void handle_view_properties_updated(wlc_handle view, uint32_t mask) { - if (mask == WLC_BIT_PROPERTY_TITLE) { - swayc_t *c = swayc_by_handle(view); - if (!c) { - return; - } - - // update window title - const char *new_name = wlc_view_get_title(view); - - if (new_name) { - if (!c->name || strcmp(c->name, new_name) != 0) { - free(c->name); - c->name = strdup(new_name); - swayc_t *p = swayc_tabbed_stacked_ancestor(c); - if (p) { - // TODO: we only got the topmost tabbed/stacked container, update borders of all containers on the path - update_container_border(get_focused_view(p)); - } else if (c->border_type == B_NORMAL) { - update_container_border(c); - } - ipc_event_window(c, "title"); - } - } - } -} - -static void handle_binding_command(struct sway_binding *binding) { - struct sway_binding *binding_copy = binding; - bool reload = false; - // if this is a reload command we need to make a duplicate of the - // binding since it will be gone after the reload has completed. - if (strcasecmp(binding->command, "reload") == 0) { - binding_copy = sway_binding_dup(binding); - if (!binding_copy) { - sway_log(L_ERROR, "Unable to duplicate binding during reload"); - return; - } - reload = true; - } - - struct cmd_results *res = handle_command(binding->command, CONTEXT_BINDING); - if (res->status != CMD_SUCCESS) { - sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); - } - ipc_event_binding_keyboard(binding_copy); - - if (reload) { // free the binding if we made a copy - free_sway_binding(binding_copy); - } - - free_cmd_results(res); -} - -static bool handle_bindsym(struct sway_binding *binding, uint32_t keysym, uint32_t keycode) { - int i; - for (i = 0; i < binding->keys->length; ++i) { - if (binding->bindcode) { - xkb_keycode_t *key = binding->keys->items[i]; - if (keycode == *key) { - handle_binding_command(binding); - return true; - } - } else { - xkb_keysym_t *key = binding->keys->items[i]; - if (keysym == *key) { - handle_binding_command(binding); - return true; - } - } - } - - return false; -} - -static bool valid_bindsym(struct sway_binding *binding) { - bool match = false; - int i; - for (i = 0; i < binding->keys->length; ++i) { - if (binding->bindcode) { - xkb_keycode_t *key = binding->keys->items[i]; - if ((match = check_key(0, *key)) == false) { - break; - } - } else { - xkb_keysym_t *key = binding->keys->items[i]; - if ((match = check_key(*key, 0)) == false) { - break; - } - } - } - - return match; -} - -static bool handle_bindsym_release(struct sway_binding *binding) { - if (binding->keys->length == 1) { - xkb_keysym_t *key = binding->keys->items[0]; - if (check_released_key(*key)) { - handle_binding_command(binding); - return true; - } - } - - return false; -} - -static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, - uint32_t key, enum wlc_key_state state) { - - if (desktop_shell.is_locked) { - return EVENT_PASSTHROUGH; - } - - // reset pointer mode on keypress - if (state == WLC_KEY_STATE_PRESSED && pointer_state.mode) { - pointer_mode_reset(); - } - - struct sway_mode *mode = config->current_mode; - - struct wlc_modifiers no_mods = { 0, 0 }; - uint32_t sym = tolower(wlc_keyboard_get_keysym_for_key(key, &no_mods)); - - int i; - - if (state == WLC_KEY_STATE_PRESSED) { - press_key(sym, key); - } else { // WLC_KEY_STATE_RELEASED - release_key(sym, key); - } - - // handle bar modifiers pressed/released - uint32_t modifier; - for (i = 0; i < config->active_bar_modifiers->length; ++i) { - modifier = *(uint32_t *)config->active_bar_modifiers->items[i]; - - switch (modifier_state_changed(modifiers->mods, modifier)) { - case MOD_STATE_PRESSED: - ipc_event_modifier(modifier, "pressed"); - break; - case MOD_STATE_RELEASED: - ipc_event_modifier(modifier, "released"); - break; - } - } - // update modifiers state - modifiers_state_update(modifiers->mods); - - // handle bindings - list_t *candidates = create_list(); - for (i = 0; i < mode->bindings->length; ++i) { - struct sway_binding *binding = mode->bindings->items[i]; - if ((modifiers->mods ^ binding->modifiers) == 0) { - switch (state) { - case WLC_KEY_STATE_PRESSED: - if (!binding->release && valid_bindsym(binding)) { - list_add(candidates, binding); - } - break; - case WLC_KEY_STATE_RELEASED: - if (binding->release && handle_bindsym_release(binding)) { - list_free(candidates); - return EVENT_HANDLED; - } - break; - } - } - } - - for (i = 0; i < candidates->length; ++i) { - struct sway_binding *binding = candidates->items[i]; - if (state == WLC_KEY_STATE_PRESSED) { - if (!binding->release && handle_bindsym(binding, sym, key)) { - list_free(candidates); - return EVENT_HANDLED; - } - } - } - - list_free(candidates); - - swayc_t *focused = get_focused_container(&root_container); - if (focused->type == C_VIEW) { - pid_t pid = wlc_view_get_pid(focused->handle); - if (!(get_feature_policy_mask(pid) & FEATURE_KEYBOARD)) { - return EVENT_HANDLED; - } - } - return EVENT_PASSTHROUGH; -} - -static bool handle_pointer_motion(wlc_handle handle, uint32_t time, double x, double y) { - if (desktop_shell.is_locked) { - return EVENT_PASSTHROUGH; - } - - double new_x = x; - double new_y = y; - // Switch to adjacent output if touching output edge. - // - // Since this doesn't currently support moving windows between outputs we - // don't do the switch if the pointer is in a mode. - if (config->seamless_mouse && !pointer_state.mode && - !pointer_state.left.held && !pointer_state.right.held && !pointer_state.scroll.held) { - - swayc_t *output = swayc_active_output(), *adjacent = NULL; - struct wlc_point abs_pos = { .x = x + output->x, .y = y + output->y }; - if (x <= 0) { // Left edge - if ((adjacent = swayc_adjacent_output(output, MOVE_LEFT, &abs_pos, false))) { - if (workspace_switch(swayc_active_workspace_for(adjacent))) { - new_x = adjacent->width; - // adjust for differently aligned outputs (well, this is - // only correct when the two outputs have the same - // resolution or the same dpi I guess, it should take - // physical attributes into account) - new_y += (output->y - adjacent->y); - } - } - } else if (x >= output->width) { // Right edge - if ((adjacent = swayc_adjacent_output(output, MOVE_RIGHT, &abs_pos, false))) { - if (workspace_switch(swayc_active_workspace_for(adjacent))) { - new_x = 0; - new_y += (output->y - adjacent->y); - } - } - } else if (y <= 0) { // Top edge - if ((adjacent = swayc_adjacent_output(output, MOVE_UP, &abs_pos, false))) { - if (workspace_switch(swayc_active_workspace_for(adjacent))) { - new_y = adjacent->height; - new_x += (output->x - adjacent->x); - } - } - } else if (y >= output->height) { // Bottom edge - if ((adjacent = swayc_adjacent_output(output, MOVE_DOWN, &abs_pos, false))) { - if (workspace_switch(swayc_active_workspace_for(adjacent))) { - new_y = 0; - new_x += (output->x - adjacent->x); - } - } - } - } - - pointer_position_set(new_x, new_y, false); - - swayc_t *focused = get_focused_container(&root_container); - if (focused->type == C_VIEW) { - pid_t pid = wlc_view_get_pid(focused->handle); - if (!(get_feature_policy_mask(pid) & FEATURE_MOUSE)) { - return EVENT_HANDLED; - } - } - - return EVENT_PASSTHROUGH; -} - -static bool swayc_border_check(swayc_t *c, const void *_origin) { - const struct wlc_point *origin = _origin; - const struct wlc_geometry title_bar = c->title_bar_geometry; - - if (c->border_type != B_NORMAL) { - return false; - } - - if (origin->x >= title_bar.origin.x && origin->y >= title_bar.origin.y - && origin->x < title_bar.origin.x + (int32_t)title_bar.size.w - && origin->y < title_bar.origin.y + (int32_t)title_bar.size.h) { - return true; - } - return false; -} - -static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, - uint32_t button, enum wlc_button_state state, const struct wlc_point *origin) { - - // Update view pointer is on - pointer_state.view = container_under_pointer(); - - struct sway_mode *mode = config->current_mode; - // handle bindings - for (int i = 0; i < mode->bindings->length; ++i) { - struct sway_binding *binding = mode->bindings->items[i]; - if ((modifiers->mods ^ binding->modifiers) == 0) { - switch (state) { - case WLC_BUTTON_STATE_PRESSED: - if (!binding->release && handle_bindsym(binding, button, 0)) { - return EVENT_HANDLED; - } - break; - case WLC_BUTTON_STATE_RELEASED: - if (binding->release && handle_bindsym(binding, button, 0)) { - return EVENT_HANDLED; - } - break; - } - } - } - - // Update pointer_state - switch (button) { - case M_LEFT_CLICK: - if (state == WLC_BUTTON_STATE_PRESSED) { - pointer_state.left.held = true; - pointer_state.left.x = origin->x; - pointer_state.left.y = origin->y; - pointer_state.left.view = pointer_state.view; - } else { - pointer_state.left.held = false; - } - break; - - case M_RIGHT_CLICK: - if (state == WLC_BUTTON_STATE_PRESSED) { - pointer_state.right.held = true; - pointer_state.right.x = origin->x; - pointer_state.right.y = origin->y; - pointer_state.right.view = pointer_state.view; - } else { - pointer_state.right.held = false; - } - break; - - case M_SCROLL_CLICK: - if (state == WLC_BUTTON_STATE_PRESSED) { - pointer_state.scroll.held = true; - pointer_state.scroll.x = origin->x; - pointer_state.scroll.y = origin->y; - pointer_state.scroll.view = pointer_state.view; - } else { - pointer_state.scroll.held = false; - } - break; - - //TODO scrolling behavior - case M_SCROLL_UP: - case M_SCROLL_DOWN: - break; - } - - // get focused window and check if to change focus on mouse click - swayc_t *focused = get_focused_container(&root_container); - - // don't change focus or mode if fullscreen - if (swayc_is_fullscreen(focused)) { - if (focused->type == C_VIEW) { - pid_t pid = wlc_view_get_pid(focused->handle); - if (!(get_feature_policy_mask(pid) & FEATURE_MOUSE)) { - return EVENT_HANDLED; - } - } - return EVENT_PASSTHROUGH; - } - - // set pointer mode only if floating mod has been set - if (config->floating_mod) { - pointer_mode_set(button, !(modifiers->mods ^ config->floating_mod)); - } - - // Check whether to change focus - swayc_t *pointer = pointer_state.view; - if (pointer) { - swayc_t *ws = swayc_parent_by_type(focused, C_WORKSPACE); - if (ws != NULL) { - swayc_t *find = container_find(ws, &swayc_border_check, origin); - if (find != NULL) { - set_focused_container(find); - return EVENT_HANDLED; - } - } - - if (focused != pointer) { - set_focused_container(pointer_state.view); - } - // Send to front if floating - if (pointer->is_floating) { - int i; - for (i = 0; i < pointer->parent->floating->length; i++) { - if (pointer->parent->floating->items[i] == pointer) { - list_del(pointer->parent->floating, i); - list_add(pointer->parent->floating, pointer); - break; - } - } - wlc_view_bring_to_front(pointer->handle); - } - } - - // Return if mode has been set - if (pointer_state.mode) { - return EVENT_HANDLED; - } - - if (focused->type == C_VIEW) { - pid_t pid = wlc_view_get_pid(focused->handle); - if (!(get_feature_policy_mask(pid) & FEATURE_MOUSE)) { - return EVENT_HANDLED; - } - } - - // Always send mouse release - if (state == WLC_BUTTON_STATE_RELEASED) { - return EVENT_PASSTHROUGH; - } - - // Finally send click - return EVENT_PASSTHROUGH; -} - -bool handle_pointer_scroll(wlc_handle view, uint32_t time, const struct wlc_modifiers* modifiers, - uint8_t axis_bits, double _amount[2]) { - if (!(modifiers->mods ^ config->floating_mod)) { - int x_amount = (int)_amount[0]; - int y_amount = (int)_amount[1]; - - if (x_amount > 0 && strcmp(config->floating_scroll_up_cmd, "")) { - handle_command(config->floating_scroll_up_cmd, CONTEXT_BINDING); - return EVENT_HANDLED; - } else if (x_amount < 0 && strcmp(config->floating_scroll_down_cmd, "")) { - handle_command(config->floating_scroll_down_cmd, CONTEXT_BINDING); - return EVENT_HANDLED; - } - - if (y_amount > 0 && strcmp(config->floating_scroll_right_cmd, "")) { - handle_command(config->floating_scroll_right_cmd, CONTEXT_BINDING); - return EVENT_HANDLED; - } else if (y_amount < 0 && strcmp(config->floating_scroll_left_cmd, "")) { - handle_command(config->floating_scroll_left_cmd, CONTEXT_BINDING); - return EVENT_HANDLED; - } - } - return EVENT_PASSTHROUGH; -} - -static void handle_wlc_ready(void) { - sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue"); - // Execute commands until there are none left - config->active = true; - while (config->cmd_queue->length) { - char *line = config->cmd_queue->items[0]; - struct cmd_results *res = handle_command(line, CONTEXT_CONFIG); - if (res->status != CMD_SUCCESS) { - sway_log(L_ERROR, "Error on line '%s': %s", line, res->error); - } - free_cmd_results(res); - free(line); - list_del(config->cmd_queue, 0); - } -} - -void register_wlc_handlers() { - wlc_set_output_created_cb(handle_output_created); - wlc_set_output_destroyed_cb(handle_output_destroyed); - wlc_set_output_resolution_cb(handle_output_resolution_change); - wlc_set_output_focus_cb(handle_output_focused); - wlc_set_output_render_post_cb(handle_output_post_render); - wlc_set_view_created_cb(handle_view_created); - wlc_set_view_destroyed_cb(handle_view_destroyed); - wlc_set_view_focus_cb(handle_view_focus); - wlc_set_view_render_pre_cb(handle_view_pre_render); - wlc_set_view_request_geometry_cb(handle_view_geometry_request); - wlc_set_view_request_state_cb(handle_view_state_request); - wlc_set_view_properties_updated_cb(handle_view_properties_updated); - wlc_set_keyboard_key_cb(handle_key); - wlc_set_pointer_motion_cb_v2(handle_pointer_motion); - wlc_set_pointer_button_cb(handle_pointer_button); - wlc_set_pointer_scroll_cb(handle_pointer_scroll); - wlc_set_compositor_ready_cb(handle_wlc_ready); - wlc_set_input_created_cb(handle_input_created); - wlc_set_input_destroyed_cb(handle_input_destroyed); -} diff --git a/sway/old/input_state.c b/sway/old/input_state.c deleted file mode 100644 index 04aafd378..000000000 --- a/sway/old/input_state.c +++ /dev/null @@ -1,490 +0,0 @@ -#include -#include -#include -#include "sway/input_state.h" -#include "sway/config.h" -#include "log.h" - -#define KEY_STATE_MAX_LENGTH 64 - -struct key_state { - /* - * Aims to store state regardless of modifiers. - * If you press a key, then hold shift, then release the key, we'll - * get two different key syms, but the same key code. This handles - * that scenario and makes sure we can use the right bindings. - */ - uint32_t key_sym; - uint32_t alt_sym; - uint32_t key_code; -}; - -static struct key_state key_state_array[KEY_STATE_MAX_LENGTH]; - -static struct key_state last_released; - -static uint32_t modifiers_state; - -void input_init(void) { - int i; - for (i = 0; i < KEY_STATE_MAX_LENGTH; ++i) { - struct key_state none = { 0, 0, 0 }; - key_state_array[i] = none; - } - - struct key_state none = { 0, 0, 0 }; - last_released = none; - - modifiers_state = 0; -} - -uint32_t modifier_state_changed(uint32_t new_state, uint32_t mod) { - if ((new_state & mod) != 0) { // pressed - if ((modifiers_state & mod) != 0) { // already pressed - return MOD_STATE_UNCHANGED; - } else { // pressed - return MOD_STATE_PRESSED; - } - } else { // not pressed - if ((modifiers_state & mod) != 0) { // released - return MOD_STATE_RELEASED; - } else { // already released - return MOD_STATE_UNCHANGED; - } - } -} - -void modifiers_state_update(uint32_t new_state) { - modifiers_state = new_state; -} - -static uint8_t find_key(uint32_t key_sym, uint32_t key_code, bool update) { - int i; - for (i = 0; i < KEY_STATE_MAX_LENGTH; ++i) { - if (0 == key_sym && 0 == key_code && key_state_array[i].key_sym == 0) { - break; - } - if (key_sym != 0 && (key_state_array[i].key_sym == key_sym - || key_state_array[i].alt_sym == key_sym)) { - break; - } - if (update && key_state_array[i].key_code == key_code) { - key_state_array[i].alt_sym = key_sym; - break; - } - if (key_sym == 0 && key_code != 0 && key_state_array[i].key_code == key_code) { - break; - } - } - return i; -} - -bool check_key(uint32_t key_sym, uint32_t key_code) { - return find_key(key_sym, key_code, false) < KEY_STATE_MAX_LENGTH; -} - -bool check_released_key(uint32_t key_sym) { - return (key_sym != 0 - && (last_released.key_sym == key_sym - || last_released.alt_sym == key_sym)); -} - -void press_key(uint32_t key_sym, uint32_t key_code) { - if (key_code == 0) { - return; - } - // Check if key exists - if (!check_key(key_sym, key_code)) { - // Check that we don't exceed buffer length - int insert = find_key(0, 0, true); - if (insert < KEY_STATE_MAX_LENGTH) { - key_state_array[insert].key_sym = key_sym; - key_state_array[insert].key_code = key_code; - } - } -} - -void release_key(uint32_t key_sym, uint32_t key_code) { - uint8_t index = find_key(key_sym, key_code, true); - if (index < KEY_STATE_MAX_LENGTH) { - last_released.key_sym = key_state_array[index].key_sym; - last_released.alt_sym = key_state_array[index].alt_sym; - last_released.key_code = key_state_array[index].key_code; - struct key_state none = { 0, 0, 0 }; - key_state_array[index] = none; - } -} - -// Pointer state and mode - -struct pointer_state pointer_state; - -static struct mode_state { - // initial view state - double x, y, w, h; - swayc_t *ptr; - // Containers used for resizing horizontally - struct { - double w; - swayc_t *ptr; - struct { - double w; - swayc_t *ptr; - } parent; - } horiz; - // Containers used for resizing vertically - struct { - double h; - swayc_t *ptr; - struct { - double h; - swayc_t *ptr; - } parent; - } vert; -} initial; - -static struct { - bool left; - bool top; -} lock; - -// initial set/unset - -static void set_initial_view(swayc_t *view) { - initial.ptr = view; - initial.x = view->x; - initial.y = view->y; - initial.w = view->width; - initial.h = view->height; -} - -static void set_initial_sibling(void) { - bool reset = true; - swayc_t *ws = swayc_active_workspace_for(initial.ptr); - if ((initial.horiz.ptr = get_swayc_in_direction_under(initial.ptr, - lock.left ? MOVE_RIGHT: MOVE_LEFT, ws))) { - initial.horiz.w = initial.horiz.ptr->width; - initial.horiz.parent.ptr = get_swayc_in_direction_under(initial.horiz.ptr, - lock.left ? MOVE_LEFT : MOVE_RIGHT, ws); - initial.horiz.parent.w = initial.horiz.parent.ptr->width; - reset = false; - } - if ((initial.vert.ptr = get_swayc_in_direction_under(initial.ptr, - lock.top ? MOVE_DOWN: MOVE_UP, ws))) { - initial.vert.h = initial.vert.ptr->height; - initial.vert.parent.ptr = get_swayc_in_direction_under(initial.vert.ptr, - lock.top ? MOVE_UP : MOVE_DOWN, ws); - initial.vert.parent.h = initial.vert.parent.ptr->height; - reset = false; - } - // If nothing will change just undo the mode - if (reset) { - pointer_state.mode = 0; - } -} - -static void reset_initial_view(void) { - initial.ptr->x = initial.x; - initial.ptr->y = initial.y; - initial.ptr->width = initial.w; - initial.ptr->height = initial.h; - arrange_windows(initial.ptr, -1, -1); - pointer_state.mode = 0; -} - -static void reset_initial_sibling(void) { - initial.horiz.ptr->width = initial.horiz.w; - initial.horiz.parent.ptr->width = initial.horiz.parent.w; - initial.vert.ptr->height = initial.vert.h; - initial.vert.parent.ptr->height = initial.vert.parent.h; - arrange_windows(initial.horiz.ptr->parent, -1, -1); - arrange_windows(initial.vert.ptr->parent, -1, -1); - pointer_state.mode = 0; -} - -void pointer_position_set(double new_x, double new_y, bool force_focus) { - double x, y; - wlc_pointer_get_position_v2(&x, &y); - pointer_state.delta.x = new_x - x; - pointer_state.delta.y = new_y - y; - - wlc_pointer_set_position_v2(new_x, new_y); - - // Update view under pointer - swayc_t *prev_view = pointer_state.view; - pointer_state.view = container_under_pointer(); - - // If pointer is in a mode, update it - if (pointer_state.mode) { - pointer_mode_update(); - // Otherwise change focus if config is set - } else if (force_focus || (prev_view != pointer_state.view && config->focus_follows_mouse)) { - if (pointer_state.view && pointer_state.view->type == C_VIEW) { - set_focused_container(pointer_state.view); - } - } -} - -void center_pointer_on(swayc_t *view) { - pointer_position_set(view->x + view->width/2, view->y + view->height/2, true); -} - -// Mode set left/right click - -static void pointer_mode_set_dragging(void) { - switch (config->dragging_key) { - case M_LEFT_CLICK: - set_initial_view(pointer_state.left.view); - break; - case M_RIGHT_CLICK: - set_initial_view(pointer_state.right.view); - break; - } - - if (initial.ptr->is_floating) { - pointer_state.mode = M_DRAGGING | M_FLOATING; - } else { - pointer_state.mode = M_DRAGGING | M_TILING; - // unset mode if we can't drag tile - if (initial.ptr->parent->type == C_WORKSPACE && - initial.ptr->parent->children->length == 1) { - pointer_state.mode = 0; - } - } -} - -static void pointer_mode_set_resizing(void) { - switch (config->resizing_key) { - case M_LEFT_CLICK: - set_initial_view(pointer_state.left.view); - break; - case M_RIGHT_CLICK: - set_initial_view(pointer_state.right.view); - break; - } - // Setup locking information - int midway_x = initial.ptr->x + initial.ptr->width/2; - int midway_y = initial.ptr->y + initial.ptr->height/2; - - double x, y; - wlc_pointer_get_position_v2(&x, &y); - lock.left = x > midway_x; - lock.top = y > midway_y; - - if (initial.ptr->is_floating) { - pointer_state.mode = M_RESIZING | M_FLOATING; - } else { - pointer_state.mode = M_RESIZING | M_TILING; - set_initial_sibling(); - } -} - -// Mode set/update/reset - -void pointer_mode_set(uint32_t button, bool condition) { - // switch on drag/resize mode - switch (pointer_state.mode & (M_DRAGGING | M_RESIZING)) { - case M_DRAGGING: - // end drag mode when 'dragging' click is unpressed - if (config->dragging_key == M_LEFT_CLICK && !pointer_state.left.held) { - pointer_state.mode = 0; - } else if (config->dragging_key == M_RIGHT_CLICK && !pointer_state.right.held) { - pointer_state.mode = 0; - } - break; - - case M_RESIZING: - // end resize mode when 'resizing' click is unpressed - if (config->resizing_key == M_LEFT_CLICK && !pointer_state.left.held) { - pointer_state.mode = 0; - } else if (config->resizing_key == M_RIGHT_CLICK && !pointer_state.right.held) { - pointer_state.mode = 0; - } - break; - - // No mode case - default: - // return if failed condition, or no view - if (!condition || !pointer_state.view) { - break; - } - - // Set mode depending on current button press - switch (button) { - // Start left-click mode - case M_LEFT_CLICK: - // if button release don't do anything - if (pointer_state.left.held) { - if (config->dragging_key == M_LEFT_CLICK) { - pointer_mode_set_dragging(); - } else if (config->resizing_key == M_LEFT_CLICK) { - pointer_mode_set_resizing(); - } - } - break; - - // Start right-click mode - case M_RIGHT_CLICK: - // if button release don't do anyhting - if (pointer_state.right.held) { - if (config->dragging_key == M_RIGHT_CLICK) { - pointer_mode_set_dragging(); - } else if (config->resizing_key == M_RIGHT_CLICK) { - pointer_mode_set_resizing(); - } - } - break; - } - } -} - -void pointer_mode_update(void) { - if (initial.ptr->type != C_VIEW) { - pointer_state.mode = 0; - return; - } - double x, y; - wlc_pointer_get_position_v2(&x, &y); - int dx = x; - int dy = y; - - switch (pointer_state.mode) { - case M_FLOATING | M_DRAGGING: - // Update position - switch (config->dragging_key) { - case M_LEFT_CLICK: - dx -= pointer_state.left.x; - dy -= pointer_state.left.y; - break; - case M_RIGHT_CLICK: - dx -= pointer_state.right.x; - dy -= pointer_state.right.y; - break; - } - - if (initial.x + dx != initial.ptr->x) { - initial.ptr->x = initial.x + dx; - } - if (initial.y + dy != initial.ptr->y) { - initial.ptr->y = initial.y + dy; - } - update_geometry(initial.ptr); - break; - - case M_FLOATING | M_RESIZING: - switch (config->resizing_key) { - case M_LEFT_CLICK: - dx -= pointer_state.left.x; - dy -= pointer_state.left.y; - initial.ptr = pointer_state.left.view; - break; - case M_RIGHT_CLICK: - dx -= pointer_state.right.x; - dy -= pointer_state.right.y; - initial.ptr = pointer_state.right.view; - break; - } - - if (lock.left) { - if (initial.w + dx > min_sane_w) { - initial.ptr->width = initial.w + dx; - } - } else { // lock.right - if (initial.w - dx > min_sane_w) { - initial.ptr->width = initial.w - dx; - initial.ptr->x = initial.x + dx; - } - } - if (lock.top) { - if (initial.h + dy > min_sane_h) { - initial.ptr->height = initial.h + dy; - } - } else { // lock.bottom - if (initial.h - dy > min_sane_h) { - initial.ptr->height = initial.h - dy; - initial.ptr->y = initial.y + dy; - } - } - update_geometry(initial.ptr); - break; - - case M_TILING | M_DRAGGING: - // swap current view under pointer with dragged view - if (pointer_state.view && pointer_state.view->type == C_VIEW - && pointer_state.view != initial.ptr - && !pointer_state.view->is_floating) { - // Swap them around - swap_container(pointer_state.view, initial.ptr); - swap_geometry(pointer_state.view, initial.ptr); - update_geometry(pointer_state.view); - update_geometry(initial.ptr); - // Set focus back to initial view - set_focused_container(initial.ptr); - // Arrange the windows - arrange_windows(&root_container, -1, -1); - } - break; - - case M_TILING | M_RESIZING: - switch (config->resizing_key) { - case M_LEFT_CLICK: - dx -= pointer_state.left.x; - dy -= pointer_state.left.y; - break; - case M_RIGHT_CLICK: - dx -= pointer_state.right.x; - dy -= pointer_state.right.y; - break; - } - - // resize if we can - if (initial.horiz.ptr) { - if (lock.left) { - // Check whether its fine to resize - if (initial.w + dx > min_sane_w && initial.horiz.w - dx > min_sane_w) { - initial.horiz.ptr->width = initial.horiz.w - dx; - initial.horiz.parent.ptr->width = initial.horiz.parent.w + dx; - } - } else { // lock.right - if (initial.w - dx > min_sane_w && initial.horiz.w + dx > min_sane_w) { - initial.horiz.ptr->width = initial.horiz.w + dx; - initial.horiz.parent.ptr->width = initial.horiz.parent.w - dx; - } - } - arrange_windows(initial.horiz.ptr->parent, -1, -1); - } - if (initial.vert.ptr) { - if (lock.top) { - if (initial.h + dy > min_sane_h && initial.vert.h - dy > min_sane_h) { - initial.vert.ptr->height = initial.vert.h - dy; - initial.vert.parent.ptr->height = initial.vert.parent.h + dy; - } - } else { // lock.bottom - if (initial.h - dy > min_sane_h && initial.vert.h + dy > min_sane_h) { - initial.vert.ptr->height = initial.vert.h + dy; - initial.vert.parent.ptr->height = initial.vert.parent.h - dy; - } - } - arrange_windows(initial.vert.ptr->parent, -1, -1); - } - default: - return; - } -} - -void pointer_mode_reset(void) { - switch (pointer_state.mode) { - case M_FLOATING | M_RESIZING: - case M_FLOATING | M_DRAGGING: - reset_initial_view(); - break; - - case M_TILING | M_RESIZING: - (void) reset_initial_sibling; - break; - - case M_TILING | M_DRAGGING: - default: - break; - } -} diff --git a/sway/old/ipc-json.c b/sway/old/ipc-json.c deleted file mode 100644 index 1579a2d99..000000000 --- a/sway/old/ipc-json.c +++ /dev/null @@ -1,521 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include -#include -#include "sway/output.h" -#include "sway/container.h" -#include "sway/input.h" -#include "sway/ipc-json.h" -#include "util.h" - -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)); - json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); - - struct wlr_box box; - if (c->type == C_OUTPUT) { - wlr_output_effective_resolution(c->_handle.output->wlr_output, - &box.width, &box.height); - } else { - box.width = c->width; - box.width = c->height; - } - - json_object_object_add(rect, "width", - json_object_new_int((int32_t)box.width)); - json_object_object_add(rect, "height", - json_object_new_int((int32_t)box.height)); - - return rect; -} - -static json_object *ipc_json_create_rect_from_geometry(struct wlc_geometry g) { - json_object *rect = json_object_new_object(); - - json_object_object_add(rect, "x", json_object_new_int(g.origin.x)); - json_object_object_add(rect, "y", json_object_new_int(g.origin.y)); - json_object_object_add(rect, "width", json_object_new_int(g.size.w)); - json_object_object_add(rect, "height", json_object_new_int(g.size.h)); - - return rect; -} - -static const char *ipc_json_border_description(swayc_t *c) { - const char *border; - - switch (c->border_type) { - case B_PIXEL: - border = "1pixel"; - break; - - case B_NORMAL: - border = "normal"; - break; - - case B_NONE: // fallthrough - default: - border = "none"; - break; - } - - return border; -} - -static const char *ipc_json_layout_description(enum swayc_layouts l) { - const char *layout; - - switch (l) { - case L_VERT: - layout = "splitv"; - break; - - case L_HORIZ: - layout = "splith"; - break; - - case L_TABBED: - layout = "tabbed"; - break; - - case L_STACKED: - layout = "stacked"; - break; - - case L_FLOATING: - layout = "floating"; - break; - - case L_NONE: // fallthrough - case L_LAYOUTS: // fallthrough; this should never happen, I'm just trying to silence compiler warnings - default: - layout = "null"; - break; - } - - return layout; -} - -static float ipc_json_child_percentage(swayc_t *c) { - float percent = 0; - swayc_t *parent = c->parent; - - if (parent) { - switch (parent->layout) { - case L_VERT: - percent = c->height / parent->height; - break; - - case L_HORIZ: - percent = c->width / parent->width; - break; - - case L_STACKED: // fallthrough - case L_TABBED: // fallthrough - percent = 1.0; - break; - - default: - break; - } - } - - return percent; -} - -static void ipc_json_describe_output(swayc_t *output, json_object *object) { - uint32_t scale = wlc_output_get_scale(output->handle); - json_object_object_add(object, "active", json_object_new_boolean(true)); - json_object_object_add(object, "primary", json_object_new_boolean(false)); - json_object_object_add(object, "layout", json_object_new_string("output")); - json_object_object_add(object, "type", json_object_new_string("output")); - json_object_object_add(object, "current_workspace", - (output->focused) ? json_object_new_string(output->focused->name) : NULL); - json_object_object_add(object, "scale", json_object_new_int(scale)); -} - -static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { - int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; - const char *layout = ipc_json_layout_description(workspace->workspace_layout); - - json_object_object_add(object, "num", json_object_new_int(num)); - json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL); - json_object_object_add(object, "type", json_object_new_string("workspace")); - json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); -} - -// window is in the scratchpad ? changed : none -static const char *ipc_json_get_scratchpad_state(swayc_t *c) { - int i; - for (i = 0; i < scratchpad->length; i++) { - if (scratchpad->items[i] == c) { - return "changed"; - } - } - return "none"; // we ignore the fresh value -} - -static void ipc_json_describe_view(swayc_t *c, json_object *object) { - json_object *props = json_object_new_object(); - json_object_object_add(object, "type", json_object_new_string((c->is_floating) ? "floating_con" : "con")); - - wlc_handle parent = wlc_view_get_parent(c->handle); - json_object_object_add(object, "scratchpad_state", - json_object_new_string(ipc_json_get_scratchpad_state(c))); - - json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); - - json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) : - c->app_id ? json_object_new_string(c->app_id) : NULL); - json_object_object_add(props, "instance", c->instance ? json_object_new_string(c->instance) : - c->app_id ? json_object_new_string(c->app_id) : NULL); - json_object_object_add(props, "title", (c->name) ? json_object_new_string(c->name) : NULL); - json_object_object_add(props, "transient_for", parent ? json_object_new_int(parent) : NULL); - json_object_object_add(object, "window_properties", props); - - json_object_object_add(object, "fullscreen_mode", - json_object_new_int(swayc_is_fullscreen(c) ? 1 : 0)); - json_object_object_add(object, "sticky", json_object_new_boolean(c->sticky)); - json_object_object_add(object, "floating", json_object_new_string( - c->is_floating ? "auto_on" : "auto_off")); // we can't state the cause - - json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL); - - if (c->parent) { - const char *layout = (c->parent->type == C_CONTAINER) ? - ipc_json_layout_description(c->parent->layout) : "none"; - const char *last_layout = (c->parent->type == C_CONTAINER) ? - ipc_json_layout_description(c->parent->prev_layout) : "none"; - json_object_object_add(object, "layout", - (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); - json_object_object_add(object, "last_split_layout", - (strcmp(last_layout, "null") == 0) ? NULL : json_object_new_string(last_layout)); - json_object_object_add(object, "workspace_layout", - json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout))); - } -} - -static void ipc_json_describe_root(swayc_t *c, 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")); -} - -json_object *ipc_json_describe_container(swayc_t *c) { - float percent = ipc_json_child_percentage(c); - - if (!(sway_assert(c, "Container must not be null."))) { - return NULL; - } - - json_object *object = json_object_new_object(); - - json_object_object_add(object, "id", json_object_new_int((int)c->id)); - json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); - json_object_object_add(object, "rect", ipc_json_create_rect(c)); - json_object_object_add(object, "visible", json_object_new_boolean(c->visible)); - json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus)); - - json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c))); - json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry)); - json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry)); - json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry)); - json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL); - json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat - // TODO: make urgency actually work once Sway supports it - json_object_object_add(object, "urgent", json_object_new_boolean(false)); - json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness)); - - switch (c->type) { - case C_ROOT: - ipc_json_describe_root(c, object); - break; - - case C_OUTPUT: - ipc_json_describe_output(c, object); - break; - - case C_CONTAINER: // fallthrough - case C_VIEW: - ipc_json_describe_view(c, object); - break; - - case C_WORKSPACE: - ipc_json_describe_workspace(c, object); - break; - - case C_TYPES: // fallthrough; this should never happen, I'm just trying to silence compiler warnings - default: - break; - } - - return object; -} - -json_object *ipc_json_describe_input(struct libinput_device *device) { - char* identifier = libinput_dev_unique_id(device); - int vendor = libinput_device_get_id_vendor(device); - int product = libinput_device_get_id_product(device); - const char *name = libinput_device_get_name(device); - double width = -1, height = -1; - int has_size = libinput_device_get_size(device, &width, &height); - - json_object *device_object = json_object_new_object(); - json_object_object_add(device_object,"identifier", - identifier ? json_object_new_string(identifier) : NULL); - json_object_object_add(device_object, - "vendor", json_object_new_int(vendor)); - json_object_object_add(device_object, - "product", json_object_new_int(product)); - json_object_object_add(device_object, - "name", json_object_new_string(name)); - if (has_size == 0) { - json_object *size_object = json_object_new_object(); - json_object_object_add(size_object, - "width", json_object_new_double(width)); - json_object_object_add(size_object, - "height", json_object_new_double(height)); - } else { - json_object_object_add(device_object, "size", NULL); - } - - struct { - enum libinput_device_capability cap; - const char *name; - // If anyone feels like implementing device-specific IPC output, - // be my guest - json_object *(*describe)(struct libinput_device *); - } caps[] = { - { LIBINPUT_DEVICE_CAP_KEYBOARD, "keyboard", NULL }, - { LIBINPUT_DEVICE_CAP_POINTER, "pointer", NULL }, - { LIBINPUT_DEVICE_CAP_TOUCH, "touch", NULL }, - { LIBINPUT_DEVICE_CAP_TABLET_TOOL, "tablet_tool", NULL }, - { LIBINPUT_DEVICE_CAP_TABLET_PAD, "tablet_pad", NULL }, - { LIBINPUT_DEVICE_CAP_GESTURE, "gesture", NULL }, -#ifdef LIBINPUT_DEVICE_CAP_SWITCH // libinput 1.7.0+ - { LIBINPUT_DEVICE_CAP_SWITCH, "switch", NULL }, -#endif - }; - - json_object *_caps = json_object_new_array(); - for (size_t i = 0; i < sizeof(caps) / sizeof(caps[0]); ++i) { - if (libinput_device_has_capability(device, caps[i].cap)) { - json_object_array_add(_caps, json_object_new_string(caps[i].name)); - if (caps[i].describe) { - json_object *desc = caps[i].describe(device); - json_object_object_add(device_object, caps[i].name, desc); - } - } - } - json_object_object_add(device_object, "capabilities", _caps); - - free(identifier); - return device_object; -} - -json_object *ipc_json_get_version() { - int major = 0, minor = 0, patch = 0; - json_object *version = json_object_new_object(); - - sscanf(SWAY_VERSION, "%u.%u.%u", &major, &minor, &patch); - - json_object_object_add(version, "human_readable", json_object_new_string(SWAY_VERSION)); - json_object_object_add(version, "variant", json_object_new_string("sway")); - json_object_object_add(version, "major", json_object_new_int(major)); - json_object_object_add(version, "minor", json_object_new_int(minor)); - json_object_object_add(version, "patch", json_object_new_int(patch)); - - return version; -} - -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)); -#ifdef ENABLE_TRAY - if (bar->tray_output) { - json_object_object_add(json, "tray_output", json_object_new_string(bar->tray_output)); - } else { - json_object_object_add(json, "tray_output", NULL); - } - if (bar->icon_theme) { - json_object_object_add(json, "icon_theme", json_object_new_string(bar->icon_theme)); - } else { - json_object_object_add(json, "icon_theme", NULL); - } - json_object_object_add(json, "tray_padding", json_object_new_int(bar->tray_padding)); - json_object_object_add(json, "activate_button", json_object_new_int(bar->activate_button)); - json_object_object_add(json, "context_button", json_object_new_int(bar->context_button)); - json_object_object_add(json, "secondary_button", json_object_new_int(bar->secondary_button)); -#endif - 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, "modifier", json_object_new_string(get_modifier_name_by_mask(bar->modifier))); - switch (bar->position) { - case DESKTOP_SHELL_PANEL_POSITION_TOP: - json_object_object_add(json, "position", json_object_new_string("top")); - break; - case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: - json_object_object_add(json, "position", json_object_new_string("bottom")); - break; - case DESKTOP_SHELL_PANEL_POSITION_LEFT: - json_object_object_add(json, "position", json_object_new_string("left")); - break; - case DESKTOP_SHELL_PANEL_POSITION_RIGHT: - json_object_object_add(json, "position", json_object_new_string("right")); - break; - } - 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(); - int i; - for (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; -} - -json_object *ipc_json_describe_container_recursive(swayc_t *c) { - json_object *object = ipc_json_describe_container(c); - int i; - - json_object *floating = json_object_new_array(); - if (c->type != C_VIEW && c->floating) { - for (i = 0; i < c->floating->length; ++i) { - swayc_t *item = c->floating->items[i]; - json_object_array_add(floating, ipc_json_describe_container_recursive(item)); - } - } - json_object_object_add(object, "floating_nodes", floating); - - json_object *children = json_object_new_array(); - if (c->type != C_VIEW && c->children) { - for (i = 0; i < c->children->length; ++i) { - json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); - } - } - json_object_object_add(object, "nodes", children); - - json_object *focus = json_object_new_array(); - if (c->type != C_VIEW) { - if (c->focused) { - json_object_array_add(focus, json_object_new_double(c->focused->id)); - } - if (c->floating) { - for (i = 0; i < c->floating->length; ++i) { - swayc_t *item = c->floating->items[i]; - if (item == c->focused) { - continue; - } - - json_object_array_add(focus, json_object_new_double(item->id)); - } - } - if (c->children) { - for (i = 0; i < c->children->length; ++i) { - swayc_t *item = c->children->items[i]; - if (item == c->focused) { - continue; - } - - json_object_array_add(focus, json_object_new_double(item->id)); - } - } - } - json_object_object_add(object, "focus", focus); - - if (c->type == C_ROOT) { - json_object *scratchpad_json = json_object_new_array(); - if (scratchpad->length > 0) { - for (i = 0; i < scratchpad->length; ++i) { - json_object_array_add(scratchpad_json, ipc_json_describe_container_recursive(scratchpad->items[i])); - } - } - json_object_object_add(object, "scratchpad", scratchpad_json); - } - - return object; -} diff --git a/sway/old/ipc-server.c b/sway/old/ipc-server.c deleted file mode 100644 index fd64e81b1..000000000 --- a/sway/old/ipc-server.c +++ /dev/null @@ -1,840 +0,0 @@ -// See https://i3wm.org/docs/ipc.html for protocol information -#ifndef __FreeBSD__ -// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0) -#define _XOPEN_SOURCE 700 -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __linux__ -struct ucred { - pid_t pid; - uid_t uid; - gid_t gid; -}; -#endif -#include "sway/ipc-json.h" -#include "sway/ipc-server.h" -#include "sway/security.h" -#include "sway/config.h" -#include "sway/commands.h" -#include "sway/input.h" -#include "sway/server.h" -#include "stringop.h" -#include "log.h" -#include "list.h" -#include "util.h" - -static int ipc_socket = -1; -static struct wl_event_source *ipc_event_source = NULL; -static struct sockaddr_un *ipc_sockaddr = NULL; -static list_t *ipc_client_list = NULL; - -static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; - -struct ipc_client { - struct wl_event_source *event_source; - struct wl_event_source *writable_event_source; - int fd; - uint32_t payload_length; - uint32_t security_policy; - enum ipc_command_type current_command; - enum ipc_command_type subscribed_events; - size_t write_buffer_len; - size_t write_buffer_size; - char *write_buffer; -}; - -struct sockaddr_un *ipc_user_sockaddr(void); -int ipc_handle_connection(int fd, uint32_t mask, void *data); -int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); -int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data); -void ipc_client_disconnect(struct ipc_client *client); -void ipc_client_handle_command(struct ipc_client *client); -bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); -void ipc_get_workspaces_callback(swayc_t *workspace, void *data); -void ipc_get_outputs_callback(swayc_t *container, void *data); -static void ipc_get_marks_callback(swayc_t *container, void *data); - -void ipc_init(void) { - ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); - if (ipc_socket == -1) { - sway_abort("Unable to create IPC socket"); - } - - ipc_sockaddr = ipc_user_sockaddr(); - - // We want to use socket name set by user, not existing socket from another sway instance. - if (getenv("SWAYSOCK") != NULL && access(getenv("SWAYSOCK"), F_OK) == -1) { - strncpy(ipc_sockaddr->sun_path, getenv("SWAYSOCK"), sizeof(ipc_sockaddr->sun_path)); - ipc_sockaddr->sun_path[sizeof(ipc_sockaddr->sun_path) - 1] = 0; - } - - unlink(ipc_sockaddr->sun_path); - if (bind(ipc_socket, (struct sockaddr *)ipc_sockaddr, sizeof(*ipc_sockaddr)) == -1) { - sway_abort("Unable to bind IPC socket"); - } - - if (listen(ipc_socket, 3) == -1) { - sway_abort("Unable to listen on IPC socket"); - } - - // Set i3 IPC socket path so that i3-msg works out of the box - setenv("I3SOCK", ipc_sockaddr->sun_path, 1); - setenv("SWAYSOCK", ipc_sockaddr->sun_path, 1); - - ipc_client_list = create_list(); - - ipc_event_source = wl_event_loop_add_fd(server.wl_event_loop, ipc_socket, - WL_EVENT_READABLE, ipc_handle_connection, NULL); -} - -void ipc_terminate(void) { - if (ipc_event_source) { - wl_event_source_remove(ipc_event_source); - } - close(ipc_socket); - unlink(ipc_sockaddr->sun_path); - - list_free(ipc_client_list); - - if (ipc_sockaddr) { - free(ipc_sockaddr); - } -} - -struct sockaddr_un *ipc_user_sockaddr(void) { - struct sockaddr_un *ipc_sockaddr = malloc(sizeof(struct sockaddr_un)); - if (ipc_sockaddr == NULL) { - sway_abort("Can't allocate ipc_sockaddr"); - } - - ipc_sockaddr->sun_family = AF_UNIX; - int path_size = sizeof(ipc_sockaddr->sun_path); - - // Env var typically set by logind, e.g. "/run/user/" - const char *dir = getenv("XDG_RUNTIME_DIR"); - if (!dir) { - dir = "/tmp"; - } - if (path_size <= snprintf(ipc_sockaddr->sun_path, path_size, - "%s/sway-ipc.%i.%i.sock", dir, getuid(), getpid())) { - sway_abort("Socket path won't fit into ipc_sockaddr->sun_path"); - } - - return ipc_sockaddr; -} - -static pid_t get_client_pid(int client_fd) { -// FreeBSD supports getting uid/gid, but not pid -#ifdef __linux__ - struct ucred ucred; - socklen_t len = sizeof(struct ucred); - - if (getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { - return -1; - } - - return ucred.pid; -#else - return -1; -#endif -} - -int ipc_handle_connection(int fd, uint32_t mask, void *data) { - (void) fd; (void) data; - sway_log(L_DEBUG, "Event on IPC listening socket"); - assert(mask == WL_EVENT_READABLE); - - int client_fd = accept(ipc_socket, NULL, NULL); - if (client_fd == -1) { - sway_log_errno(L_ERROR, "Unable to accept IPC client connection"); - return 0; - } - - int flags; - if ((flags = fcntl(client_fd, F_GETFD)) == -1 - || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { - sway_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); - close(client_fd); - return 0; - } - if ((flags = fcntl(client_fd, F_GETFL)) == -1 - || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { - sway_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); - close(client_fd); - return 0; - } - - struct ipc_client* client = malloc(sizeof(struct ipc_client)); - if (!client) { - sway_log(L_ERROR, "Unable to allocate ipc client"); - close(client_fd); - return 0; - } - client->payload_length = 0; - client->fd = client_fd; - client->subscribed_events = 0; - client->event_source = wl_event_loop_add_fd(server.wl_event_loop, client_fd, - WL_EVENT_READABLE, ipc_client_handle_readable, client); - client->writable_event_source = NULL; - - client->write_buffer_size = 128; - client->write_buffer_len = 0; - client->write_buffer = malloc(client->write_buffer_size); - if (!client->write_buffer) { - sway_log(L_ERROR, "Unable to allocate ipc client write buffer"); - close(client_fd); - return 0; - } - - pid_t pid = get_client_pid(client->fd); - client->security_policy = get_ipc_policy_mask(pid); - - sway_log(L_DEBUG, "New client: fd %d, pid %d", client_fd, pid); - - list_add(ipc_client_list, client); - - return 0; -} - -static const int ipc_header_size = sizeof(ipc_magic)+8; - -int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { - struct ipc_client *client = data; - - if (mask & WL_EVENT_ERROR) { - sway_log(L_ERROR, "IPC Client socket error, removing client"); - ipc_client_disconnect(client); - return 0; - } - - if (mask & WL_EVENT_HANGUP) { - sway_log(L_DEBUG, "Client %d hung up", client->fd); - ipc_client_disconnect(client); - return 0; - } - - sway_log(L_DEBUG, "Client %d readable", client->fd); - - int read_available; - if (ioctl(client_fd, FIONREAD, &read_available) == -1) { - sway_log_errno(L_INFO, "Unable to read IPC socket buffer size"); - ipc_client_disconnect(client); - return 0; - } - - // Wait for the rest of the command payload in case the header has already been read - if (client->payload_length > 0) { - if ((uint32_t)read_available >= client->payload_length) { - ipc_client_handle_command(client); - } - return 0; - } - - if (read_available < ipc_header_size) { - return 0; - } - - uint8_t buf[ipc_header_size]; - uint32_t *buf32 = (uint32_t*)(buf + sizeof(ipc_magic)); - // Should be fully available, because read_available >= ipc_header_size - ssize_t received = recv(client_fd, buf, ipc_header_size, 0); - if (received == -1) { - sway_log_errno(L_INFO, "Unable to receive header from IPC client"); - ipc_client_disconnect(client); - return 0; - } - - if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { - sway_log(L_DEBUG, "IPC header check failed"); - ipc_client_disconnect(client); - return 0; - } - - client->payload_length = buf32[0]; - client->current_command = (enum ipc_command_type)buf32[1]; - - if (read_available - received >= (long)client->payload_length) { - ipc_client_handle_command(client); - } - - return 0; -} - -int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { - struct ipc_client *client = data; - - if (mask & WL_EVENT_ERROR) { - sway_log(L_ERROR, "IPC Client socket error, removing client"); - ipc_client_disconnect(client); - return 0; - } - - if (mask & WL_EVENT_HANGUP) { - sway_log(L_DEBUG, "Client %d hung up", client->fd); - ipc_client_disconnect(client); - return 0; - } - - if (client->write_buffer_len <= 0) { - return 0; - } - - sway_log(L_DEBUG, "Client %d writable", client->fd); - - ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); - - if (written == -1 && errno == EAGAIN) { - return 0; - } else if (written == -1) { - sway_log_errno(L_INFO, "Unable to send data from queue to IPC client"); - ipc_client_disconnect(client); - return 0; - } - - memmove(client->write_buffer, client->write_buffer + written, client->write_buffer_len - written); - client->write_buffer_len -= written; - - if (client->write_buffer_len == 0 && client->writable_event_source) { - wl_event_source_remove(client->writable_event_source); - client->writable_event_source = NULL; - } - - return 0; -} - -void ipc_client_disconnect(struct ipc_client *client) { - if (!sway_assert(client != NULL, "client != NULL")) { - return; - } - - if (client->fd != -1) { - shutdown(client->fd, SHUT_RDWR); - } - - sway_log(L_INFO, "IPC Client %d disconnected", client->fd); - wl_event_source_remove(client->event_source); - if (client->writable_event_source) { - wl_event_source_remove(client->writable_event_source); - } - int i = 0; - while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++; - list_del(ipc_client_list, i); - free(client->write_buffer); - close(client->fd); - free(client); -} - -bool output_by_name_test(swayc_t *view, void *data) { - char *name = (char *)data; - if (view->type != C_OUTPUT) { - return false; - } - return !strcmp(name, view->name); -} - -// greedy wildcard (only "*") matching -bool mime_type_matches(const char *mime_type, const char *pattern) { - const char *wildcard = NULL; - while (*mime_type && *pattern) { - if (*pattern == '*' && !wildcard) { - wildcard = pattern; - ++pattern; - } - - if (*mime_type != *pattern) { - if (!wildcard) - return false; - - pattern = wildcard; - ++mime_type; - continue; - } - - ++mime_type; - ++pattern; - } - - while (*pattern == '*') { - ++pattern; - } - - return (*mime_type == *pattern); -} - -void ipc_client_handle_command(struct ipc_client *client) { - if (!sway_assert(client != NULL, "client != NULL")) { - return; - } - - char *buf = malloc(client->payload_length + 1); - if (!buf) { - sway_log_errno(L_INFO, "Unable to allocate IPC payload"); - ipc_client_disconnect(client); - return; - } - if (client->payload_length > 0) { - // Payload should be fully available - ssize_t received = recv(client->fd, buf, client->payload_length, 0); - if (received == -1) - { - sway_log_errno(L_INFO, "Unable to receive payload from IPC client"); - ipc_client_disconnect(client); - free(buf); - return; - } - } - buf[client->payload_length] = '\0'; - - const char *error_denied = "{ \"success\": false, \"error\": \"Permission denied\" }"; - - switch (client->current_command) { - case IPC_COMMAND: - { - if (!(client->security_policy & IPC_FEATURE_COMMAND)) { - goto exit_denied; - } - struct cmd_results *results = handle_command(buf, CONTEXT_IPC); - const char *json = cmd_results_to_json(results); - char reply[256]; - int length = snprintf(reply, sizeof(reply), "%s", json); - ipc_send_reply(client, reply, (uint32_t) length); - free_cmd_results(results); - goto exit_cleanup; - } - - case IPC_SUBSCRIBE: - { - // TODO: Check if they're permitted to use these events - struct json_object *request = json_tokener_parse(buf); - if (request == NULL) { - ipc_send_reply(client, "{\"success\": false}", 18); - sway_log_errno(L_INFO, "Failed to read request"); - goto exit_cleanup; - } - - // parse requested event types - for (int i = 0; i < json_object_array_length(request); i++) { - const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); - if (strcmp(event_type, "workspace") == 0) { - client->subscribed_events |= event_mask(IPC_EVENT_WORKSPACE); - } else if (strcmp(event_type, "barconfig_update") == 0) { - client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); - } else if (strcmp(event_type, "mode") == 0) { - client->subscribed_events |= event_mask(IPC_EVENT_MODE); - } else if (strcmp(event_type, "window") == 0) { - client->subscribed_events |= event_mask(IPC_EVENT_WINDOW); - } else if (strcmp(event_type, "modifier") == 0) { - client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER); - } else if (strcmp(event_type, "binding") == 0) { - client->subscribed_events |= event_mask(IPC_EVENT_BINDING); - } else { - ipc_send_reply(client, "{\"success\": false}", 18); - json_object_put(request); - sway_log_errno(L_INFO, "Failed to parse request"); - goto exit_cleanup; - } - } - - json_object_put(request); - - ipc_send_reply(client, "{\"success\": true}", 17); - goto exit_cleanup; - } - - case IPC_GET_WORKSPACES: - { - if (!(client->security_policy & IPC_FEATURE_GET_WORKSPACES)) { - goto exit_denied; - } - 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_GET_INPUTS: - { - if (!(client->security_policy & IPC_FEATURE_GET_INPUTS)) { - goto exit_denied; - } - json_object *inputs = json_object_new_array(); - /* TODO WLR - if (input_devices) { - for(int i = 0; ilength; i++) { - struct libinput_device *device = input_devices->items[i]; - json_object_array_add(inputs, ipc_json_describe_input(device)); - } - } - */ - const char *json_string = json_object_to_json_string(inputs); - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); - json_object_put(inputs); - goto exit_cleanup; - } - - case IPC_GET_OUTPUTS: - { - if (!(client->security_policy & IPC_FEATURE_GET_OUTPUTS)) { - goto exit_denied; - } - json_object *outputs = json_object_new_array(); - container_map(&root_container, ipc_get_outputs_callback, outputs); - const char *json_string = json_object_to_json_string(outputs); - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); - json_object_put(outputs); // free - goto exit_cleanup; - } - - case IPC_GET_TREE: - { - if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { - goto exit_denied; - } - json_object *tree = ipc_json_describe_container_recursive(&root_container); - const char *json_string = json_object_to_json_string(tree); - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); - json_object_put(tree); - goto exit_cleanup; - } - - case IPC_GET_MARKS: - { - if (!(client->security_policy & IPC_FEATURE_GET_MARKS)) { - goto exit_denied; - } - json_object *marks = json_object_new_array(); - container_map(&root_container, ipc_get_marks_callback, marks); - const char *json_string = json_object_to_json_string(marks); - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); - json_object_put(marks); - goto exit_cleanup; - } - - case IPC_GET_VERSION: - { - json_object *version = ipc_json_get_version(); - const char *json_string = json_object_to_json_string(version); - ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); - json_object_put(version); // free - goto exit_cleanup; - } - - case IPC_GET_BAR_CONFIG: - { - if (!(client->security_policy & IPC_FEATURE_GET_BAR_CONFIG)) { - goto exit_denied; - } - 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; - } - - case IPC_GET_CLIPBOARD: - // TODO WLR - break; - - default: - sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); - goto exit_cleanup; - } - -exit_denied: - ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); - sway_log(L_DEBUG, "Denied IPC client access to %i", client->current_command); - -exit_cleanup: - client->payload_length = 0; - free(buf); - return; -} - -bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { - assert(payload); - - char data[ipc_header_size]; - uint32_t *data32 = (uint32_t*)(data + sizeof(ipc_magic)); - - memcpy(data, ipc_magic, sizeof(ipc_magic)); - data32[0] = payload_length; - data32[1] = client->current_command; - - while (client->write_buffer_len + ipc_header_size + payload_length >= - client->write_buffer_size) { - client->write_buffer_size *= 2; - } - - // TODO: reduce the limit back to 4 MB when screenshooter is implemented - if (client->write_buffer_size > (1 << 28)) { // 256 MB - sway_log(L_ERROR, "Client write buffer too big, disconnecting client"); - ipc_client_disconnect(client); - return false; - } - - char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); - if (!new_buffer) { - sway_log(L_ERROR, "Unable to reallocate ipc client write buffer"); - ipc_client_disconnect(client); - return false; - } - client->write_buffer = new_buffer; - - memcpy(client->write_buffer + client->write_buffer_len, data, ipc_header_size); - client->write_buffer_len += ipc_header_size; - memcpy(client->write_buffer + client->write_buffer_len, payload, payload_length); - client->write_buffer_len += payload_length; - - if (!client->writable_event_source) { - client->writable_event_source = wl_event_loop_add_fd( - server.wl_event_loop, client->fd, WL_EVENT_WRITABLE, - ipc_client_handle_writable, client); - } - - sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); - - return true; -} - -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 - bool focused = root_container.focused == workspace->parent && workspace->parent->focused == workspace; - 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_get_outputs_callback(swayc_t *container, void *data) { - if (container->type == C_OUTPUT) { - json_object_array_add((json_object *)data, ipc_json_describe_container(container)); - } -} - -static void ipc_get_marks_callback(swayc_t *container, void *data) { - json_object *object = (json_object *)data; - if (container->marks) { - for (int i = 0; i < container->marks->length; ++i) { - char *mark = (char *)container->marks->items[i]; - json_object_array_add(object, json_object_new_string(mark)); - } - } -} - -void ipc_send_event(const char *json_string, enum ipc_command_type event) { - static struct { - enum ipc_command_type event; - enum ipc_feature feature; - } security_mappings[] = { - { IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE }, - { IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT }, - { IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE }, - { IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW }, - { IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING }, - { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT } - }; - - uint32_t security_mask = 0; - for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) { - if (security_mappings[i].event == event) { - security_mask = security_mappings[i].feature; - break; - } - } - - int i; - struct ipc_client *client; - for (i = 0; i < ipc_client_list->length; i++) { - client = ipc_client_list->items[i]; - if (!(client->security_policy & security_mask)) { - continue; - } - if ((client->subscribed_events & event_mask(event)) == 0) { - continue; - } - client->current_command = event; - if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { - sway_log_errno(L_INFO, "Unable to send reply to IPC client"); - ipc_client_disconnect(client); - } - } -} - -void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { - sway_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); // free -} - -void ipc_event_window(swayc_t *window, const char *change) { - sway_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)); - json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window)); - - const char *json_string = json_object_to_json_string(obj); - ipc_send_event(json_string, IPC_EVENT_WINDOW); - - json_object_put(obj); // free -} - -void ipc_event_barconfig_update(struct bar_config *bar) { - sway_log(L_DEBUG, "Sending barconfig_update event"); - json_object *json = ipc_json_describe_bar_config(bar); - const char *json_string = json_object_to_json_string(json); - ipc_send_event(json_string, IPC_EVENT_BARCONFIG_UPDATE); - - json_object_put(json); // free -} - -void ipc_event_mode(const char *mode) { - sway_log(L_DEBUG, "Sending mode::%s event", mode); - json_object *obj = json_object_new_object(); - json_object_object_add(obj, "change", json_object_new_string(mode)); - - const char *json_string = json_object_to_json_string(obj); - ipc_send_event(json_string, IPC_EVENT_MODE); - - json_object_put(obj); // free -} - -void ipc_event_modifier(uint32_t modifier, const char *state) { - sway_log(L_DEBUG, "Sending modifier::%s event", state); - json_object *obj = json_object_new_object(); - json_object_object_add(obj, "change", json_object_new_string(state)); - - const char *modifier_name = get_modifier_name_by_mask(modifier); - json_object_object_add(obj, "modifier", json_object_new_string(modifier_name)); - - const char *json_string = json_object_to_json_string(obj); - ipc_send_event(json_string, IPC_EVENT_MODIFIER); - - json_object_put(obj); // free -} - -static void ipc_event_binding(json_object *sb_obj) { - sway_log(L_DEBUG, "Sending binding::run event"); - json_object *obj = json_object_new_object(); - json_object_object_add(obj, "change", json_object_new_string("run")); - json_object_object_add(obj, "binding", sb_obj); - - const char *json_string = json_object_to_json_string(obj); - ipc_send_event(json_string, IPC_EVENT_BINDING); - - json_object_put(obj); // free -} - -void ipc_event_binding_keyboard(struct sway_binding *sb) { - json_object *sb_obj = json_object_new_object(); - json_object_object_add(sb_obj, "command", json_object_new_string(sb->command)); - - const char *names[10]; - - int len = get_modifier_names(names, sb->modifiers); - int i; - json_object *modifiers = json_object_new_array(); - for (i = 0; i < len; ++i) { - json_object_array_add(modifiers, json_object_new_string(names[i])); - } - - json_object_object_add(sb_obj, "event_state_mask", modifiers); - - json_object *input_codes = json_object_new_array(); - int input_code = 0; - json_object *symbols = json_object_new_array(); - json_object *symbol = NULL; - - if (sb->bindcode) { // bindcode: populate input_codes - uint32_t keycode; - for (i = 0; i < sb->keys->length; ++i) { - keycode = *(uint32_t *)sb->keys->items[i]; - json_object_array_add(input_codes, json_object_new_int(keycode)); - if (i == 0) { - input_code = keycode; - } - } - } else { // bindsym: populate symbols - uint32_t keysym; - char buffer[64]; - for (i = 0; i < sb->keys->length; ++i) { - keysym = *(uint32_t *)sb->keys->items[i]; - if (xkb_keysym_get_name(keysym, buffer, 64) > 0) { - json_object *str = json_object_new_string(buffer); - json_object_array_add(symbols, str); - if (i == 0) { - symbol = str; - } - } - } - } - - json_object_object_add(sb_obj, "input_codes", input_codes); - json_object_object_add(sb_obj, "input_code", json_object_new_int(input_code)); - json_object_object_add(sb_obj, "symbols", symbols); - json_object_object_add(sb_obj, "symbol", symbol); - json_object_object_add(sb_obj, "input_type", json_object_new_string("keyboard")); - - ipc_event_binding(sb_obj); -} diff --git a/sway/old/layout.c b/sway/old/layout.c deleted file mode 100644 index 22f81688a..000000000 --- a/sway/old/layout.c +++ /dev/null @@ -1,1773 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include "sway/config.h" -#include "sway/container.h" -#include "sway/workspace.h" -#include "sway/focus.h" -#include "sway/output.h" -#include "sway/ipc-server.h" -#include "sway/border.h" -#include "sway/layout.h" -#include "list.h" -#include "log.h" - -swayc_t root_container; -swayc_t *current_focus; -list_t *scratchpad; - -int min_sane_h = 60; -int min_sane_w = 100; - -void init_layout(void) { - root_container.id = 0; // normally assigned in new_swayc() - root_container.type = C_ROOT; - root_container.layout = L_NONE; - root_container.name = strdup("root"); - root_container.children = create_list(); - root_container.handle = -1; - root_container.visible = true; - current_focus = &root_container; - scratchpad = create_list(); -} - -int index_child(const swayc_t *child) { - swayc_t *parent = child->parent; - int i, len; - if (!child->is_floating) { - len = parent->children->length; - for (i = 0; i < len; ++i) { - if (parent->children->items[i] == child) { - break; - } - } - } else { - len = parent->floating->length; - for (i = 0; i < len; ++i) { - if (parent->floating->items[i] == child) { - break; - } - } - } - if (!sway_assert(i < len, "Stray container")) { - return -1; - } - return i; -} - -void add_child(swayc_t *parent, swayc_t *child) { - sway_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); - list_add(parent->children, child); - child->parent = parent; - // set focus for this container - if (!parent->focused) { - parent->focused = child; - } - 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); - } -} - -static double *get_height(swayc_t *cont) { - return &cont->height; -} - -static double *get_width(swayc_t *cont) { - return &cont->width; -} - -void insert_child(swayc_t *parent, swayc_t *child, int index) { - if (index > parent->children->length) { - index = parent->children->length; - } - if (index < 0) { - index = 0; - } - list_insert(parent->children, index, child); - child->parent = parent; - if (!parent->focused) { - parent->focused = child; - } - 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); - } - if (is_auto_layout(parent->layout)) { - /* go through each group, adjust the size of the first child of each group */ - double *(*get_maj_dim)(swayc_t *cont); - double *(*get_min_dim)(swayc_t *cont); - if (parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT) { - get_maj_dim = get_width; - get_min_dim = get_height; - } else { - get_maj_dim = get_height; - get_min_dim = get_width; - } - for (int i = index; i < parent->children->length;) { - int start = auto_group_start_index(parent, i); - int end = auto_group_end_index(parent, i); - swayc_t *first = parent->children->items[start]; - if (start + 1 < parent->children->length) { - /* preserve the group's dimension along major axis */ - *get_maj_dim(first) = *get_maj_dim(parent->children->items[start + 1]); - } else { - /* new group, let the apply_layout handle it */ - first->height = first->width = 0; - break; - } - double remaining = *get_min_dim(parent); - for (int j = end - 1; j > start; --j) { - swayc_t *sibling = parent->children->items[j]; - if (sibling == child) { - /* the inserted child won't yet have its minor - dimension set */ - remaining -= *get_min_dim(parent) / (end - start); - } else { - remaining -= *get_min_dim(sibling); - } - } - *get_min_dim(first) = remaining; - i = end; - } - } -} - -void add_floating(swayc_t *ws, swayc_t *child) { - sway_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", child, child->type, - child->width, child->height, ws, ws->type, ws->width, ws->height); - if (!sway_assert(ws->type == C_WORKSPACE, "Must be of workspace type")) { - return; - } - list_add(ws->floating, child); - child->parent = ws; - child->is_floating = true; - if (!ws->focused) { - ws->focused = child; - } - ipc_event_window(child, "floating"); -} - -swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { - swayc_t *parent = fixed->parent; - if (fixed->is_floating) { - if (active->is_floating) { - int i = index_child(fixed); - list_insert(parent->floating, i + 1, active); - } else { - list_add(parent->children, active); - } - } else { - if (active->is_floating) { - list_add(parent->floating, active); - } else { - int i = index_child(fixed); - if (is_auto_layout(parent->layout)) { - list_add(parent->children, active); - } else { - list_insert(parent->children, i + 1, active); - } - } - } - active->parent = parent; - // focus new child - parent->focused = active; - return active->parent; -} - -swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { - swayc_t *parent = child->parent; - if (parent == NULL) { - return NULL; - } - int i = index_child(child); - if (child->is_floating) { - parent->floating->items[i] = new_child; - } else { - parent->children->items[i] = new_child; - } - // Set parent and focus for new_child - new_child->parent = child->parent; - if (child->parent->focused == child) { - child->parent->focused = new_child; - } - child->parent = NULL; - - // Set geometry for new child - new_child->x = child->x; - new_child->y = child->y; - new_child->width = child->width; - new_child->height = child->height; - - // reset geometry for child - child->width = 0; - child->height = 0; - - // deactivate child - if (child->type == C_VIEW) { - wlc_view_set_state(child->handle, WLC_BIT_ACTIVATED, false); - } - return parent; -} - -swayc_t *remove_child(swayc_t *child) { - int i; - swayc_t *parent = child->parent; - if (child->is_floating) { - // Special case for floating views - for (i = 0; i < parent->floating->length; ++i) { - if (parent->floating->items[i] == child) { - list_del(parent->floating, i); - break; - } - } - i = 0; - } else { - for (i = 0; i < parent->children->length; ++i) { - if (parent->children->items[i] == child) { - list_del(parent->children, i); - break; - } - } - if (is_auto_layout(parent->layout) && parent->children->length) { - /* go through each group, adjust the size of the last child of each group */ - double *(*get_maj_dim)(swayc_t *cont); - double *(*get_min_dim)(swayc_t *cont); - if (parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT) { - get_maj_dim = get_width; - get_min_dim = get_height; - } else { - get_maj_dim = get_height; - get_min_dim = get_width; - } - for (int j = parent->children->length - 1; j >= i;) { - int start = auto_group_start_index(parent, j); - int end = auto_group_end_index(parent, j); - swayc_t *first = parent->children->items[start]; - if (i == start) { - /* removed element was first child in the current group, - use its size along the major axis */ - *get_maj_dim(first) = *get_maj_dim(child); - } else if (start > i) { - /* preserve the group's dimension along major axis */ - *get_maj_dim(first) = *get_maj_dim(parent->children->items[start - 1]); - } - if (end != parent->children->length) { - double remaining = *get_min_dim(parent); - for (int k = start; k < end - 1; ++k) { - swayc_t *sibling = parent->children->items[k]; - remaining -= *get_min_dim(sibling); - } - /* last element of the group gets remaining size, elements - that don't change groups keep their ratio */ - *get_min_dim((swayc_t *) parent->children->items[end - 1]) = remaining; - } /* else last group, let apply_layout handle it */ - j = start - 1; - } - } - } - // Set focused to new container - if (parent->focused == child) { - if (parent->children->length > 0) { - parent->focused = parent->children->items[i ? i-1:0]; - } else if (parent->floating && parent->floating->length) { - parent->focused = parent->floating->items[parent->floating->length - 1]; - } else { - parent->focused = NULL; - } - } - child->parent = NULL; - // deactivate view - if (child->type == C_VIEW) { - wlc_view_set_state(child->handle, WLC_BIT_ACTIVATED, false); - } - return parent; -} - -void swap_container(swayc_t *a, swayc_t *b) { - if (!sway_assert(a&&b, "parameters must be non null") || - !sway_assert(a->parent && b->parent, "containers must have parents")) { - return; - } - size_t a_index = index_child(a); - size_t b_index = index_child(b); - swayc_t *a_parent = a->parent; - swayc_t *b_parent = b->parent; - // Swap the pointers - if (a->is_floating) { - a_parent->floating->items[a_index] = b; - } else { - a_parent->children->items[a_index] = b; - } - if (b->is_floating) { - b_parent->floating->items[b_index] = a; - } else { - b_parent->children->items[b_index] = a; - } - a->parent = b_parent; - b->parent = a_parent; - if (a_parent->focused == a) { - a_parent->focused = b; - } - // don't want to double switch - if (b_parent->focused == b && a_parent != b_parent) { - b_parent->focused = a; - } -} - -void swap_geometry(swayc_t *a, swayc_t *b) { - double x = a->x; - double y = a->y; - double w = a->width; - double h = a->height; - a->x = b->x; - a->y = b->y; - a->width = b->width; - a->height = b->height; - b->x = x; - b->y = y; - b->width = w; - b->height = h; -} - -static void swap_children(swayc_t *container, int a, int b) { - if (a >= 0 && b >= 0 && a < container->children->length - && b < container->children->length - && a != b) { - swayc_t *pa = (swayc_t *)container->children->items[a]; - swayc_t *pb = (swayc_t *)container->children->items[b]; - container->children->items[a] = container->children->items[b]; - container->children->items[b] = pa; - if (is_auto_layout(container->layout)) { - size_t ga = auto_group_index(container, a); - size_t gb = auto_group_index(container, b); - if (ga != gb) { - swap_geometry(pa, pb); - } - } - } -} - -void move_container(swayc_t *container, enum movement_direction dir, int move_amt) { - enum swayc_layouts layout = L_NONE; - swayc_t *parent = container->parent; - if (container->is_floating) { - swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); - switch(dir) { - case MOVE_LEFT: - container->x = MAX(0, container->x - move_amt); - break; - case MOVE_RIGHT: - container->x = MIN(output->width - container->width, container->x + move_amt); - break; - case MOVE_UP: - container->y = MAX(0, container->y - move_amt); - break; - case MOVE_DOWN: - container->y = MIN(output->height - container->height, container->y + move_amt); - break; - default: - break; - } - update_geometry(container); - return; - } - if (container->type != C_VIEW && container->type != C_CONTAINER) { - return; - } - if (dir == MOVE_UP || dir == MOVE_DOWN) { - layout = L_VERT; - } else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { - layout = L_HORIZ; - } else if (dir == MOVE_FIRST) { - // swap first child in auto layout with currently focused child - if (is_auto_layout(parent->layout)) { - int focused_idx = index_child(container); - swayc_t *first = parent->children->items[0]; - if (focused_idx > 0) { - list_swap(parent->children, 0, focused_idx); - swap_geometry(first, container); - } - arrange_windows(parent->parent, -1, -1); - ipc_event_window(container, "move"); - set_focused_container_for(parent->parent, container); - } - return; - } else if (! (dir == MOVE_NEXT || dir == MOVE_PREV)) { - return; - } - swayc_t *child = container; - bool ascended = false; - - // View is wrapped in intermediate container which is needed for displaying - // the titlebar. Moving only the view outside of its parent container would just - // wrap it again under worspace. There would effectively be no movement, - // just a change of wrapping container. - if (child->type == C_VIEW && - parent->type == C_CONTAINER && - parent->children->length == 1 && - parent->parent->type == C_WORKSPACE) { - child = parent; - parent = parent->parent; - } - - while (true) { - sway_log(L_DEBUG, "container:%p, parent:%p, child %p,", - container,parent,child); - if (parent->layout == layout - || (layout == L_NONE && (parent->type == C_CONTAINER || parent->type == C_WORKSPACE)) /* accept any layout for next/prev direction */ - || (parent->layout == L_TABBED && layout == L_HORIZ) - || (parent->layout == L_STACKED && layout == L_VERT) - || is_auto_layout(parent->layout)) { - int diff; - // If it has ascended (parent has moved up), no container is removed - // so insert it at index, or index+1. - // if it has not, the moved container is removed, so it needs to be - // inserted at index-1, or index+1 - if (ascended) { - diff = dir == MOVE_LEFT || dir == MOVE_UP || dir == MOVE_PREV ? 0 : 1; - } else { - diff = dir == MOVE_LEFT || dir == MOVE_UP || dir == MOVE_PREV ? -1 : 1; - } - int idx = index_child(child); - int desired = idx + diff; - if (dir == MOVE_NEXT || dir == MOVE_PREV) { - // Next/Prev always wrap. - if (desired < 0) { - desired += parent->children->length; - } else if (desired >= parent->children->length) { - desired = 0; - } - } - // when it has ascended, legal insertion position is 0:len - // when it has not, legal insertion position is 0:len-1 - if (desired >= 0 && desired - ascended < parent->children->length) { - if (!ascended) { - child = parent->children->items[desired]; - // Move container into sibling container - if (child->type == C_CONTAINER) { - parent = child; - // Insert it in first/last if matching layout, otherwise - // insert it next to focused container - if (parent->layout == layout - || (parent->layout == L_TABBED && layout == L_HORIZ) - || (parent->layout == L_STACKED && layout == L_VERT) - || is_auto_layout(parent->layout)) { - desired = (diff < 0) * parent->children->length; - } else { - desired = index_child(child->focused) + 1; - } - //reset geometry - container->width = container->height = 0; - } - } - if (container->parent == parent) { - swap_children(parent, idx, desired); - } else { - swayc_t *old_parent = remove_child(container); - insert_child(parent, container, desired); - destroy_container(old_parent); - sway_log(L_DEBUG,"Moving to %p %d", parent, desired); - } - break; - } - } - // Change parent layout if we need to - if (parent->children->length == 1 && parent->layout != layout && layout != L_NONE) { - /* swayc_change_layout(parent, layout); */ - parent->layout = layout; - continue; - } - if (parent->type == C_WORKSPACE) { - // If moving to an adjacent output we need a starting position (since this - // output might border to multiple outputs). - struct wlc_point abs_pos; - get_absolute_center_position(container, &abs_pos); - - swayc_t *output = swayc_adjacent_output(parent->parent, dir, &abs_pos, true); - - if (output) { - sway_log(L_DEBUG, "Moving between outputs"); - swayc_t *old_parent = remove_child(container); - destroy_container(old_parent); - - swayc_t *dest = output->focused; - switch (dir) { - case MOVE_LEFT: - case MOVE_UP: - // reset container geometry - container->width = container->height = 0; - add_child(dest, container); - break; - case MOVE_RIGHT: - case MOVE_DOWN: - // reset container geometry - container->width = container->height = 0; - insert_child(dest, container, 0); - break; - default: - break; - } - // arrange new workspace - arrange_windows(dest, -1, -1); - set_focused_container(container); - break; - } - - // We simply cannot move any further. - if (parent->layout == layout) { - break; - } - // Create container around workspace to insert child into - parent = new_container(parent, layout); - // Previous line set the resulting container's layout to - // workspace_layout. It should have been just layout. - parent->layout = parent->parent->layout; - } - ascended = true; - child = parent; - parent = child->parent; - } - arrange_windows(parent->parent, -1, -1); - ipc_event_window(container, "move"); - set_focused_container_for(parent->parent, container); -} - -void move_container_to(swayc_t* container, swayc_t* destination) { - if (container == destination || swayc_is_parent_of(container, destination)) { - return; - } - swayc_t *parent = remove_child(container); - // Send to new destination - if (container->is_floating) { - swayc_t *ws = swayc_active_workspace_for(destination); - add_floating(ws, container); - - // If the workspace only has one child after adding one, it - // means that the workspace was just initialized. - if (ws->children->length + ws->floating->length == 1) { - ipc_event_workspace(NULL, ws, "init"); - } - } else if (destination->type == C_WORKSPACE) { - // reset container geometry - container->width = container->height = 0; - add_child(destination, container); - - // If the workspace only has one child after adding one, it - // means that the workspace was just initialized. - if (destination->children->length + destination->floating->length == 1) { - ipc_event_workspace(NULL, destination, "init"); - } - } else { - // reset container geometry - container->width = container->height = 0; - add_sibling(destination, container); - } - // Destroy old container if we need to - parent = destroy_container(parent); - // Refocus - swayc_t *op1 = swayc_parent_by_type(destination, C_OUTPUT); - swayc_t *op2 = swayc_parent_by_type(parent, C_OUTPUT); - set_focused_container(get_focused_view(op1)); - arrange_windows(op1, -1, -1); - update_visibility(op1); - if (op1 != op2) { - set_focused_container(get_focused_view(op2)); - arrange_windows(op2, -1, -1); - update_visibility(op2); - } -} - -void move_workspace_to(swayc_t* workspace, swayc_t* destination) { - if (workspace == destination || swayc_is_parent_of(workspace, destination)) { - return; - } - swayc_t *src_op = remove_child(workspace); - // reset container geometry - workspace->width = workspace->height = 0; - add_child(destination, workspace); - sort_workspaces(destination); - // Refocus destination (change to new workspace) - set_focused_container(get_focused_view(workspace)); - arrange_windows(destination, -1, -1); - update_visibility(destination); - - // make sure source output has a workspace - if (src_op->children->length == 0) { - char *ws_name = workspace_next_name(src_op->name); - swayc_t *ws = new_workspace(src_op, ws_name); - ws->is_focused = true; - free(ws_name); - } - set_focused_container(get_focused_view(src_op)); - update_visibility(src_op); -} - -static void adjust_border_geometry(swayc_t *c, struct wlc_geometry *g, - const struct wlc_size *res, int left, int right, int top, int bottom) { - - g->size.w += left + right; - if (g->origin.x - left < 0) { - g->size.w += g->origin.x - left; - } else if (g->origin.x + g->size.w - right > res->w) { - g->size.w = res->w - g->origin.x + right; - } - - g->size.h += top + bottom; - if (g->origin.y - top < 0) { - g->size.h += g->origin.y - top; - } else if (g->origin.y + g->size.h - top > res->h) { - g->size.h = res->h - g->origin.y + top; - } - - g->origin.x = MIN((uint32_t)MAX(g->origin.x - left, 0), res->w); - g->origin.y = MIN((uint32_t)MAX(g->origin.y - top, 0), res->h); - -} - -static void update_border_geometry_floating(swayc_t *c, struct wlc_geometry *geometry) { - struct wlc_geometry g = *geometry; - c->actual_geometry = g; - - swayc_t *output = swayc_parent_by_type(c, C_OUTPUT); - struct wlc_size res; - output_get_scaled_size(output->handle, &res); - - switch (c->border_type) { - case B_NONE: - break; - case B_PIXEL: - adjust_border_geometry(c, &g, &res, c->border_thickness, - c->border_thickness, c->border_thickness, c->border_thickness); - break; - case B_NORMAL: - { - int title_bar_height = config->font_height + 4; // borders + padding - - adjust_border_geometry(c, &g, &res, c->border_thickness, - c->border_thickness, title_bar_height, c->border_thickness); - - struct wlc_geometry title_bar = { - .origin = { - .x = c->actual_geometry.origin.x - c->border_thickness, - .y = c->actual_geometry.origin.y - title_bar_height - }, - .size = { - .w = c->actual_geometry.size.w + (2 * c->border_thickness), - .h = title_bar_height - } - }; - c->title_bar_geometry = title_bar; - break; - } - } - - c->border_geometry = g; - *geometry = c->actual_geometry; - - update_container_border(c); -} - -void update_layout_geometry(swayc_t *parent, enum swayc_layouts prev_layout) { - switch (parent->layout) { - case L_TABBED: - case L_STACKED: - if (prev_layout != L_TABBED && prev_layout != L_STACKED) { - // cache current geometry for all non-float children - int i; - for (i = 0; i < parent->children->length; ++i) { - swayc_t *child = parent->children->items[i]; - child->cached_geometry.origin.x = child->x; - child->cached_geometry.origin.y = child->y; - child->cached_geometry.size.w = child->width; - child->cached_geometry.size.h = child->height; - } - } - break; - default: - if (prev_layout == L_TABBED || prev_layout == L_STACKED) { - // recover cached geometry for all non-float children - int i; - for (i = 0; i < parent->children->length; ++i) { - swayc_t *child = parent->children->items[i]; - // only recoverer cached geometry if non-zero - if (!wlc_geometry_equals(&child->cached_geometry, &wlc_geometry_zero)) { - child->x = child->cached_geometry.origin.x; - child->y = child->cached_geometry.origin.y; - child->width = child->cached_geometry.size.w; - child->height = child->cached_geometry.size.h; - } - } - } - break; - } -} - -static int update_gap_geometry(swayc_t *container, struct wlc_geometry *g) { - swayc_t *ws = swayc_parent_by_type(container, C_WORKSPACE); - swayc_t *op = ws->parent; - int gap = container->is_floating ? 0 : swayc_gap(container); - if (gap % 2 != 0) { - // because gaps are implemented as "half sized margins" it's currently - // not possible to align views properly with odd sized gaps. - gap -= 1; - } - - g->origin.x = container->x + gap/2 < op->width ? container->x + gap/2 : op->width-1; - g->origin.y = container->y + gap/2 < op->height ? container->y + gap/2 : op->height-1; - g->size.w = container->width > gap ? container->width - gap : 1; - g->size.h = container->height > gap ? container->height - gap : 1; - - if ((!config->edge_gaps && gap > 0) || (config->smart_gaps && ws->children->length == 1)) { - // Remove gap against the workspace edges. Because a pixel is not - // divisable, depending on gap size and the number of siblings our view - // might be at the workspace edge without being exactly so (thus test - // with gap, and align correctly). - if (container->x - gap <= ws->x) { - g->origin.x = ws->x; - g->size.w = container->width - gap/2; - } - if (container->y - gap <= ws->y) { - g->origin.y = ws->y; - g->size.h = container->height - gap/2; - } - if (container->x + container->width + gap >= ws->x + ws->width) { - g->size.w = ws->x + ws->width - g->origin.x; - } - if (container->y + container->height + gap >= ws->y + ws->height) { - g->size.h = ws->y + ws->height - g->origin.y; - } - } - - return gap; -} - -void update_geometry(swayc_t *container) { - if (container->type != C_VIEW && container->type != C_CONTAINER) { - return; - } - - swayc_t *workspace = swayc_parent_by_type(container, C_WORKSPACE); - swayc_t *op = workspace->parent; - swayc_t *parent = container->parent; - - struct wlc_geometry geometry = { - .origin = { - .x = container->x < op->width ? container->x : op->width-1, - .y = container->y < op->height ? container->y : op->height-1 - }, - .size = { - .w = container->width, - .h = container->height, - } - }; - - int gap = 0; - - // apply inner gaps to non-tabbed/stacked containers - swayc_t *p = swayc_tabbed_stacked_ancestor(container); - if (p == NULL) { - gap = update_gap_geometry(container, &geometry); - } - - swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); - struct wlc_size size; - output_get_scaled_size(output->handle, &size); - - if (swayc_is_fullscreen(container)) { - geometry.origin.x = 0; - geometry.origin.y = 0; - geometry.size.w = size.w; - geometry.size.h = size.h; - if (op->focused == workspace) { - wlc_view_bring_to_front(container->handle); - } - - container->border_geometry = wlc_geometry_zero; - container->title_bar_geometry = wlc_geometry_zero; - border_clear(container->border); - } else if (container->is_floating) { // allocate border for floating window - update_border_geometry_floating(container, &geometry); - } else if (!container->is_floating) { // allocate border for titled window - container->border_geometry = geometry; - - int border_top = container->border_thickness; - int border_bottom = container->border_thickness; - int border_left = container->border_thickness; - int border_right = container->border_thickness; - - // handle hide_edge_borders - if (config->hide_edge_borders != E_NONE && (gap <= 0 || (config->smart_gaps && workspace->children->length == 1))) { - if (config->hide_edge_borders == E_VERTICAL || config->hide_edge_borders == E_BOTH) { - if (geometry.origin.x == workspace->x) { - border_left = 0; - } - - if (geometry.origin.x + geometry.size.w == workspace->x + workspace->width) { - border_right = 0; - } - } - - if (config->hide_edge_borders == E_HORIZONTAL || config->hide_edge_borders == E_BOTH) { - if (geometry.origin.y == workspace->y || should_hide_top_border(container, geometry.origin.y)) { - border_top = 0; - } - - if (geometry.origin.y + geometry.size.h == workspace->y + workspace->height) { - border_bottom = 0; - } - } - - if (config->hide_edge_borders == E_SMART && workspace->children->length == 1) { - border_top = 0; - border_bottom = 0; - border_left = 0; - border_right = 0; - } - } - - int title_bar_height = config->font_height + 4; //borders + padding - - if (parent->layout == L_TABBED && parent->children->length > 1) { - int i, x = 0, w, l, r; - l = parent->children->length; - w = geometry.size.w / l; - r = geometry.size.w % l; - for (i = 0; i < parent->children->length; ++i) { - swayc_t *view = parent->children->items[i]; - if (view == container) { - x = w * i; - if (i == l - 1) { - w += r; - } - break; - } - } - - struct wlc_geometry title_bar = { - .origin = { - .x = container->border_geometry.origin.x + x, - .y = container->border_geometry.origin.y - }, - .size = { - .w = w, - .h = title_bar_height - } - }; - geometry.origin.x += border_left; - geometry.origin.y += title_bar.size.h; - geometry.size.w -= (border_left + border_right); - geometry.size.h -= (border_bottom + title_bar.size.h); - container->title_bar_geometry = title_bar; - } else if (parent->layout == L_STACKED && parent->children->length > 1) { - int i, y = 0; - for (i = 0; i < parent->children->length; ++i) { - swayc_t *view = parent->children->items[i]; - if (view == container) { - y = title_bar_height * i; - } - } - - struct wlc_geometry title_bar = { - .origin = { - .x = container->border_geometry.origin.x, - .y = container->border_geometry.origin.y + y - }, - .size = { - .w = container->border_geometry.size.w, - .h = title_bar_height - } - }; - title_bar_height = title_bar_height * parent->children->length; - geometry.origin.x += border_left; - geometry.origin.y += title_bar_height; - geometry.size.w -= (border_left + border_right); - geometry.size.h -= (border_bottom + title_bar_height); - container->title_bar_geometry = title_bar; - } else { - switch (container->border_type) { - case B_NONE: - break; - case B_PIXEL: - geometry.origin.x += border_left; - geometry.origin.y += border_top; - geometry.size.w -= (border_left + border_right); - geometry.size.h -= (border_top + border_bottom); - break; - case B_NORMAL: - { - struct wlc_geometry title_bar = { - .origin = { - .x = container->border_geometry.origin.x, - .y = container->border_geometry.origin.y - }, - .size = { - .w = container->border_geometry.size.w, - .h = title_bar_height - } - }; - geometry.origin.x += border_left; - geometry.origin.y += title_bar.size.h; - geometry.size.w -= (border_left + border_right); - geometry.size.h -= (border_bottom + title_bar.size.h); - container->title_bar_geometry = title_bar; - break; - } - } - } - - container->actual_geometry = geometry; - - if (container->type == C_VIEW) { - update_container_border(container); - } - } - - if (container->type == C_VIEW) { - wlc_view_set_geometry(container->handle, 0, &geometry); - } -} - -/** - * Layout application prototypes - */ -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(swayc_t *container, const double x, - const double y, const double width, - const double height, const int start, - const int end); -static void apply_tabbed_or_stacked_layout(swayc_t *container, double x, - double y, double width, - double height); - -static void apply_auto_layout(swayc_t *container, const double x, const double y, - const double width, const double height, - enum swayc_layouts group_layout, - bool master_first); - -static void arrange_windows_r(swayc_t *container, double width, double height) { - int i; - if (width == -1 || height == -1) { - swayc_log(L_DEBUG, container, "Arranging layout for %p", container); - width = container->width; - height = container->height; - } - // pixels are indivisible. if we don't round the pixels, then the view - // calculations will be off (e.g. 50.5 + 50.5 = 101, but in reality it's - // 50 + 50 = 100). doing it here cascades properly to all width/height/x/y. - width = floor(width); - height = floor(height); - - sway_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, - container->name, container->width, container->height, container->x, - container->y); - - double x = 0, y = 0; - switch (container->type) { - case C_ROOT: - for (i = 0; i < container->children->length; ++i) { - swayc_t *output = container->children->items[i]; - sway_log(L_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); - arrange_windows_r(output, -1, -1); - } - return; - case C_OUTPUT: - { - struct wlc_size resolution; - output_get_scaled_size(container->handle, &resolution); - width = resolution.w; height = resolution.h; - // output must have correct size due to e.g. seamless mouse, - // but a workspace might be smaller depending on panels. - container->width = width; - container->height = height; - } - // arrange all workspaces: - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - arrange_windows_r(child, -1, -1); - } - // Bring all unmanaged views to the front - for (i = 0; i < container->unmanaged->length; ++i) { - wlc_handle *handle = container->unmanaged->items[i]; - wlc_view_bring_to_front(*handle); - } - return; - case C_WORKSPACE: - { - swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); - width = output->width, height = output->height; - /* TODO WLR - for (i = 0; i < desktop_shell.panels->length; ++i) { - struct panel_config *config = desktop_shell.panels->items[i]; - if (config->output == output->handle) { - struct wlc_size size = *wlc_surface_get_size(config->surface); - sway_log(L_DEBUG, "-> Found panel for this workspace: %ux%u, position: %u", size.w, size.h, config->panel_position); - switch (config->panel_position) { - case DESKTOP_SHELL_PANEL_POSITION_TOP: - y += size.h; height -= size.h; - break; - case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: - height -= size.h; - break; - case DESKTOP_SHELL_PANEL_POSITION_LEFT: - x += size.w; width -= size.w; - break; - case DESKTOP_SHELL_PANEL_POSITION_RIGHT: - width -= size.w; - break; - } - } - } - */ - int gap = swayc_gap(container); - x = container->x = x + gap; - y = container->y = y + gap; - width = container->width = width - gap * 2; - height = container->height = height - gap * 2; - sway_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", container->name, container->x, container->y); - } - // children are properly handled below - break; - case C_VIEW: - { - container->width = width; - container->height = height; - update_geometry(container); - sway_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", container->width, - container->height, container->x, container->y); - } - return; - default: - container->width = width; - container->height = height; - x = container->x; - y = container->y; - - // add gaps to top level tapped/stacked container - if (container->parent->type == C_WORKSPACE && - (container->layout == L_TABBED || container->layout == L_STACKED)) { - update_geometry(container); - width = container->border_geometry.size.w; - height = container->border_geometry.size.h; - x = container->border_geometry.origin.x; - y = container->border_geometry.origin.y; - } - - // update container size if it's a direct child in a tabbed/stacked layout - // if parent is a workspace, its actual_geometry won't be initialized - if (swayc_tabbed_stacked_parent(container) != NULL && - container->parent->type != C_WORKSPACE) { - // Use parent actual_geometry as a base for calculating - // container geometry - container->width = container->parent->actual_geometry.size.w; - container->height = container->parent->actual_geometry.size.h; - container->x = container->parent->actual_geometry.origin.x; - container->y = container->parent->actual_geometry.origin.y; - - update_geometry(container); - width = container->width = container->actual_geometry.size.w; - height = container->height = container->actual_geometry.size.h; - x = container->x = container->actual_geometry.origin.x; - y = container->y = container->actual_geometry.origin.y; - } - - break; - } - - switch (container->layout) { - case L_HORIZ: - default: - apply_horiz_layout(container, x, y, width, height, 0, - container->children->length); - break; - case L_VERT: - apply_vert_layout(container, x, y, width, height, 0, - container->children->length); - break; - case L_TABBED: - case L_STACKED: - apply_tabbed_or_stacked_layout(container, x, y, width, height); - break; - case L_AUTO_LEFT: - apply_auto_layout(container, x, y, width, height, L_VERT, true); - break; - case L_AUTO_RIGHT: - apply_auto_layout(container, x, y, width, height, L_VERT, false); - break; - case L_AUTO_TOP: - apply_auto_layout(container, x, y, width, height, L_HORIZ, true); - break; - case L_AUTO_BOTTOM: - apply_auto_layout(container, x, y, width, height, L_HORIZ, false); - break; - } - - // Arrage floating layouts for workspaces last - if (container->type == C_WORKSPACE) { - for (int i = 0; i < container->floating->length; ++i) { - swayc_t *view = container->floating->items[i]; - if (view->type == C_VIEW) { - update_geometry(view); - sway_log(L_DEBUG, "Set floating view to %.f x %.f @ %.f, %.f", - view->width, view->height, view->x, view->y); - if (swayc_is_fullscreen(view)) { - wlc_view_bring_to_front(view->handle); - } else if (!container->focused || - !swayc_is_fullscreen(container->focused)) { - wlc_view_bring_to_front(view->handle); - } - } - } - } -} - -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 = &((swayc_t *)container->children->items[i])->width; - if (*old_width <= 0) { - if (end - start > 1) { - *old_width = width / (end - start - 1); - } else { - *old_width = width; - } - } - scale += *old_width; - } - scale = width / scale; - - // Resize windows - double child_x = x; - if (scale > 0.1) { - sway_log(L_DEBUG, "Arranging %p horizontally", container); - swayc_t *focused = NULL; - for (int i = start; i < end; ++i) { - swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, - "Calculating arrangement for %p:%d (will scale %f by %f)", child, - child->type, width, scale); - child->x = child_x; - child->y = y; - - if (child == container->focused) { - focused = child; - } - - if (i == end - 1) { - double remaining_width = x + width - child_x; - arrange_windows_r(child, remaining_width, height); - } else { - arrange_windows_r(child, child->width * scale, height); - } - child_x += child->width; - } - - // update focused view border last because it may - // depend on the title bar geometry of its siblings. - if (focused && container->children->length > 1) { - update_container_border(focused); - } - } -} - -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) { - int i; - double scale = 0; - // Calculate total height - for (i = start; i < end; ++i) { - double *old_height = &((swayc_t *)container->children->items[i])->height; - if (*old_height <= 0) { - if (end - start > 1) { - *old_height = height / (end - start - 1); - } else { - *old_height = height; - } - } - scale += *old_height; - } - scale = height / scale; - - // Resize - double child_y = y; - if (scale > 0.1) { - sway_log(L_DEBUG, "Arranging %p vertically", container); - swayc_t *focused = NULL; - for (i = start; i < end; ++i) { - swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, - "Calculating arrangement for %p:%d (will scale %f by %f)", child, - child->type, height, scale); - child->x = x; - child->y = child_y; - - if (child == container->focused) { - focused = child; - } - - if (i == end - 1) { - double remaining_height = y + height - child_y; - arrange_windows_r(child, width, remaining_height); - } else { - arrange_windows_r(child, width, child->height * scale); - } - child_y += child->height; - } - - // update focused view border last because it may - // depend on the title bar geometry of its siblings. - if (focused && container->children->length > 1) { - update_container_border(focused); - } - } -} - -void apply_tabbed_or_stacked_layout(swayc_t *container, double x, double y, - double width, double height) { - int i; - swayc_t *focused = NULL; - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - child->x = x; - child->y = y; - if (child == container->focused) { - focused = child; - } else { - arrange_windows_r(child, width, height); - } - } - - if (focused) { - arrange_windows_r(focused, width, height); - } -} - -void apply_auto_layout(swayc_t *container, const double x, const double y, - const double width, const double height, - enum swayc_layouts group_layout, - bool master_first) { - // Auto layout "container" in width x height @ x, y - // using "group_layout" for each of the groups in the container. - // There is one "master" group, plus container->nb_slave_groups. - // Each group is layed out side by side following the "major" axis. - // The direction of the layout used for groups is the "minor" axis. - // Example: - // - // ---- major axis --> - // +---------+-----------+ - // | | | | - // | master | slave 1 | | - // | +-----------+ | minor axis (direction of group_layout) - // | | | | - // | | slave 2 | V - // +---------+-----------+ - // - // container with three children (one master and two slaves) and - // a single slave group (containing slave 1 and 2). The master - // group and slave group are layed out using L_VERT. - - size_t nb_groups = auto_group_count(container); - - // the target dimension of the container along the "major" axis, each - // group in the container will be layed out using "group_layout" along - // the "minor" axis. - double dim_maj; - double pos_maj; - - // x and y coords for the next group to be laid out. - const double *group_x, *group_y; - - // pos of the next group to layout along the major axis - double pos; - - // size of the next group along the major axis. - double group_dim; - - // height and width of next group to be laid out. - const double *group_h, *group_w; - - switch (group_layout) { - default: - sway_log(L_DEBUG, "Unknown layout type (%d) used in %s()", - group_layout, __func__); - /* fall through */ - case L_VERT: - dim_maj = width; - pos_maj = x; - - group_x = &pos; - group_y = &y; - group_w = &group_dim; - group_h = &height; - break; - case L_HORIZ: - dim_maj = height; - pos_maj = y; - - group_x = &x; - group_y = &pos; - group_w = &width; - group_h = &group_dim; - break; - } - - /* Determine the dimension of each of the groups in the layout. - * Dimension will be width for a VERT layout and height for a HORIZ - * layout. */ - double old_group_dim[nb_groups]; - double old_dim = 0; - for (size_t group = 0; group < nb_groups; ++group) { - int idx; - if (auto_group_bounds(container, group, &idx, NULL)) { - swayc_t *child = container->children->items[idx]; - double *dim = group_layout == L_HORIZ ? &child->height : &child->width; - if (*dim <= 0) { - // New child with uninitialized dimension - *dim = dim_maj; - if (nb_groups > 1) { - // child gets a dimension proportional to existing groups, - // it will be later scaled based on to the available size - // in the major axis. - *dim /= (nb_groups - 1); - } - } - old_dim += *dim; - old_group_dim[group] = *dim; - } - } - double scale = dim_maj / old_dim; - - /* Apply layout to each group */ - pos = pos_maj; - - for (size_t group = 0; group < nb_groups; ++group) { - int start, end; // index of first (inclusive) and last (exclusive) child in the group - if (auto_group_bounds(container, group, &start, &end)) { - // adjusted size of the group - group_dim = old_group_dim[group] * scale; - if (group == nb_groups - 1) { - group_dim = pos_maj + dim_maj - pos; // remaining width - } - sway_log(L_DEBUG, "Arranging container %p column %zu, children [%d,%d[ (%fx%f+%f,%f)", - container, group, start, end, *group_w, *group_h, *group_x, *group_y); - switch (group_layout) { - default: - case L_VERT: - apply_vert_layout(container, *group_x, *group_y, *group_w, *group_h, start, end); - break; - case L_HORIZ: - apply_horiz_layout(container, *group_x, *group_y, *group_w, *group_h, start, end); - break; - } - - /* update position for next group */ - pos += group_dim; - } - } -} - -void arrange_windows(swayc_t *container, double width, double height) { - update_visibility(container); - arrange_windows_r(container, width, height); - layout_log(&root_container, 0); -} - -void arrange_backgrounds(void) { - /* TODO WLR - struct background_config *bg; - for (int i = 0; i < desktop_shell.backgrounds->length; ++i) { - bg = desktop_shell.backgrounds->items[i]; - wlc_view_send_to_back(bg->handle); - } - */ -} - -/** - * Get swayc in the direction of newly entered output. - */ -static swayc_t *get_swayc_in_output_direction(swayc_t *output, enum movement_direction dir) { - if (!output) { - return NULL; - } - - swayc_t *ws = swayc_focus_by_type(output, C_WORKSPACE); - if (ws && ws->children->length > 0) { - switch (dir) { - case MOVE_LEFT: - // get most right child of new output - return ws->children->items[ws->children->length-1]; - case MOVE_RIGHT: - // get most left child of new output - return ws->children->items[0]; - case MOVE_UP: - case MOVE_DOWN: - { - swayc_t *focused_view = swayc_focus_by_type(ws, C_VIEW); - if (focused_view && focused_view->parent) { - swayc_t *parent = focused_view->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]; - } else if (dir == MOVE_DOWN) { - // get child furthest up on new output - return parent->children->items[0]; - } - } - return focused_view; - } - break; - } - default: - break; - } - } - - return output; -} - -swayc_t *get_swayc_in_direction_under(swayc_t *container, enum movement_direction dir, swayc_t *limit) { - if (dir == MOVE_CHILD) { - return container->focused; - } - - swayc_t *parent = container->parent; - if (dir == MOVE_PARENT) { - if (parent->type == C_OUTPUT) { - return NULL; - } else { - return parent; - } - } - - if (dir == MOVE_PREV || dir == MOVE_NEXT) { - int focused_idx = index_child(container); - if (focused_idx == -1) { - return NULL; - } else { - int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) % - parent->children->length; - if (desired < 0) { - desired += parent->children->length; - } - return parent->children->items[desired]; - } - } - - // If moving to an adjacent output we need a starting position (since this - // output might border to multiple outputs). - struct wlc_point abs_pos; - get_absolute_center_position(container, &abs_pos); - - if (container->type == C_VIEW && swayc_is_fullscreen(container)) { - sway_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); - container = swayc_parent_by_type(container, C_OUTPUT); - get_absolute_center_position(container, &abs_pos); - 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) { - sway_log(L_DEBUG, "Moving to fullscreen view"); - return container->fullscreen; - } - - swayc_t *wrap_candidate = NULL; - while (true) { - // Test if we can even make a difference here - bool can_move = false; - int desired; - int idx = index_child(container); - if (parent->type == C_ROOT) { - swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); - if (!output || output == container) { - return wrap_candidate; - } - sway_log(L_DEBUG, "Moving between outputs"); - return get_swayc_in_output_direction(output, dir); - } else { - if (is_auto_layout(parent->layout)) { - bool is_major = parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT - ? dir == MOVE_LEFT || dir == MOVE_RIGHT - : dir == MOVE_DOWN || dir == MOVE_UP; - size_t gidx = auto_group_index(parent, idx); - if (is_major) { - size_t desired_grp = gidx + (dir == MOVE_RIGHT || dir == MOVE_DOWN ? 1 : -1); - can_move = auto_group_bounds(parent, desired_grp, &desired, NULL); - } else { - desired = idx + (dir == MOVE_RIGHT || dir == MOVE_DOWN ? 1 : -1); - int start, end; - can_move = auto_group_bounds(parent, gidx, &start, &end) - && desired >= start && desired < end; - } - } else { - if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { - if (parent->layout == L_HORIZ || parent->layout == L_TABBED) { - can_move = true; - desired = idx + (dir == MOVE_LEFT ? -1 : 1); - } - } else { - if (parent->layout == L_VERT || parent->layout == L_STACKED) { - can_move = true; - desired = idx + (dir == MOVE_UP ? -1 : 1); - } - } - } - } - - if (can_move) { - if (container->is_floating) { - if (desired < 0) { - wrap_candidate = parent->floating->items[parent->floating->length-1]; - } else if (desired >= parent->floating->length){ - wrap_candidate = parent->floating->items[0]; - } else { - wrap_candidate = parent->floating->items[desired]; - } - if (wrap_candidate) { - wlc_view_bring_to_front(wrap_candidate->handle); - } - return wrap_candidate; - } else if (desired < 0 || desired >= parent->children->length) { - can_move = false; - int len = parent->children->length; - if (!wrap_candidate && len > 1) { - if (desired < 0) { - wrap_candidate = parent->children->items[len-1]; - } else { - wrap_candidate = parent->children->items[0]; - } - if (config->force_focus_wrapping) { - return wrap_candidate; - } - } - } else { - sway_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]; - } - } - if (!can_move) { - container = parent; - parent = parent->parent; - if (!parent || container == limit) { - // wrapping is the last chance - return wrap_candidate; - } - } - } -} - -swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) { - return get_swayc_in_direction_under(container, dir, NULL); -} - -void recursive_resize(swayc_t *container, double amount, enum wlc_resize_edge edge) { - int i; - bool layout_match = true; - sway_log(L_DEBUG, "Resizing %p with amount: %f", container, amount); - if (edge == WLC_RESIZE_EDGE_LEFT || edge == WLC_RESIZE_EDGE_RIGHT) { - container->width += amount; - layout_match = container->layout == L_HORIZ; - } else if (edge == WLC_RESIZE_EDGE_TOP || edge == WLC_RESIZE_EDGE_BOTTOM) { - container->height += amount; - layout_match = container->layout == L_VERT; - } - if (container->type == C_VIEW) { - update_geometry(container); - return; - } - if (layout_match) { - for (i = 0; i < container->children->length; i++) { - recursive_resize(container->children->items[i], amount/container->children->length, edge); - } - } else { - for (i = 0; i < container->children->length; i++) { - recursive_resize(container->children->items[i], amount, edge); - } - } -} - -enum swayc_layouts default_layout(swayc_t *output) { - if (config->default_layout != L_NONE) { - return config->default_layout; - } else if (config->default_orientation != L_NONE) { - return config->default_orientation; - } else if (output->width >= output->height) { - return L_HORIZ; - } else { - return L_VERT; - } -} - -bool is_auto_layout(enum swayc_layouts layout) { - return (layout >= L_AUTO_FIRST) && (layout <= L_AUTO_LAST); -} - -/** - * Return the number of master elements in a container - */ -static inline size_t auto_master_count(const swayc_t *container) { - sway_assert(container->children->length >= 0, "Container %p has (negative) children %d", - container, container->children->length); - return MIN(container->nb_master, (size_t)container->children->length); -} - -/** - * Return the number of children in the slave groups. This corresponds to the children - * that are not members of the master group. - */ -static inline size_t auto_slave_count(const swayc_t *container) { - return container->children->length - auto_master_count(container); -} - -/** - * Return the number of slave groups in the container. - */ -size_t auto_slave_group_count(const swayc_t *container) { - return MIN(container->nb_slave_groups, auto_slave_count(container)); -} - -/** - * Return the combined number of master and slave groups in the container. - */ -size_t auto_group_count(const swayc_t *container) { - return auto_slave_group_count(container) - + (container->children->length && container->nb_master ? 1 : 0); -} - -/** - * given the index of a container's child, return the index of the first child of the group - * which index is a member of. - */ -int auto_group_start_index(const swayc_t *container, int index) { - if (index < 0 || ! is_auto_layout(container->layout) - || (size_t)index < container->nb_master) { - return 0; - } else { - size_t nb_slaves = auto_slave_count(container); - size_t nb_slave_grp = auto_slave_group_count(container); - size_t grp_sz = nb_slaves / nb_slave_grp; - size_t remainder = nb_slaves % nb_slave_grp; - int idx2 = (nb_slave_grp - remainder) * grp_sz + container->nb_master; - int start_idx; - if (index < idx2) { - start_idx = ((index - container->nb_master) / grp_sz) * grp_sz + container->nb_master; - } else { - start_idx = idx2 + ((index - idx2) / (grp_sz + 1)) * (grp_sz + 1); - } - return MIN(start_idx, container->children->length); - } -} - -/** - * given the index of a container's child, return the index of the first child of the group - * that follows the one which index is a member of. - * This makes the function usable to walk through the groups in a container. - */ -int auto_group_end_index(const swayc_t *container, int index) { - if (index < 0 || ! is_auto_layout(container->layout)) { - return container->children->length; - } else { - int nxt_idx; - if ((size_t)index < container->nb_master) { - nxt_idx = auto_master_count(container); - } else { - size_t nb_slaves = auto_slave_count(container); - size_t nb_slave_grp = auto_slave_group_count(container); - size_t grp_sz = nb_slaves / nb_slave_grp; - size_t remainder = nb_slaves % nb_slave_grp; - int idx2 = (nb_slave_grp - remainder) * grp_sz + container->nb_master; - if (index < idx2) { - nxt_idx = ((index - container->nb_master) / grp_sz + 1) * grp_sz + container->nb_master; - } else { - nxt_idx = idx2 + ((index - idx2) / (grp_sz + 1) + 1) * (grp_sz + 1); - } - } - return MIN(nxt_idx, container->children->length); - } -} - -/** - * return the index of the Group containing th child of . - * The index is the order of the group along the container's major axis (starting at 0). - */ -size_t auto_group_index(const swayc_t *container, int index) { - if (index < 0) { - return 0; - } - bool master_first = (container->layout == L_AUTO_LEFT || container->layout == L_AUTO_TOP); - size_t nb_slaves = auto_slave_count(container); - if ((size_t)index < container->nb_master) { - if (master_first || nb_slaves <= 0) { - return 0; - } else { - return auto_slave_group_count(container); - } - } else { - size_t nb_slave_grp = auto_slave_group_count(container); - size_t grp_sz = nb_slaves / nb_slave_grp; - size_t remainder = nb_slaves % nb_slave_grp; - int idx2 = (nb_slave_grp - remainder) * grp_sz + container->nb_master; - size_t grp_idx; - if (index < idx2) { - grp_idx = (index - container->nb_master) / grp_sz; - } else { - grp_idx = (nb_slave_grp - remainder) + (index - idx2) / (grp_sz + 1) ; - } - return grp_idx + (master_first && container-> nb_master ? 1 : 0); - } -} - -/** - * Return the first index (inclusive) and last index (exclusive) of the elements of a group in - * an auto layout. - * If the bounds of the given group can be calculated, they are returned in the start/end - * parameters (int pointers) and the return value will be true. - * The indexes are passed by reference and can be NULL. - */ -bool auto_group_bounds(const swayc_t *container, size_t group_index, int *start, int *end) { - size_t nb_grp = auto_group_count(container); - if (group_index >= nb_grp) { - return false; - } - bool master_first = (container->layout == L_AUTO_LEFT || container->layout == L_AUTO_TOP); - size_t nb_master = auto_master_count(container); - size_t nb_slave_grp = auto_slave_group_count(container); - int g_start, g_end; - if (nb_master && (master_first ? group_index == 0 : group_index == nb_grp - 1)) { - g_start = 0; - g_end = nb_master; - } else { - size_t nb_slaves = auto_slave_count(container); - size_t grp_sz = nb_slaves / nb_slave_grp; - size_t remainder = nb_slaves % nb_slave_grp; - size_t g0 = master_first && container->nb_master ? 1 : 0; - size_t g1 = g0 + nb_slave_grp - remainder; - if (group_index < g1) { - g_start = container->nb_master + (group_index - g0) * grp_sz; - g_end = g_start + grp_sz; - } else { - size_t g2 = group_index - g1; - g_start = container->nb_master - + (nb_slave_grp - remainder) * grp_sz - + g2 * (grp_sz + 1); - g_end = g_start + grp_sz + 1; - } - } - if (start) { - *start = g_start; - } - if (end) { - *end = g_end; - } - return true; -} diff --git a/sway/old/output.c b/sway/old/output.c deleted file mode 100644 index edfcac981..000000000 --- a/sway/old/output.c +++ /dev/null @@ -1,278 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include "sway/output.h" -#include "log.h" -#include "list.h" - -void output_get_scaled_size(wlc_handle handle, struct wlc_size *size) { - *size = *wlc_output_get_resolution(handle); - uint32_t scale = wlc_output_get_scale(handle); - size->w /= scale; - size->h /= scale; -} - -swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos) { - swayc_t *output = NULL; - // If there is no output directly next to the current one, use - // swayc_opposite_output to wrap. - if (strcasecmp(name, "left") == 0) { - output = swayc_adjacent_output(NULL, MOVE_LEFT, abs_pos, true); - if (!output) { - output = swayc_opposite_output(MOVE_RIGHT, abs_pos); - } - } else if (strcasecmp(name, "right") == 0) { - output = swayc_adjacent_output(NULL, MOVE_RIGHT, abs_pos, true); - if (!output) { - output = swayc_opposite_output(MOVE_LEFT, abs_pos); - } - } else if (strcasecmp(name, "up") == 0) { - output = swayc_adjacent_output(NULL, MOVE_UP, abs_pos, true); - if (!output) { - output = swayc_opposite_output(MOVE_DOWN, abs_pos); - } - } else if (strcasecmp(name, "down") == 0) { - output = swayc_adjacent_output(NULL, MOVE_DOWN, abs_pos, true); - if (!output) { - output = swayc_opposite_output(MOVE_UP, abs_pos); - } - } else { - for(int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c->type == C_OUTPUT && strcasecmp(c->name, name) == 0) { - return c; - } - } - } - return output; -} - -swayc_t *swayc_opposite_output(enum movement_direction dir, - const struct wlc_point *abs_pos) { - - // Search through all the outputs and pick the output whose edge covers the - // given position, and is at leftmost/rightmost/upmost/downmost side of the - // screen (decided by the direction given). - swayc_t *opposite = NULL; - char *dir_text = NULL; - switch(dir) { - case MOVE_LEFT: - case MOVE_RIGHT: ; - for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (abs_pos->y >= c->y && abs_pos->y <= c->y + c->height) { - if (!opposite) { - opposite = c; - } else if ((dir == MOVE_LEFT && c->x < opposite->x) - || (dir == MOVE_RIGHT && c->x > opposite->x)) { - opposite = c; - } - } - } - dir_text = dir == MOVE_LEFT ? "leftmost" : "rightmost"; - break; - case MOVE_UP: - case MOVE_DOWN: ; - for (int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (abs_pos->x >= c->x && abs_pos->x <= c->x + c->width) { - if (!opposite) { - opposite = c; - } else if ((dir == MOVE_UP && c->y < opposite->y) - || (dir == MOVE_DOWN && c->y > opposite->y)) { - opposite = c; - } - } - } - dir_text = dir == MOVE_UP ? "upmost" : "downmost"; - break; - default: - sway_abort("Function called with invalid argument."); - break; - } - if (opposite) { - sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s from y-position %i", - opposite->name, opposite->width, opposite->height, opposite->x, opposite->y, - dir_text, abs_pos->y); - } - return opposite; -} - -// Position is where on the edge (as absolute position) the adjacent output should be searched for. -swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir, - const struct wlc_point *abs_pos, bool pick_closest) { - - if (!output) { - output = swayc_active_output(); - } - // In order to find adjacent outputs we need to test that the outputs are - // aligned on one axis (decided by the direction given) and that the given - // position is within the edge of the adjacent output. If no such output - // exists we pick the adjacent output within the edge that is closest to - // the given position, if any. - swayc_t *adjacent = NULL; - char *dir_text = NULL; - switch(dir) { - case MOVE_LEFT: - case MOVE_RIGHT: ; - double delta_y = 0; - for(int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c == output || c->type != C_OUTPUT) { - continue; - } - bool x_aligned = dir == MOVE_LEFT ? - c->x + c->width == output->x : - c->x == output->x + output->width; - if (!x_aligned) { - continue; - } - if (abs_pos->y >= c->y && abs_pos->y <= c->y + c->height) { - delta_y = 0; - adjacent = c; - break; - } else if (pick_closest) { - // track closest adjacent output - double top_y = c->y, bottom_y = c->y + c->height; - if (top_y >= output->y && top_y <= output->y + output->height) { - double delta = top_y - abs_pos->y; - if (delta < 0) delta = -delta; - if (delta < delta_y || !adjacent) { - delta_y = delta; - adjacent = c; - } - } - // we check both points and pick the closest - if (bottom_y >= output->y && bottom_y <= output->y + output->height) { - double delta = bottom_y - abs_pos->y; - if (delta < 0) delta = -delta; - if (delta < delta_y || !adjacent) { - delta_y = delta; - adjacent = c; - } - } - } - } - dir_text = dir == MOVE_LEFT ? "left of" : "right of"; - if (adjacent && delta_y == 0) { - sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (y-position %i)", - adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y, - dir_text, output->name, abs_pos->y); - } else if (adjacent) { - // so we end up picking the closest adjacent output because - // there is no directly adjacent to the given position - sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (y-position %i, delta: %.0f)", - adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y, - dir_text, output->name, abs_pos->y, delta_y); - } - break; - case MOVE_UP: - case MOVE_DOWN: ; - double delta_x = 0; - for(int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c == output || c->type != C_OUTPUT) { - continue; - } - bool y_aligned = dir == MOVE_UP ? - c->y + c->height == output->y : - c->y == output->y + output->height; - if (!y_aligned) { - continue; - } - if (abs_pos->x >= c->x && abs_pos->x <= c->x + c->width) { - delta_x = 0; - adjacent = c; - break; - } else if (pick_closest) { - // track closest adjacent output - double left_x = c->x, right_x = c->x + c->width; - if (left_x >= output->x && left_x <= output->x + output->width) { - double delta = left_x - abs_pos->x; - if (delta < 0) delta = -delta; - if (delta < delta_x || !adjacent) { - delta_x = delta; - adjacent = c; - } - } - // we check both points and pick the closest - if (right_x >= output->x && right_x <= output->x + output->width) { - double delta = right_x - abs_pos->x; - if (delta < 0) delta = -delta; - if (delta < delta_x || !adjacent) { - delta_x = delta; - adjacent = c; - } - } - } - } - dir_text = dir == MOVE_UP ? "above" : "below"; - if (adjacent && delta_x == 0) { - sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (x-position %i)", - adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y, - dir_text, output->name, abs_pos->x); - } else if (adjacent) { - // so we end up picking the closest adjacent output because - // there is no directly adjacent to the given position - sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (x-position %i, delta: %.0f)", - adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y, - dir_text, output->name, abs_pos->x, delta_x); - } - break; - default: - sway_abort("Function called with invalid argument."); - break; - } - return adjacent; -} - -void get_absolute_position(swayc_t *container, struct wlc_point *point) { - if (!container || !point) - sway_abort("Need container and wlc_point (was %p, %p).", container, point); - - if (container->type == C_OUTPUT) { - // Coordinates are already absolute. - point->x = container->x; - point->y = container->y; - } else { - 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. - point->x = output->x; - point->y = output->y; - } else { - point->x = output->x + container->x; - point->y = output->y + container->y; - } - } -} - -void get_absolute_center_position(swayc_t *container, struct wlc_point *point) { - get_absolute_position(container, point); - point->x += container->width/2; - point->y += container->height/2; -} - -static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { - swayc_t *a = *(void **)_a; - swayc_t *b = *(void **)_b; - int retval = 0; - - if (isdigit(a->name[0]) && isdigit(b->name[0])) { - int a_num = strtol(a->name, NULL, 10); - int b_num = strtol(b->name, NULL, 10); - retval = (a_num < b_num) ? -1 : (a_num > b_num); - } else if (isdigit(a->name[0])) { - retval = -1; - } else if (isdigit(b->name[0])) { - retval = 1; - } - - return retval; -} - -void sort_workspaces(swayc_t *output) { - list_stable_sort(output->children, sort_workspace_cmp_qsort); -} diff --git a/sway/old/security.c b/sway/old/security.c deleted file mode 100644 index fcd70f9d6..000000000 --- a/sway/old/security.c +++ /dev/null @@ -1,228 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include "sway/config.h" -#include "sway/security.h" -#include "log.h" - -static bool validate_ipc_target(const char *program) { - struct stat sb; - - sway_log(L_DEBUG, "Validating IPC target '%s'", program); - - if (!strcmp(program, "*")) { - return true; - } - if (lstat(program, &sb) == -1) { - return false; - } - if (!S_ISREG(sb.st_mode)) { - sway_log(L_ERROR, - "IPC target '%s' MUST be/point at an existing regular file", - program); - return false; - } - if (sb.st_uid != 0) { -#ifdef NDEBUG - sway_log(L_ERROR, "IPC target '%s' MUST be owned by root", program); - return false; -#else - sway_log(L_INFO, "IPC target '%s' MUST be owned by root (waived for debug build)", program); - return true; -#endif - } - if (sb.st_mode & S_IWOTH) { - sway_log(L_ERROR, "IPC target '%s' MUST NOT be world writable", program); - return false; - } - - return true; -} - -struct feature_policy *alloc_feature_policy(const char *program) { - uint32_t default_policy = 0; - - if (!validate_ipc_target(program)) { - return NULL; - } - for (int i = 0; i < config->feature_policies->length; ++i) { - struct feature_policy *policy = config->feature_policies->items[i]; - if (strcmp(policy->program, "*") == 0) { - default_policy = policy->features; - break; - } - } - - struct feature_policy *policy = malloc(sizeof(struct feature_policy)); - if (!policy) { - return NULL; - } - policy->program = strdup(program); - if (!policy->program) { - free(policy); - return NULL; - } - policy->features = default_policy; - - return policy; -} - -struct ipc_policy *alloc_ipc_policy(const char *program) { - uint32_t default_policy = 0; - - if (!validate_ipc_target(program)) { - return NULL; - } - for (int i = 0; i < config->ipc_policies->length; ++i) { - struct ipc_policy *policy = config->ipc_policies->items[i]; - if (strcmp(policy->program, "*") == 0) { - default_policy = policy->features; - break; - } - } - - struct ipc_policy *policy = malloc(sizeof(struct ipc_policy)); - if (!policy) { - return NULL; - } - policy->program = strdup(program); - if (!policy->program) { - free(policy); - return NULL; - } - policy->features = default_policy; - - return policy; -} - -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; -} - -static const char *get_pid_exe(pid_t pid) { -#ifdef __FreeBSD__ - const char *fmt = "/proc/%d/file"; -#else - const char *fmt = "/proc/%d/exe"; -#endif - int pathlen = snprintf(NULL, 0, fmt, pid); - char *path = malloc(pathlen + 1); - if (path) { - snprintf(path, pathlen + 1, fmt, pid); - } - - static char link[2048]; - - ssize_t len = !path ? -1 : readlink(path, link, sizeof(link)); - if (len < 0) { - sway_log(L_INFO, - "WARNING: unable to read %s for security check. Using default policy.", - path); - strcpy(link, "*"); - } else { - link[len] = '\0'; - } - free(path); - - return link; -} - -struct feature_policy *get_feature_policy(const char *name) { - struct feature_policy *policy = NULL; - - for (int i = 0; i < config->feature_policies->length; ++i) { - struct feature_policy *p = config->feature_policies->items[i]; - if (strcmp(p->program, name) == 0) { - policy = p; - break; - } - } - if (!policy) { - policy = alloc_feature_policy(name); - sway_assert(policy, "Unable to allocate security policy"); - if (policy) { - list_add(config->feature_policies, policy); - } - } - return policy; -} - -uint32_t get_feature_policy_mask(pid_t pid) { - uint32_t default_policy = 0; - const char *link = get_pid_exe(pid); - - for (int i = 0; i < config->feature_policies->length; ++i) { - struct feature_policy *policy = config->feature_policies->items[i]; - if (strcmp(policy->program, "*") == 0) { - default_policy = policy->features; - } - if (strcmp(policy->program, link) == 0) { - return policy->features; - } - } - - return default_policy; -} - -uint32_t get_ipc_policy_mask(pid_t pid) { - uint32_t default_policy = 0; - const char *link = get_pid_exe(pid); - - for (int i = 0; i < config->ipc_policies->length; ++i) { - struct ipc_policy *policy = config->ipc_policies->items[i]; - if (strcmp(policy->program, "*") == 0) { - default_policy = policy->features; - } - if (strcmp(policy->program, link) == 0) { - return policy->features; - } - } - - return default_policy; -} - -uint32_t get_command_policy_mask(const char *cmd) { - uint32_t default_policy = 0; - - for (int i = 0; i < config->command_policies->length; ++i) { - struct command_policy *policy = config->command_policies->items[i]; - if (strcmp(policy->command, "*") == 0) { - default_policy = policy->context; - } - if (strcmp(policy->command, cmd) == 0) { - return policy->context; - } - } - - return default_policy; -} - -const char *command_policy_str(enum command_context context) { - switch (context) { - case CONTEXT_ALL: - return "all"; - case CONTEXT_CONFIG: - return "config"; - case CONTEXT_BINDING: - return "binding"; - case CONTEXT_IPC: - return "IPC"; - case CONTEXT_CRITERIA: - return "criteria"; - default: - return "unknown"; - } -} diff --git a/sway/old/workspace.c b/sway/old/workspace.c deleted file mode 100644 index 14cde1465..000000000 --- a/sway/old/workspace.c +++ /dev/null @@ -1,373 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include -#include -#include "sway/ipc-server.h" -#include "sway/workspace.h" -#include "sway/layout.h" -#include "sway/container.h" -#include "sway/handlers.h" -#include "sway/config.h" -#include "sway/focus.h" -#include "stringop.h" -#include "util.h" -#include "list.h" -#include "log.h" -#include "ipc.h" - -char *prev_workspace_name = NULL; -struct workspace_by_number_data { - int len; - const char *cset; - const char *name; -}; - -static bool workspace_valid_on_output(const char *output_name, const char *ws_name) { - int i; - for (i = 0; i < config->workspace_outputs->length; ++i) { - struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcasecmp(wso->workspace, ws_name) == 0) { - if (strcasecmp(wso->output, output_name) != 0) { - return false; - } - } - } - - return true; -} - -char *workspace_next_name(const char *output_name) { - sway_log(L_DEBUG, "Workspace: Generating new workspace name for output %s", output_name); - int i; - int l = 1; - // Scan all workspace bindings to find the next available workspace name, - // if none are found/available then default to a number - struct sway_mode *mode = config->current_mode; - - int order = INT_MAX; - char *target = NULL; - for (i = 0; i < mode->bindings->length; ++i) { - struct sway_binding *binding = mode->bindings->items[i]; - char *cmdlist = strdup(binding->command); - char *dup = cmdlist; - char *name = NULL; - - // workspace n - char *cmd = argsep(&cmdlist, " "); - if (cmdlist) { - name = argsep(&cmdlist, ",;"); - } - - if (strcmp("workspace", cmd) == 0 && name) { - sway_log(L_DEBUG, "Got valid workspace command for target: '%s'", name); - char *_target = strdup(name); - strip_quotes(_target); - while (isspace(*_target)) - _target++; - - // Make sure that the command references an actual workspace - // not a command about workspaces - if (strcmp(_target, "next") == 0 || - strcmp(_target, "prev") == 0 || - strcmp(_target, "next_on_output") == 0 || - strcmp(_target, "prev_on_output") == 0 || - strcmp(_target, "number") == 0 || - strcmp(_target, "back_and_forth") == 0 || - strcmp(_target, "current") == 0) - { - free(_target); - free(dup); - continue; - } - - // Make sure that the workspace doesn't already exist - if (workspace_by_name(_target)) { - free(_target); - free(dup); - continue; - } - - // make sure that the workspace can appear on the given - // output - if (!workspace_valid_on_output(output_name, _target)) { - free(_target); - free(dup); - continue; - } - - if (binding->order < order) { - order = binding->order; - free(target); - target = _target; - sway_log(L_DEBUG, "Workspace: Found free name %s", _target); - } - } - free(dup); - } - if (target != NULL) { - return target; - } - // As a fall back, get the current number of active workspaces - // and return that + 1 for the next workspace's name - int ws_num = root_container.children->length; - if (ws_num >= 10) { - l = 2; - } else if (ws_num >= 100) { - l = 3; - } - char *name = malloc(l + 1); - if (!name) { - sway_log(L_ERROR, "Could not allocate workspace name"); - return NULL; - } - sprintf(name, "%d", ws_num++); - return name; -} - -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) { - struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcasecmp(wso->workspace, name) == 0) - { - // Find output to use if it exists - e = root_container.children->length; - for (i = 0; i < e; ++i) { - parent = root_container.children->items[i]; - if (strcmp(parent->name, wso->output) == 0) { - return new_workspace(parent, name); - } - } - break; - } - } - // Otherwise create a new one - parent = get_focused_container(&root_container); - parent = swayc_parent_by_type(parent, C_OUTPUT); - return new_workspace(parent, name); -} - -static bool _workspace_by_name(swayc_t *view, void *data) { - return (view->type == C_WORKSPACE) && - (strcasecmp(view->name, (char *) data) == 0); -} - -swayc_t *workspace_by_name(const char* name) { - if (strcmp(name, "prev") == 0) { - return workspace_prev(); - } - else if (strcmp(name, "prev_on_output") == 0) { - return workspace_output_prev(); - } - else if (strcmp(name, "next") == 0) { - return workspace_next(); - } - else if (strcmp(name, "next_on_output") == 0) { - return workspace_output_next(); - } - else if (strcmp(name, "current") == 0) { - return swayc_active_workspace(); - } - else { - return swayc_by_test(&root_container, _workspace_by_name, (void *) name); - } -} - -static bool _workspace_by_number(swayc_t *view, void *data) { - if (view->type != C_WORKSPACE) { - return false; - } - struct workspace_by_number_data *wbnd = data; - int a = strspn(view->name, wbnd->cset); - return a == wbnd->len && strncmp(view->name, wbnd->name, a) == 0; -} -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 swayc_by_test(&root_container, _workspace_by_number, (void *) &wbnd); -} - -/** - * Get the previous or next workspace on the specified output. - * Wraps around at 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) { - if (!sway_assert(output->type == C_OUTPUT, "Argument must be an output, is %d", output->type)) { - return NULL; - } - - int i; - for (i = 0; i < output->children->length; i++) { - if (output->children->items[i] == output->focused) { - return output->children->items[wrap(i + (next ? 1 : -1), output->children->length)]; - } - } - - // Doesn't happen, at worst the for loop returns the previously active workspace - return NULL; -} - -/** - * Get the previous or next workspace. If the first/last workspace on an output is active, - * proceed to the previous/next output's previous/next workspace. - * If 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) { - if (!sway_assert(workspace->type == C_WORKSPACE, "Argument must be a workspace, is %d", workspace->type)) { - return NULL; - } - - swayc_t *current_output = workspace->parent; - int offset = next ? 1 : -1; - int start = next ? 0 : 1; - int end = next ? (current_output->children->length) - 1 : current_output->children->length; - int i; - for (i = start; i < end; i++) { - if (current_output->children->items[i] == workspace) { - return current_output->children->items[i + offset]; - } - } - - // 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[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 - return NULL; -} - -swayc_t *workspace_output_next() { - return workspace_output_prev_next_impl(swayc_active_output(), true); -} - -swayc_t *workspace_next() { - return workspace_prev_next_impl(swayc_active_workspace(), true); -} - -swayc_t *workspace_output_prev() { - return workspace_output_prev_next_impl(swayc_active_output(), false); -} - -swayc_t *workspace_prev() { - return workspace_prev_next_impl(swayc_active_workspace(), false); -} - -bool workspace_switch(swayc_t *workspace) { - if (!workspace) { - return false; - } - swayc_t *active_ws = swayc_active_workspace(); - if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { - swayc_t *new_ws = workspace_by_name(prev_workspace_name); - workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); - } - - if (!prev_workspace_name - || (strcmp(prev_workspace_name, active_ws->name) - && active_ws != workspace)) { - free(prev_workspace_name); - prev_workspace_name = malloc(strlen(active_ws->name) + 1); - if (!prev_workspace_name) { - sway_log(L_ERROR, "Unable to allocate previous workspace name"); - return false; - } - strcpy(prev_workspace_name, active_ws->name); - } - - // move sticky containers - if (swayc_parent_by_type(active_ws, C_OUTPUT) == swayc_parent_by_type(workspace, C_OUTPUT)) { - // don't change list while traversing it, use intermediate list instead - list_t *stickies = create_list(); - for (int i = 0; i < active_ws->floating->length; i++) { - swayc_t *cont = active_ws->floating->items[i]; - if (cont->sticky) { - list_add(stickies, cont); - } - } - for (int i = 0; i < stickies->length; i++) { - swayc_t *cont = stickies->items[i]; - sway_log(L_DEBUG, "Moving sticky container %p to %p:%s", - cont, workspace, workspace->name); - swayc_t *parent = remove_child(cont); - add_floating(workspace, cont); - // Destroy old container if we need to - destroy_container(parent); - } - list_free(stickies); - } - sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); - if (!set_focused_container(get_focused_view(workspace))) { - return false; - } - swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); - arrange_backgrounds(); - arrange_windows(output, -1, -1); - return true; -} - -swayc_t *workspace_for_pid(pid_t pid) { - int i; - swayc_t *ws = NULL; - struct pid_workspace *pw = NULL; - - sway_log(L_DEBUG, "looking for workspace for pid %d", pid); - - // leaving this here as it's useful for debugging - // sway_log(L_DEBUG, "all pid_workspaces"); - // for (int k = 0; k < config->pid_workspaces->length; k++) { - // pw = config->pid_workspaces->items[k]; - // sway_log(L_DEBUG, "pid %d workspace %s time_added %li", *pw->pid, pw->workspace, *pw->time_added); - // } - - do { - for (i = 0; i < config->pid_workspaces->length; i++) { - pw = config->pid_workspaces->items[i]; - pid_t *pw_pid = pw->pid; - - if (pid == *pw_pid) { - sway_log(L_DEBUG, "found pid_workspace for pid %d, workspace %s", pid, pw->workspace); - break; // out of for loop - } - - pw = NULL; - } - - if (pw) { - break; // out of do-while loop - } - - pid = get_parent_pid(pid); - // no sense in looking for matches for pid 0. - // also, if pid == getpid(), that is the compositor's - // pid, which definitely isn't helpful - } while (pid > 0 && pid != getpid()); - - if (pw) { - ws = workspace_by_name(pw->workspace); - - if (!ws) { - sway_log(L_DEBUG, "Creating workspace %s for pid %d because it disappeared", pw->workspace, pid); - ws = workspace_create(pw->workspace); - } - - list_del(config->pid_workspaces, i); - } - - return ws; -} From 5505d84ac2fda7c5fb4e4c52385ff818e66ef8e1 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 21 Jan 2018 14:11:41 -0500 Subject: [PATCH 170/522] criteria cleanup --- include/sway/criteria.h | 2 +- sway/commands.c | 2 +- sway/criteria.c | 15 ++++++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/sway/criteria.h b/include/sway/criteria.h index c5ed9857e..9b4b4befa 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -34,7 +34,7 @@ char *extract_crit_tokens(list_t *tokens, const char *criteria); 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); +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); diff --git a/sway/commands.c b/sway/commands.c index 3ab5add6e..a77ff7919 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -226,7 +226,7 @@ struct cmd_results *handle_command(char *_exec) { free(tokens); goto cleanup; } - containers = container_for(tokens); + containers = container_for_crit_tokens(tokens); free(tokens); } else { diff --git a/sway/criteria.c b/sway/criteria.c index 097336162..2eee331c1 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -103,7 +103,8 @@ static int countchr(char *str, char c) { // of buf. // // Returns error string or NULL if successful. -static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str) { +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; @@ -423,16 +424,20 @@ struct list_tokens { list_t *tokens; }; -static void container_match_add(swayc_t *container, struct list_tokens *list_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}; +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, &list_tokens); + container_map(&root_container, + (void (*)(swayc_t *, void *))container_match_add, + &list_tokens); // TODO look in the scratchpad From c3fc0d446f64ef7f46bc2a152cd68331de4410d0 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 21 Jan 2018 14:15:10 -0500 Subject: [PATCH 171/522] cmd-kill: use sway_assert when no container --- sway/commands/kill.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 62a3a5149..8208bc145 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -1,12 +1,13 @@ #include +#include "log.h" #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) { - if (!config->handler_context.current_container) { - wlr_log(L_ERROR, "cmd_kill called without container context"); + if (!sway_assert(config->handler_context.current_container, + "cmd_kill called without container context")) { return cmd_results_new(CMD_INVALID, NULL, "cmd_kill called without container context " "(this is a bug in sway)"); From 38a1628a76e22220e18ece7ee82ac45421d9b42f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 21 Jan 2018 14:21:32 -0500 Subject: [PATCH 172/522] clear handler context before ipc command --- sway/ipc-server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/ipc-server.c b/sway/ipc-server.c index d2dd881f0..a16a2b806 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -335,6 +335,7 @@ void ipc_client_handle_command(struct ipc_client *client) { switch (client->current_command) { case IPC_COMMAND: { + config_clear_handler_context(config); struct cmd_results *results = handle_command(buf); const char *json = cmd_results_to_json(results); char reply[256]; From beb3805cf0300bc2640290233aa763d757c12466 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 21 Jan 2018 19:13:11 -0500 Subject: [PATCH 173/522] dont allow kill command in config --- sway/commands/kill.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 8208bc145..3804f0b09 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -6,6 +6,10 @@ #include "sway/commands.h" struct cmd_results *cmd_kill(int argc, char **argv) { + if (config->reading) { + return cmd_results_new(CMD_FAILURE, "kill", + "Command 'kill' cannot be used in the config file"); + } if (!sway_assert(config->handler_context.current_container, "cmd_kill called without container context")) { return cmd_results_new(CMD_INVALID, NULL, From 869be4378d44e08c686b550a86a5e4fa60915edb Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 5 Jan 2018 22:05:48 +0100 Subject: [PATCH 174/522] commands: add 'reload' command --- sway/commands.c | 1 + sway/commands/reload.c | 21 +++++++++++++++++++++ sway/config.c | 4 ++++ sway/meson.build | 1 + 4 files changed, 27 insertions(+) create mode 100644 sway/commands/reload.c diff --git a/sway/commands.c b/sway/commands.c index a77ff7919..d4262c082 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -136,6 +136,7 @@ static struct cmd_handler handlers[] = { { "input", cmd_input }, { "kill", cmd_kill }, { "output", cmd_output }, + { "reload", cmd_reload }, { "seat", cmd_seat }, { "set", cmd_set }, }; diff --git a/sway/commands/reload.c b/sway/commands/reload.c new file mode 100644 index 000000000..2b5538456 --- /dev/null +++ b/sway/commands/reload.c @@ -0,0 +1,21 @@ +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/layout.h" + +struct cmd_results *cmd_reload(int argc, char **argv) { + struct cmd_results *error = NULL; + if (config->reading) { + return cmd_results_new(CMD_FAILURE, "reload", "Can't be used in config file."); + } + if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { + return error; + } + if (!load_main_config(config->current_config, true)) { + return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); + } + + load_swaybars(); + + arrange_windows(&root_container, -1, -1); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 1fd123b71..cb22f664a 100644 --- a/sway/config.c +++ b/sway/config.c @@ -698,3 +698,7 @@ char *do_var_replacement(char *str) { } return str; } + +void load_swaybars() { + /* stub function for reload commnd, to fill when we restore swaybars */ +} diff --git a/sway/meson.build b/sway/meson.build index 80ccc01d5..51e9e4dbb 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -34,6 +34,7 @@ sway_sources = files( 'commands/input/xkb_rules.c', 'commands/input/xkb_variant.c', 'commands/output.c', + 'commands/reload.c', 'config.c', 'config/output.c', 'config/seat.c', From 5766f426aac11bf39234dcca4c479ee865081dad Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 16 Jan 2018 21:16:04 +0100 Subject: [PATCH 175/522] config reload: destroy old seat when removed from config This adds new sway_seat_destroy and sway_cursor_destroy helpers and compare new and old config on free --- include/sway/input/cursor.h | 1 + include/sway/input/input-manager.h | 2 ++ include/sway/input/seat.h | 2 ++ sway/config.c | 19 +++++++++++++++++++ sway/input/cursor.c | 10 ++++++++++ sway/input/input-manager.c | 2 +- sway/input/seat.c | 10 ++++++++++ 7 files changed, 45 insertions(+), 1 deletion(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 2f70cf4b4..a16b793b5 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -25,6 +25,7 @@ struct sway_cursor { struct wl_listener request_set_cursor; }; +void sway_cursor_destroy(struct sway_cursor *cursor); struct sway_cursor *sway_cursor_create(struct sway_seat *seat); #endif diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 2bf297ce9..63806b8ec 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -46,4 +46,6 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, struct sway_seat *sway_input_manager_get_default_seat( struct sway_input_manager *input); +struct sway_seat *input_manager_get_seat(struct sway_input_manager *input, + const char *seat_name); #endif diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index d703f94c5..b21cbccb7 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -29,6 +29,8 @@ struct sway_seat { struct sway_seat *sway_seat_create(struct sway_input_manager *input, const char *seat_name); +void sway_seat_destroy(struct sway_seat *seat); + void sway_seat_add_device(struct sway_seat *seat, struct sway_input_device *device); diff --git a/sway/config.c b/sway/config.c index cb22f664a..0f91cce69 100644 --- a/sway/config.c +++ b/sway/config.c @@ -21,6 +21,7 @@ #endif #include #include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/commands.h" #include "sway/config.h" #include "sway/layout.h" @@ -109,6 +110,23 @@ void free_config(struct sway_config *config) { free(config); } +static void destroy_removed_seats(struct sway_config *old_config, + struct sway_config *new_config) { + struct seat_config *seat_config; + struct sway_seat *seat; + int i; + for (i = 0; i < old_config->seat_configs->length; i++) { + seat_config = old_config->seat_configs->items[i]; + /* Also destroy seats that aren't present in new config */ + if (new_config && list_seq_find(new_config->seat_configs, + seat_name_cmp, seat_config->name) < 0) { + seat = input_manager_get_seat(input_manager, + seat_config->name); + sway_seat_destroy(seat); + } + } +} + static void config_defaults(struct sway_config *config) { if (!(config->symbols = create_list())) goto cleanup; if (!(config->modes = create_list())) goto cleanup; @@ -382,6 +400,7 @@ bool load_main_config(const char *file, bool is_active) { } if (old_config) { + destroy_removed_seats(old_config, config); free_config(old_config); } config->reading = false; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index e6a4eca8a..73a8ec5ce 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -149,6 +149,16 @@ static void handle_request_set_cursor(struct wl_listener *listener, wlr_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); } +void sway_cursor_destroy(struct sway_cursor *cursor) { + if (!cursor) { + return; + } + + wlr_xcursor_manager_destroy(cursor->xcursor_manager); + wlr_cursor_destroy(cursor->cursor); + free(cursor); +} + struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { struct sway_cursor *cursor = calloc(1, sizeof(struct sway_cursor)); if (!sway_assert(cursor, "could not allocate sway cursor")) { diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 2d119cf26..12b3a430e 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -23,7 +23,7 @@ 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_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) { diff --git a/sway/input/seat.c b/sway/input/seat.c index e9b375e09..9ea08eec0 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -21,6 +21,16 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { free(seat_device); } +void sway_seat_destroy(struct sway_seat *seat) { + struct sway_seat_device *seat_device, *next; + wl_list_for_each_safe(seat_device, next, &seat->devices, link) { + seat_device_destroy(seat_device); + } + sway_cursor_destroy(seat->cursor); + wl_list_remove(&seat->link); + wlr_seat_destroy(seat->wlr_seat); +} + 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)); From 6259831d3168898a3f1560fb832106d194b582b4 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Mon, 22 Jan 2018 07:19:12 +0100 Subject: [PATCH 176/522] commands/reload: remove unimplemented 'load_swaybars' call --- sway/commands/reload.c | 2 +- sway/config.c | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 2b5538456..419c7de3d 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -14,7 +14,7 @@ struct cmd_results *cmd_reload(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); } - load_swaybars(); + /* load_swaybars(); -- for when it's implemented */ arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/config.c b/sway/config.c index 0f91cce69..a67322d1c 100644 --- a/sway/config.c +++ b/sway/config.c @@ -717,7 +717,3 @@ char *do_var_replacement(char *str) { } return str; } - -void load_swaybars() { - /* stub function for reload commnd, to fill when we restore swaybars */ -} From a686fb07ae324cb122f7175941f0ef6c3cdd0cf4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 30 Jan 2018 20:01:49 -0500 Subject: [PATCH 177/522] Execute pending commands when Xwayland is ready --- include/sway/server.h | 1 + sway/server.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/sway/server.h b/include/sway/server.h index 76a054764..d497e1328 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -33,6 +33,7 @@ struct sway_server { struct wlr_xwayland *xwayland; struct wl_listener xwayland_surface; + struct wl_listener xwayland_ready; struct wlr_wl_shell *wl_shell; struct wl_listener wl_shell_surface; diff --git a/sway/server.c b/sway/server.c index 365094ef2..b5eb510be 100644 --- a/sway/server.c +++ b/sway/server.c @@ -11,9 +11,27 @@ // TODO WLR: make Xwayland optional #include #include +#include "sway/commands.h" +#include "sway/config.h" #include "sway/server.h" #include "sway/input/input-manager.h" +static void server_ready(struct wl_listener *listener, void *data) { + wlr_log(L_DEBUG, "Compositor is ready, executing cmds in queue"); + // Execute commands until there are none left + config->active = true; + while (config->cmd_queue->length) { + char *line = config->cmd_queue->items[0]; + struct cmd_results *res = handle_command(line); + if (res->status != CMD_SUCCESS) { + wlr_log(L_ERROR, "Error on line '%s': %s", line, res->error); + } + free_cmd_results(res); + free(line); + list_del(config->cmd_queue, 0); + } +} + bool server_init(struct sway_server *server) { wlr_log(L_DEBUG, "Initializing Wayland server"); @@ -48,6 +66,10 @@ bool server_init(struct sway_server *server) { wl_signal_add(&server->xwayland->events.new_surface, &server->xwayland_surface); server->xwayland_surface.notify = handle_xwayland_surface; + wl_signal_add(&server->xwayland->events.ready, + &server->xwayland_ready); + // TODO: call server_ready now if xwayland is not enabled + server->xwayland_ready.notify = server_ready; server->wl_shell = wlr_wl_shell_create(server->wl_display); wl_signal_add(&server->wl_shell->events.new_surface, From 8231f99c12b059bf762c2ca77258a520b3a6886f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 30 Jan 2018 20:51:57 -0500 Subject: [PATCH 178/522] Remove include/sway/old/ --- include/sway/old/border.h | 28 --- include/sway/old/commands.h | 214 ----------------- include/sway/old/config.h | 406 --------------------------------- include/sway/old/container.h | 362 ----------------------------- include/sway/old/criteria.h | 42 ---- include/sway/old/focus.h | 45 ---- include/sway/old/input.h | 24 -- include/sway/old/input_state.h | 102 --------- include/sway/old/ipc-json.h | 15 -- include/sway/old/ipc-server.h | 33 --- include/sway/old/layout.h | 85 ------- include/sway/old/output.h | 36 --- include/sway/old/workspace.h | 22 -- 13 files changed, 1414 deletions(-) delete mode 100644 include/sway/old/border.h delete mode 100644 include/sway/old/commands.h delete mode 100644 include/sway/old/config.h delete mode 100644 include/sway/old/container.h delete mode 100644 include/sway/old/criteria.h delete mode 100644 include/sway/old/focus.h delete mode 100644 include/sway/old/input.h delete mode 100644 include/sway/old/input_state.h delete mode 100644 include/sway/old/ipc-json.h delete mode 100644 include/sway/old/ipc-server.h delete mode 100644 include/sway/old/layout.h delete mode 100644 include/sway/old/output.h delete mode 100644 include/sway/old/workspace.h diff --git a/include/sway/old/border.h b/include/sway/old/border.h deleted file mode 100644 index c30c9da3f..000000000 --- a/include/sway/old/border.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _SWAY_BORDER_H -#define _SWAY_BORDER_H -#include -#include "container.h" - -/** - * Border pixel buffer and corresponding geometry. - */ -struct border { - unsigned char *buffer; - struct wlc_geometry geometry; -}; - -/** - * Clear border buffer. - */ -void border_clear(struct border *border); - -/** - * Recursively update all of the borders within a container. - */ -void update_container_border(swayc_t *container); - -void render_view_borders(wlc_handle view); -int get_font_text_height(const char *font); -bool should_hide_top_border(swayc_t *con, double y); - -#endif diff --git a/include/sway/old/commands.h b/include/sway/old/commands.h deleted file mode 100644 index 660da2c22..000000000 --- a/include/sway/old/commands.h +++ /dev/null @@ -1,214 +0,0 @@ -#ifndef _SWAY_COMMANDS_H -#define _SWAY_COMMANDS_H -#include -#include -#include -#include "config.h" - -// Container that a called command should act upon. Only valid in command functions. -extern swayc_t *current_container; - -/** - * Indicates the result of a command's execution. - */ -enum cmd_status { - CMD_SUCCESS, /**< The command was successful */ - CMD_FAILURE, /**< The command resulted in an error */ - CMD_INVALID, /**< Unknown command or parser error */ - CMD_DEFER, /**< Command execution deferred */ - // Config Blocks - CMD_BLOCK_END, - CMD_BLOCK_MODE, - CMD_BLOCK_BAR, - CMD_BLOCK_BAR_COLORS, - CMD_BLOCK_INPUT, - CMD_BLOCK_COMMANDS, - CMD_BLOCK_IPC, - CMD_BLOCK_IPC_EVENTS, -}; - -/** - * Stores the result of executing a command. - */ -struct cmd_results { - enum cmd_status status; - char *input; - /** - * Human friendly error message, or NULL on success - */ - char *error; -}; - -enum expected_args { - EXPECTED_MORE_THAN, - EXPECTED_AT_LEAST, - EXPECTED_LESS_THAN, - EXPECTED_EQUAL_TO -}; - -struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val); -struct cmd_results *add_color(const char*, char*, const char*); -void input_cmd_apply(struct input_config *input); -void hide_view_in_scratchpad(swayc_t *sp_view); - -swayc_t *sp_view; -int sp_index; - -/** - * Parse and handles a command. - */ -struct cmd_results *handle_command(char *command, enum command_context context); -/** - * 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. - */ -struct cmd_results *cmd_results_new(enum cmd_status status, const char* input, const char *error, ...); -/** - * Frees a cmd_results object. - */ -void free_cmd_results(struct cmd_results *results); -/** - * Serializes cmd_results to a JSON string. - * - * Free the JSON string later on. - */ -const char *cmd_results_to_json(struct cmd_results *results); - -void remove_view_from_scratchpad(swayc_t *); - -/** - * Actual command function signatures for individual .c files in commands/ directory. - */ - -typedef struct cmd_results *sway_cmd(int argc, char **argv); - -sway_cmd cmd_assign; -sway_cmd cmd_bar; -sway_cmd cmd_bindcode; -sway_cmd cmd_bindsym; -sway_cmd cmd_border; -sway_cmd cmd_client_focused; -sway_cmd cmd_client_focused_inactive; -sway_cmd cmd_client_unfocused; -sway_cmd cmd_client_urgent; -sway_cmd cmd_client_placeholder; -sway_cmd cmd_client_background; -sway_cmd cmd_clipboard; -sway_cmd cmd_commands; -sway_cmd cmd_debuglog; -sway_cmd cmd_default_border; -sway_cmd cmd_default_floating_border; -sway_cmd cmd_exec; -sway_cmd cmd_exec_always; -sway_cmd cmd_exit; -sway_cmd cmd_floating; -sway_cmd cmd_floating_maximum_size; -sway_cmd cmd_floating_minimum_size; -sway_cmd cmd_floating_mod; -sway_cmd cmd_floating_scroll; -sway_cmd cmd_focus; -sway_cmd cmd_focus_follows_mouse; -sway_cmd cmd_font; -sway_cmd cmd_for_window; -sway_cmd cmd_force_focus_wrapping; -sway_cmd cmd_fullscreen; -sway_cmd cmd_gaps; -sway_cmd cmd_hide_edge_borders; -sway_cmd cmd_include; -sway_cmd cmd_input; -sway_cmd cmd_ipc; -sway_cmd cmd_kill; -sway_cmd cmd_layout; -sway_cmd cmd_log_colors; -sway_cmd cmd_mark; -sway_cmd cmd_mode; -sway_cmd cmd_mouse_warping; -sway_cmd cmd_move; -sway_cmd cmd_new_float; -sway_cmd cmd_new_window; -sway_cmd cmd_no_focus; -sway_cmd cmd_orientation; -sway_cmd cmd_output; -sway_cmd cmd_permit; -sway_cmd cmd_reject; -sway_cmd cmd_reload; -sway_cmd cmd_resize; -sway_cmd cmd_scratchpad; -sway_cmd cmd_seamless_mouse; -sway_cmd cmd_set; -sway_cmd cmd_show_marks; -sway_cmd cmd_smart_gaps; -sway_cmd cmd_split; -sway_cmd cmd_splith; -sway_cmd cmd_splitt; -sway_cmd cmd_splitv; -sway_cmd cmd_sticky; -sway_cmd cmd_unmark; -sway_cmd cmd_workspace; -sway_cmd cmd_ws_auto_back_and_forth; -sway_cmd cmd_workspace_layout; - -sway_cmd bar_cmd_activate_button; -sway_cmd bar_cmd_binding_mode_indicator; -sway_cmd bar_cmd_bindsym; -sway_cmd bar_cmd_colors; -sway_cmd bar_cmd_context_button; -sway_cmd bar_cmd_font; -sway_cmd bar_cmd_mode; -sway_cmd bar_cmd_modifier; -sway_cmd bar_cmd_output; -sway_cmd bar_cmd_height; -sway_cmd bar_cmd_hidden_state; -sway_cmd bar_cmd_icon_theme; -sway_cmd bar_cmd_id; -sway_cmd bar_cmd_position; -sway_cmd bar_cmd_secondary_button; -sway_cmd bar_cmd_separator_symbol; -sway_cmd bar_cmd_status_command; -sway_cmd bar_cmd_pango_markup; -sway_cmd bar_cmd_strip_workspace_numbers; -sway_cmd bar_cmd_swaybar_command; -sway_cmd bar_cmd_tray_output; -sway_cmd bar_cmd_tray_padding; -sway_cmd bar_cmd_wrap_scroll; -sway_cmd bar_cmd_workspace_buttons; - -sway_cmd bar_colors_cmd_active_workspace; -sway_cmd bar_colors_cmd_background; -sway_cmd bar_colors_cmd_focused_background; -sway_cmd bar_colors_cmd_binding_mode; -sway_cmd bar_colors_cmd_focused_workspace; -sway_cmd bar_colors_cmd_inactive_workspace; -sway_cmd bar_colors_cmd_separator; -sway_cmd bar_colors_cmd_focused_separator; -sway_cmd bar_colors_cmd_statusline; -sway_cmd bar_colors_cmd_focused_statusline; -sway_cmd bar_colors_cmd_urgent_workspace; - -sway_cmd input_cmd_accel_profile; -sway_cmd input_cmd_click_method; -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_middle_emulation; -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 cmd_ipc_cmd; -sway_cmd cmd_ipc_events; -sway_cmd cmd_ipc_event_cmd; - -#endif diff --git a/include/sway/old/config.h b/include/sway/old/config.h deleted file mode 100644 index a05d5ede8..000000000 --- a/include/sway/old/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 diff --git a/include/sway/old/container.h b/include/sway/old/container.h deleted file mode 100644 index d46ffa63b..000000000 --- a/include/sway/old/container.h +++ /dev/null @@ -1,362 +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; -extern swayc_t *current_focus; - -struct sway_view; - -/** - * 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). */ - // Keep last - 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 */ -}; - -/** - * Stores information about a container. - * - * The tree is made of these. Views are containers that cannot have children. - */ -struct sway_container { - // TODO WLR: reconcile these - wlc_handle handle; - - union { - struct sway_output *output; - struct sway_view *view; - } _handle; - - /** - * A unique ID to identify this container. Primarily used in the - * get_tree JSON output. - */ - size_t id; - - enum swayc_types type; - enum swayc_layouts layout; - enum swayc_layouts prev_layout; - enum swayc_layouts workspace_layout; - - /** - * Width and height of this container, without borders or gaps. - */ - double width, height; - - /** - * Views may request geometry, which is stored in this and ignored until - * the views are floated. - */ - int desired_width, desired_height; - - /** - * The coordinates that this view appear at, relative to the output they - * are located on (output containers have absolute coordinates). - */ - double x, y; - - /** - * Cached geometry used to store view/container geometry when switching - * between tabbed/stacked and horizontal/vertical layouts. - */ - struct wlc_geometry cached_geometry; - - /** - * False if this view is invisible. It could be in the scratchpad or on a - * workspace that is not shown. - */ - bool visible; - bool is_floating; - bool is_focused; - bool sticky; // floating view always visible on its output - - // Attributes that mostly views have. - char *name; - char *class; - char *instance; - char *app_id; - - // Used by output containers to keep track of swaybg child processes. - pid_t bg_pid; - - int gaps; - - list_t *children; - /** - * Children of this container that are floated. - */ - list_t *floating; - /** - * Unmanaged view handles in this container. - */ - list_t *unmanaged; - - /** - * The parent of this container. NULL for the root container. - */ - struct sway_container *parent; - /** - * Which of this container's children has focus. - */ - struct sway_container *focused; - /** - * If this container's children include a fullscreen view, this is that view. - */ - struct sway_container *fullscreen; - /** - * If this container is a view, this may be set to the window's decoration - * buffer (or NULL). - */ - struct border *border; - enum swayc_border_types border_type; - struct wlc_geometry border_geometry; - struct wlc_geometry title_bar_geometry; - struct wlc_geometry actual_geometry; - int border_thickness; - - /** - * 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; -}; - -enum visibility_mask { - VISIBLE = true -} visible; - -struct sway_output; -/** - * Allocates a new output container. - */ -swayc_t *new_output(struct sway_output *sway_output); -/** - * Allocates a new workspace container. - */ -swayc_t *new_workspace(swayc_t *output, const char *name); -/** - * Allocates a new container and places a child into it. - * - * This is used from the split command, which creates a new container with the - * requested layout and replaces the focused container in the tree with the new - * one. Then the removed container is added as a child of the new container. - */ -swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); -/** - * Allocates a new view container. - * - * Pass in a sibling view, or a workspace to become this container's parent. - */ -swayc_t *new_view(swayc_t *sibling, struct sway_view *view); -/** - * Allocates a new floating view in the active workspace. - */ -swayc_t *new_floating_view(wlc_handle handle); - -void floating_view_sane_size(swayc_t *view); - -/** - * Frees an output's container. - */ -swayc_t *destroy_output(swayc_t *output); -/** - * Destroys a workspace container and returns the parent pointer, or NULL. - */ -swayc_t *destroy_workspace(swayc_t *workspace); -/** - * Destroys a container and all empty parents. Returns the topmost non-empty - * parent container, or NULL. - */ -swayc_t *destroy_container(swayc_t *container); -/** - * Destroys a view container and all empty parents. Returns the topmost - * non-empty parent container, or NULL. - */ -swayc_t *destroy_view(swayc_t *view); - -/** - * 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); -/** - * Finds a parent with the given swayc_layout. - */ -swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); -/** - * Finds the bottom-most focused container of a type. - */ -swayc_t *swayc_focus_by_type(swayc_t *container, enum swayc_types); -/** - * Finds the bottom-most focused container of a layout. - */ -swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts); - -/** - * Gets the swayc_t associated with a wlc_handle. - */ -swayc_t *swayc_by_handle(wlc_handle handle); -/** - * Gets the named swayc_t. - */ -swayc_t *swayc_by_name(const char *name); -/** - * Gets the active output's container. - */ -swayc_t *swayc_active_output(void); -/** - * Gets the active workspace's container. - */ -swayc_t *swayc_active_workspace(void); -/** - * Gets the workspace for the given view container. - */ -swayc_t *swayc_active_workspace_for(swayc_t *view); -/** - * Finds the container currently underneath the pointer. - */ -swayc_t *container_under_pointer(void); -/** - * Finds the first container following a callback. - */ -swayc_t *container_find(swayc_t *container, bool (*f)(swayc_t *, const void *), const void *data); - -/** - * Returns true if a container is fullscreen. - */ -bool swayc_is_fullscreen(swayc_t *view); -/** - * Returns true if this view is focused. - */ -bool swayc_is_active(swayc_t *view); -/** - * Returns true if the parent is an ancestor of the child. - */ -bool swayc_is_parent_of(swayc_t *parent, swayc_t *child); -/** - * Returns true if the child is a desecendant of the parent. - */ -bool swayc_is_child_of(swayc_t *child, swayc_t *parent); - -/** - * Returns true if this container is an empty workspace. - */ -bool swayc_is_empty_workspace(swayc_t *container); - -/** - * Returns the top most tabbed or stacked parent container. Returns NULL if - * view is not in a tabbed/stacked layout. - */ -swayc_t *swayc_tabbed_stacked_ancestor(swayc_t *view); - -/** - * Returns the immediate tabbed or stacked parent container. Returns NULL if - * view is not directly in a tabbed/stacked layout. - */ -swayc_t *swayc_tabbed_stacked_parent(swayc_t *view); - -/** - * Returns the gap (padding) of the container. - * - * This returns the inner gaps for a view, the outer gaps for a workspace, and - * 0 otherwise. - */ -int swayc_gap(swayc_t *container); - -/** - * Maps a container's children over a function. - */ -void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); - -/** - * Set a view as visible or invisible. - * - * This will perform the required wlc calls as well; it is not sufficient to - * simply toggle the boolean in swayc_t. - */ -void set_view_visibility(swayc_t *view, void *data); -/** - * Set the gaps value for a view. - */ -void set_gaps(swayc_t *view, void *amount); -/** - * Add to the gaps value for a view. - */ -void add_gaps(swayc_t *view, void *amount); - -/** - * Issue wlc calls to make the visibility of a container consistent. - */ -void update_visibility(swayc_t *container); - -/** - * Close all child views of container - */ -void close_views(swayc_t *container); - -/** - * Assign layout to a container. Needed due to workspace container specifics. - * Workspace should always have either L_VERT or L_HORIZ layout. - */ -swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout); - -#endif diff --git a/include/sway/old/criteria.h b/include/sway/old/criteria.h deleted file mode 100644 index c5ed9857e..000000000 --- a/include/sway/old/criteria.h +++ /dev/null @@ -1,42 +0,0 @@ -#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/include/sway/old/focus.h b/include/sway/old/focus.h deleted file mode 100644 index 652cdccc4..000000000 --- a/include/sway/old/focus.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _SWAY_FOCUS_H -#define _SWAY_FOCUS_H -enum movement_direction { - MOVE_LEFT, - MOVE_RIGHT, - MOVE_UP, - MOVE_DOWN, - MOVE_PARENT, - MOVE_CHILD, - MOVE_NEXT, - MOVE_PREV, - MOVE_FIRST -}; - -#include "container.h" - -// focused_container - the container found by following the `focused` pointer -// from a given container to a container with `is_focused` boolean set -// --- -// focused_view - the container found by following the `focused` pointer from a -// given container to a view. -// --- - -swayc_t *get_focused_container(swayc_t *parent); -swayc_t *get_focused_view(swayc_t *parent); -swayc_t *get_focused_float(swayc_t *ws); - -// a special-case function to get the focused view, regardless -// of whether it's tiled or floating -swayc_t *get_focused_view_include_floating(swayc_t *parent); - -bool set_focused_container(swayc_t *container); -bool set_focused_container_for(swayc_t *ancestor, swayc_t *container); - -// lock focused container/view. locked by windows with OVERRIDE attribute -// and unlocked when they are destroyed - -extern bool locked_container_focus; - -// Prevents wss from being destroyed on focus switch -extern bool suspend_workspace_cleanup; - -bool move_focus(enum movement_direction direction); - -#endif diff --git a/include/sway/old/input.h b/include/sway/old/input.h deleted file mode 100644 index eb92e470a..000000000 --- a/include/sway/old/input.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _SWAY_INPUT_H -#define _SWAY_INPUT_H -#include -#include "sway/server.h" -#include "config.h" -#include "list.h" - -struct sway_input { - list_t *input_devices; -}; - -struct input_config *new_input_config(const char* identifier); - -char* libinput_dev_unique_id(struct libinput_device *dev); - -struct sway_input *sway_input_create(struct sway_server *server); - -/** - * Pointer used when reading input blocked. - * Shared so that it can be cleared from commands.c when closing the block - */ -extern struct input_config *current_input_config; - -#endif diff --git a/include/sway/old/input_state.h b/include/sway/old/input_state.h deleted file mode 100644 index fd5a3a25a..000000000 --- a/include/sway/old/input_state.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef _SWAY_KEY_STATE_H -#define _SWAY_KEY_STATE_H -#include -#include -#include "container.h" - -/* Keyboard state */ - -// returns true if key has been pressed, otherwise false -bool check_key(uint32_t key_sym, uint32_t key_code); - -// returns true if key_sym matches latest released key. -bool check_released_key(uint32_t key_sym); - -// sets a key as pressed -void press_key(uint32_t key_sym, uint32_t key_code); - -// unsets a key as pressed -void release_key(uint32_t key_sym, uint32_t key_code); - - -/* Pointer state */ - -enum pointer_values { - M_LEFT_CLICK = 272, - M_RIGHT_CLICK = 273, - M_SCROLL_CLICK = 274, - M_SCROLL_UP = 275, - M_SCROLL_DOWN = 276, -}; - -enum pointer_mode { - // Target - M_FLOATING = 1, - M_TILING = 2, - // Action - M_DRAGGING = 4, - M_RESIZING = 8, -}; - -struct pointer_button_state { - bool held; - // state at the point it was pressed - int x, y; - swayc_t *view; -}; - -extern struct pointer_state { - // mouse clicks - struct pointer_button_state left; - struct pointer_button_state right; - struct pointer_button_state scroll; - - // change in pointer position - struct { - int x, y; - } delta; - - // view pointer is currently over - swayc_t *view; - - // Pointer mode - int mode; -} pointer_state; - -enum modifier_state { - MOD_STATE_UNCHANGED = 0, - MOD_STATE_PRESSED = 1, - MOD_STATE_RELEASED = 2 -}; - -void pointer_position_set(double new_x, double new_y, bool force_focus); -void center_pointer_on(swayc_t *view); - -// on button release unset mode depending on the button. -// on button press set mode conditionally depending on the button -void pointer_mode_set(uint32_t button, bool condition); - -// Update mode in mouse motion -void pointer_mode_update(void); - -// Reset mode on any keypress; -void pointer_mode_reset(void); - -void input_init(void); - -/** - * Check if state of mod changed from current state to new_state. - * - * Returns MOD_STATE_UNCHANGED if the state didn't change, MOD_STATE_PRESSED if - * the state changed to pressed and MOD_STATE_RELEASED if the state changed to - * released. - */ -uint32_t modifier_state_changed(uint32_t new_state, uint32_t mod); - -/** - * Update the current modifiers state to new_state. - */ -void modifiers_state_update(uint32_t new_state); - -#endif - diff --git a/include/sway/old/ipc-json.h b/include/sway/old/ipc-json.h deleted file mode 100644 index 3a5af0f59..000000000 --- a/include/sway/old/ipc-json.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _SWAY_IPC_JSON_H -#define _SWAY_IPC_JSON_H - -#include -#include "config.h" -#include "container.h" - -json_object *ipc_json_get_version(); -json_object *ipc_json_describe_bar_config(struct bar_config *bar); -json_object *ipc_json_describe_container(swayc_t *c); -json_object *ipc_json_describe_container_recursive(swayc_t *c); -json_object *ipc_json_describe_window(swayc_t *c); -json_object *ipc_json_describe_input(struct libinput_device *device); - -#endif diff --git a/include/sway/old/ipc-server.h b/include/sway/old/ipc-server.h deleted file mode 100644 index 0cc26d990..000000000 --- a/include/sway/old/ipc-server.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _SWAY_IPC_SERVER_H -#define _SWAY_IPC_SERVER_H -#include "container.h" -#include "config.h" -#include "ipc.h" - -void ipc_init(void); -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_barconfig_update(struct bar_config *bar); -/** - * Send IPC mode event to all listening clients - */ -void ipc_event_mode(const char *mode); -/** - * Send IPC window change event - */ -void ipc_event_window(swayc_t *window, const char *change); -/** - * Sends an IPC modifier event to all listening clients. The modifier event - * includes a key 'change' with the value of state and a key 'modifier' with - * the name of that modifier. - */ -void ipc_event_modifier(uint32_t modifier, const char *state); -/** - * Send IPC keyboard binding event. - */ -void ipc_event_binding_keyboard(struct sway_binding *sb); -const char *swayc_type_string(enum swayc_types type); - -#endif diff --git a/include/sway/old/layout.h b/include/sway/old/layout.h deleted file mode 100644 index f0791588a..000000000 --- a/include/sway/old/layout.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _SWAY_LAYOUT_H -#define _SWAY_LAYOUT_H - -#include -#include "log.h" -#include "list.h" -#include "container.h" -#include "focus.h" - -extern list_t *scratchpad; - -extern int min_sane_w; -extern int min_sane_h; - -// Set initial values for root_container -void init_layout(void); - -// Returns the index of child for its parent -int index_child(const swayc_t *child); - -// Adds child to parent, if parent has no focus, it is set to child -// parent must be of type C_WORKSPACE or C_CONTAINER -void add_child(swayc_t *parent, swayc_t *child); - -// Adds child to parent at index, if parent has no focus, it is set to child -// parent must be of type C_WORKSPACE or C_CONTAINER -void insert_child(swayc_t *parent, swayc_t *child, int index); - -// Adds child as floating window to ws, if there is no focus it is set to child. -// ws must be of type C_WORKSPACE -void add_floating(swayc_t *ws, swayc_t *child); - -// insert child after sibling in parents children. -swayc_t *add_sibling(swayc_t *sibling, swayc_t *child); - -// Replace child with new_child in parents children -// new_child will inherit childs geometry, childs geometry will be reset -// if parents focus is on child, it will be changed to new_child -swayc_t *replace_child(swayc_t *child, swayc_t *new_child); - -// Remove child from its parent, if focus is on child, focus will be changed to -// a sibling, or to a floating window, or NULL -swayc_t *remove_child(swayc_t *child); - -// 2 containers are swapped, they inherit eachothers focus -void swap_container(swayc_t *a, swayc_t *b); - -// 2 Containers geometry are swapped, used with `swap_container` -void swap_geometry(swayc_t *a, swayc_t *b); - -void move_container(swayc_t* container, enum movement_direction direction, int move_amt); -void move_container_to(swayc_t* container, swayc_t* destination); -void move_workspace_to(swayc_t* workspace, swayc_t* destination); - -// Layout -/** - * Update child container geometries when switching between layouts. - */ -void update_layout_geometry(swayc_t *parent, enum swayc_layouts prev_layout); -void update_geometry(swayc_t *view); -void arrange_windows(swayc_t *container, double width, double height); -void arrange_backgrounds(void); - -swayc_t *get_focused_container(swayc_t *parent); -swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir); -swayc_t *get_swayc_in_direction_under(swayc_t *container, enum movement_direction dir, swayc_t *limit); - -void recursive_resize(swayc_t *container, double amount, enum wlc_resize_edge edge); - -void layout_log(const swayc_t *c, int depth); -void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ...) __attribute__((format(printf,3,4))); - -/** - * Get default layout. - */ -enum swayc_layouts default_layout(swayc_t *output); - -bool is_auto_layout(enum swayc_layouts layout); -int auto_group_start_index(const swayc_t *container, int index); -int auto_group_end_index(const swayc_t *container, int index); -size_t auto_group_count(const swayc_t *container); -size_t auto_group_index(const swayc_t *container, int index); -bool auto_group_bounds(const swayc_t *container, size_t group_index, int *start, int *end); - -#endif diff --git a/include/sway/old/output.h b/include/sway/old/output.h deleted file mode 100644 index 2a2222385..000000000 --- a/include/sway/old/output.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _SWAY_OUTPUT_H -#define _SWAY_OUTPUT_H -#include -#include -#include -#include "container.h" -#include "focus.h" - -struct sway_server; - -struct sway_output { - struct wlr_output *wlr_output; - struct wl_listener frame; - struct sway_server *server; - struct timespec last_frame; -}; - -// Position is absolute coordinates on the edge where the adjacent output -// should be searched for. -swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos); -swayc_t *swayc_opposite_output(enum movement_direction dir, const struct wlc_point *abs_pos); -swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir, const struct wlc_point *abs_pos, bool pick_closest); - -// Place absolute coordinates for given container into given wlc_point. -void get_absolute_position(swayc_t *container, struct wlc_point *point); - -// Place absolute coordinates for the center point of given container into -// given wlc_point. -void get_absolute_center_position(swayc_t *container, struct wlc_point *point); - -// stable sort workspaces on this output -void sort_workspaces(swayc_t *output); - -void output_get_scaled_size(wlc_handle handle, struct wlc_size *size); - -#endif diff --git a/include/sway/old/workspace.h b/include/sway/old/workspace.h deleted file mode 100644 index c268fafab..000000000 --- a/include/sway/old/workspace.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _SWAY_WORKSPACE_H -#define _SWAY_WORKSPACE_H - -#include -#include -#include "list.h" -#include "layout.h" - -extern char *prev_workspace_name; - -char *workspace_next_name(const char *output_name); -swayc_t *workspace_create(const char*); -swayc_t *workspace_by_name(const char*); -swayc_t *workspace_by_number(const char*); -bool workspace_switch(swayc_t*); -swayc_t *workspace_output_next(); -swayc_t *workspace_next(); -swayc_t *workspace_output_prev(); -swayc_t *workspace_prev(); -swayc_t *workspace_for_pid(pid_t pid); - -#endif From b28602aa7425cf435150e6008624429737e037d3 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 30 Jan 2018 23:09:21 -0500 Subject: [PATCH 179/522] Implement workspaces --- include/sway/container.h | 19 ++- include/sway/input/input-manager.h | 4 + include/sway/workspace.h | 14 ++ sway/commands.c | 1 + sway/commands/kill.c | 7 +- sway/commands/workspace.c | 101 ++++++++++++++ sway/config.c | 15 +- sway/desktop/output.c | 4 +- sway/desktop/xdg_shell_v6.c | 9 +- sway/input/input-manager.c | 8 ++ sway/input/seat.c | 15 +- sway/meson.build | 1 + sway/tree/container.c | 41 +++++- sway/tree/workspace.c | 211 +++++++++++++++++++++++++++++ 14 files changed, 420 insertions(+), 30 deletions(-) create mode 100644 sway/commands/workspace.c diff --git a/include/sway/container.h b/include/sway/container.h index a99e26945..0c66932d6 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -11,6 +11,7 @@ typedef struct sway_container swayc_t; extern swayc_t root_container; struct sway_view; +struct sway_seat; /** * Different kinds of containers. @@ -140,11 +141,25 @@ 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); -void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data); - #endif diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 63806b8ec..66ace2626 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -48,4 +48,8 @@ struct sway_seat *sway_input_manager_get_default_seat( struct sway_seat *input_manager_get_seat(struct sway_input_manager *input, const char *seat_name); + +/** Gets the last seat the user interacted with */ +struct sway_seat *input_manager_current_seat(struct sway_input_manager *input); + #endif diff --git a/include/sway/workspace.h b/include/sway/workspace.h index 04b2ea4ef..30bbdaa8a 100644 --- a/include/sway/workspace.h +++ b/include/sway/workspace.h @@ -1,6 +1,20 @@ #ifndef _SWAY_WORKSPACE_H #define _SWAY_WORKSPACE_H +struct sway_container; + +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(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/sway/commands.c b/sway/commands.c index d4262c082..0d4aa104a 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -139,6 +139,7 @@ static struct cmd_handler handlers[] = { { "reload", cmd_reload }, { "seat", cmd_seat }, { "set", cmd_set }, + { "workspace", cmd_workspace }, }; static int handler_compare(const void *_a, const void *_b) { diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 3804f0b09..cebf7f3c7 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -10,11 +10,10 @@ struct cmd_results *cmd_kill(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "kill", "Command 'kill' cannot be used in the config file"); } - if (!sway_assert(config->handler_context.current_container, - "cmd_kill called without container context")) { + enum swayc_types type = config->handler_context.current_container->type; + if (type != C_VIEW || type != C_CONTAINER) { return cmd_results_new(CMD_INVALID, NULL, - "cmd_kill called without container context " - "(this is a bug in sway)"); + "Can only kill views and containers with this command"); } // TODO close arbitrary containers without a view struct sway_view *view = diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c new file mode 100644 index 000000000..12984ed4a --- /dev/null +++ b/sway/commands/workspace.c @@ -0,0 +1,101 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/input/seat.h" +#include "sway/workspace.h" +#include "list.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *cmd_workspace(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) { + return error; + } + + int output_location = -1; + + 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 = swayc_parent_by_type(current_container, C_WORKSPACE); + } + old_output = swayc_parent_by_type(current_container, C_OUTPUT); + } + + for (int i = 0; i < argc; ++i) { + if (strcasecmp(argv[i], "output") == 0) { + output_location = i; + break; + } + } + if (output_location >= 0) { + if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { + return error; + } + struct workspace_output *wso = calloc(1, sizeof(struct workspace_output)); + if (!wso) { + return cmd_results_new(CMD_FAILURE, "workspace output", + "Unable to allocate workspace output"); + } + wso->workspace = join_args(argv, argc - 2); + wso->output = strdup(argv[output_location + 1]); + int i = -1; + if ((i = list_seq_find(config->workspace_outputs, workspace_output_cmp_workspace, wso)) != -1) { + struct workspace_output *old = config->workspace_outputs->items[i]; + free(old); // workspaces can only be assigned to a single output + list_del(config->workspace_outputs, i); + } + wlr_log(L_DEBUG, "Assigning workspace %s to output %s", wso->workspace, wso->output); + list_add(config->workspace_outputs, wso); + } else { + if (config->reading || !config->active) { + return cmd_results_new(CMD_DEFER, "workspace", 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); + ws = workspace_create(name); + free(name); + } + } else if (strcasecmp(argv[0], "next") == 0) { + ws = workspace_next(old_workspace); + } else if (strcasecmp(argv[0], "prev") == 0) { + ws = workspace_prev(old_workspace); + } else if (strcasecmp(argv[0], "next_on_output") == 0) { + ws = workspace_output_next(old_output); + } else if (strcasecmp(argv[0], "prev_on_output") == 0) { + ws = workspace_output_prev(old_output); + } else if (strcasecmp(argv[0], "back_and_forth") == 0) { + // if auto_back_and_forth is enabled, workspace_switch will swap + // the workspaces. If we created prev_workspace here, workspace_switch + // would put us back on original workspace. + if (config->auto_back_and_forth) { + ws = old_workspace; + } else if (prev_workspace_name + && !(ws = workspace_by_name(prev_workspace_name))) { + ws = workspace_create(prev_workspace_name); + } + } else { + char *name = join_args(argv, argc); + if (!(ws = workspace_by_name(name))) { + ws = workspace_create(name); + } + free(name); + } + workspace_switch(ws); + current_container = config->handler_context.seat->focus; + swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); + + if (config->mouse_warping && old_output != new_output) { + // TODO: Warp mouse + } + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index a67322d1c..213e7680a 100644 --- a/sway/config.c +++ b/sway/config.c @@ -318,10 +318,6 @@ static bool load_config(const char *path, struct sway_config *config) { 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) { @@ -349,7 +345,9 @@ bool load_main_config(const char *file, bool is_active) { config->reading = true; // Read security configs + // TODO: Security bool success = true; + /* DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); if (!dir) { wlr_log(L_ERROR, @@ -392,6 +390,7 @@ bool load_main_config(const char *file, bool is_active) { free_flat_list(secconfigs); } + */ success = success && load_config(path, config); @@ -717,3 +716,11 @@ char *do_var_replacement(char *str) { } return str; } + +// the naming is intentional (albeit long): a workspace_output_cmp function +// would compare two structs in full, while this method only compares the +// workspace. +int workspace_output_cmp_workspace(const void *a, const void *b) { + const struct workspace_output *wsa = a, *wsb = b; + return lenient_strcmp(wsa->workspace, wsb->workspace); +} diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0f00222b3..a650665f4 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -219,8 +219,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { wlr_output_make_current(wlr_output); wlr_renderer_begin(server->renderer, wlr_output); - swayc_descendants_of_type( - &root_container, C_VIEW, output_frame_view, soutput); + swayc_t *workspace = soutput->swayc->focused; + swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); // render unmanaged views on top struct sway_view *view; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 4b50093f4..ca56a9c01 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -124,8 +124,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_surface->view = sway_view; // TODO: - // - Wire up listeners - // - Handle popups // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria @@ -136,11 +134,8 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_surface->destroy.notify = handle_destroy; wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); - // TODO: actual focus semantics - swayc_t *parent = root_container.children->items[0]; - parent = parent->children->items[0]; // workspace - - swayc_t *cont = new_view(parent, sway_view); + struct sway_seat *seat = input_manager_current_seat(input_manager); + swayc_t *cont = new_view(seat->focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 12b3a430e..d789c7eb8 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -23,6 +23,14 @@ struct sway_input_manager *input_manager; struct input_config *current_input_config = NULL; struct seat_config *current_seat_config = NULL; +struct sway_seat *input_manager_current_seat(struct sway_input_manager *input) { + struct sway_seat *seat = config->handler_context.seat; + if (!seat) { + seat = sway_input_manager_get_default_seat(input_manager); + } + return seat; +} + struct sway_seat *input_manager_get_seat( struct sway_input_manager *input, const char *seat_name) { struct sway_seat *seat = NULL; diff --git a/sway/input/seat.c b/sway/input/seat.c index 9ea08eec0..5e87986d0 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,6 +1,7 @@ #define _XOPEN_SOURCE 700 #include #include +#include "sway/container.h" #include "sway/input/seat.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" @@ -81,7 +82,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); - if (seat->focus) { + if (seat->focus && seat->focus->type == C_VIEW) { // force notify reenter to pick up the new configuration wlr_seat_keyboard_clear_focus(seat->wlr_seat); wlr_seat_keyboard_notify_enter(seat->wlr_seat, @@ -205,10 +206,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { static void handle_focus_destroy(struct wl_listener *listener, void *data) { struct sway_seat *seat = wl_container_of(listener, seat, focus_destroy); - //swayc_t *container = data; - - // TODO set new focus based on the state of the tree - sway_seat_set_focus(seat, NULL); + swayc_t *container = data; + sway_seat_set_focus(seat, container->parent); } void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { @@ -218,11 +217,11 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { return; } - if (last_focus) { + if (last_focus && last_focus->type == C_VIEW) { wl_list_remove(&seat->focus_destroy.link); } - if (container) { + if (container && container->type == C_VIEW) { struct sway_view *view = container->sway_view; view_set_activated(view, true); wl_signal_add(&container->events.destroy, &seat->focus_destroy); @@ -241,7 +240,7 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { seat->focus = container; - if (last_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; view_set_activated(view, false); diff --git a/sway/meson.build b/sway/meson.build index 51e9e4dbb..271d4a998 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -35,6 +35,7 @@ sway_sources = files( 'commands/input/xkb_variant.c', 'commands/output.c', 'commands/reload.c', + 'commands/workspace.c', 'config.c', 'config/output.c', 'config/seat.c', diff --git a/sway/tree/container.c b/sway/tree/container.c index b7b9bc682..48aabd865 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -3,10 +3,13 @@ #include #include #include +#include #include #include #include "sway/config.h" #include "sway/container.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/layout.h" #include "sway/output.h" #include "sway/server.h" @@ -14,6 +17,26 @@ #include "sway/workspace.h" #include "log.h" +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) { @@ -127,7 +150,19 @@ 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); - new_workspace(output, ws_name); + swayc_t *ws = new_workspace(output, ws_name); + output->focused = ws; + // Set each seat's focus if not already set + // TODO FOCUS: this is probably stupid, we shouldn't define focus in two + // places. We should probably put the active workspace on the sway_output + // struct instead of trying to do focus semantics like this + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input_manager->seats, link) { + if (!seat->focus) { + seat->focus = ws; + } + } + free(ws_name); return output; } @@ -159,8 +194,8 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { } const char *title = view_get_title(sway_view); swayc_t *swayc = new_swayc(C_VIEW); - wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d", - swayc, title, sibling, sibling ? sibling->type : 0); + 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 swayc->sway_view = sway_view; swayc->name = title ? strdup(title) : NULL; diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c37a873cc..23c630b65 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -2,8 +2,20 @@ #include #include #include +#include #include "sway/container.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" +#include "sway/workspace.h" #include "log.h" +#include "util.h" + +char *prev_workspace_name = NULL; +struct workspace_by_number_data { + int len; + const char *cset; + const char *name; +}; void next_name_map(swayc_t *ws, void *data) { int *count = data; @@ -24,3 +36,202 @@ char *workspace_next_name(const char *output_name) { snprintf(name, len + 1, "%d", count); return name; } + +static bool _workspace_by_number(swayc_t *view, void *data) { + if (view->type != C_WORKSPACE) { + return false; + } + struct workspace_by_number_data *wbnd = data; + int a = strspn(view->name, wbnd->cset); + return a == wbnd->len && strncmp(view->name, wbnd->name, a) == 0; +} + +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 swayc_by_test(&root_container, _workspace_by_number, (void *) &wbnd); +} + +static bool _workspace_by_name(swayc_t *view, void *data) { + return (view->type == C_WORKSPACE) && + (strcasecmp(view->name, (char *) data) == 0); +} + +swayc_t *workspace_by_name(const char *name) { + struct sway_seat *seat = input_manager_current_seat(input_manager); + swayc_t *current_workspace = NULL, *current_output = NULL; + if (seat->focus) { + current_workspace = swayc_parent_by_type(seat->focus, C_WORKSPACE); + current_output = swayc_parent_by_type(seat->focus, C_OUTPUT); + } + if (strcmp(name, "prev") == 0) { + return workspace_prev(current_workspace); + } else if (strcmp(name, "prev_on_output") == 0) { + return workspace_output_prev(current_output); + } else if (strcmp(name, "next") == 0) { + return workspace_next(current_workspace); + } else if (strcmp(name, "next_on_output") == 0) { + return workspace_output_next(current_output); + } else if (strcmp(name, "current") == 0) { + return current_workspace; + } else { + return swayc_by_test(&root_container, _workspace_by_name, (void *) name); + } +} + +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) { + struct workspace_output *wso = config->workspace_outputs->items[i]; + if (strcasecmp(wso->workspace, name) == 0) { + // Find output to use if it exists + e = root_container.children->length; + for (i = 0; i < e; ++i) { + parent = root_container.children->items[i]; + if (strcmp(parent->name, wso->output) == 0) { + return new_workspace(parent, name); + } + } + break; + } + } + // Otherwise create a new one + struct sway_seat *seat = input_manager_current_seat(input_manager); + parent = seat->focus; + parent = swayc_parent_by_type(parent, C_OUTPUT); + return new_workspace(parent, name); +} + +/** + * Get the previous or next workspace on the specified output. Wraps around at + * 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) { + if (!sway_assert(output->type == C_OUTPUT, + "Argument must be an output, is %d", output->type)) { + return NULL; + } + + int i; + for (i = 0; i < output->children->length; i++) { + if (output->children->items[i] == output->focused) { + return output->children->items[ + wrap(i + (next ? 1 : -1), output->children->length)]; + } + } + + // Doesn't happen, at worst the for loop returns the previously active workspace + return NULL; +} + +/** + * Get the previous or next workspace. If the first/last workspace on an output + * is active, proceed to the previous/next output's previous/next workspace. If + * 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) { + if (!sway_assert(workspace->type == C_WORKSPACE, + "Argument must be a workspace, is %d", workspace->type)) { + return NULL; + } + + swayc_t *current_output = workspace->parent; + int offset = next ? 1 : -1; + int start = next ? 0 : 1; + int end; + if (next) { + end = current_output->children->length - 1; + } else { + end = current_output->children->length; + } + int i; + for (i = start; i < end; i++) { + if (current_output->children->items[i] == workspace) { + return current_output->children->items[i + offset]; + } + } + + // 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[ + 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 + return NULL; +} + +swayc_t *workspace_output_next(swayc_t *current) { + return workspace_output_prev_next_impl(current, true); +} + +swayc_t *workspace_next(swayc_t *current) { + return workspace_prev_next_impl(current, true); +} + +swayc_t *workspace_output_prev(swayc_t *current) { + return workspace_output_prev_next_impl(current, false); +} + +swayc_t *workspace_prev(swayc_t *current) { + return workspace_prev_next_impl(current, false); +} + +bool workspace_switch(swayc_t *workspace) { + if (!workspace) { + return false; + } + struct sway_seat *seat = input_manager_current_seat(input_manager); + if (!seat || !seat->focus) { + return false; + } + swayc_t *active_ws = seat->focus; + if (active_ws->type != C_WORKSPACE) { + swayc_parent_by_type(seat->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); + workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); + } + + if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) + && active_ws != workspace)) { + free(prev_workspace_name); + prev_workspace_name = malloc(strlen(active_ws->name) + 1); + if (!prev_workspace_name) { + wlr_log(L_ERROR, "Unable to allocate previous workspace name"); + return false; + } + strcpy(prev_workspace_name, active_ws->name); + } + + // TODO: Deal with sticky containers + + wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); + // TODO FOCUS: Focus the last view this seat had focused on this workspace + if (workspace->children->length) { + // TODO FOCUS: This is really fucking stupid + sway_seat_set_focus(seat, workspace->children->items[0]); + } else { + sway_seat_set_focus(seat, workspace); + } + swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); + // TODO FOCUS: take a look at this + output->focused = workspace; + arrange_windows(output, -1, -1); + return true; +} From 515150229847c9ebdfd0cabb6f0026fca9d57a23 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 4 Feb 2018 13:39:10 -0500 Subject: [PATCH 180/522] basic focus overhaul --- include/sway/container.h | 6 ++ include/sway/input/seat.h | 16 ++++- include/sway/layout.h | 6 ++ sway/commands.c | 5 +- sway/commands/kill.c | 7 +- sway/commands/workspace.c | 3 +- sway/desktop/xdg_shell_v6.c | 3 +- sway/input/input-manager.c | 2 +- sway/input/seat.c | 135 ++++++++++++++++++++++++++++++------ sway/tree/container.c | 33 +++++++-- sway/tree/layout.c | 30 ++++++++ sway/tree/workspace.c | 17 +++-- 12 files changed, 224 insertions(+), 39 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index 0c66932d6..997240bd6 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -162,4 +162,10 @@ void container_map(swayc_t *container, swayc_t *swayc_at(swayc_t *parent, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); +/** + * Get a list of containers that are descendents of the container in rendering + * order + */ +list_t *container_list_children(swayc_t *con); + #endif diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index b21cbccb7..8d5d6b75a 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -12,14 +12,26 @@ struct sway_seat_device { struct wl_list link; // sway_seat::devices }; +struct sway_seat_container { + struct sway_seat *seat; + swayc_t *container; + + struct wl_list link; // sway_seat::focus_stack + + struct wl_listener destroy; +}; + struct sway_seat { struct wlr_seat *wlr_seat; struct seat_config *config; struct sway_cursor *cursor; struct sway_input_manager *input; - swayc_t *focus; + + bool has_focus; + struct wl_list focus_stack; // list of containers in focus order struct wl_listener focus_destroy; + struct wl_listener new_container; struct wl_list devices; // sway_seat_device::link @@ -44,6 +56,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat); void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); +swayc_t *sway_seat_get_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/include/sway/layout.h b/include/sway/layout.h index af5614531..69a666741 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h @@ -2,6 +2,7 @@ #define _SWAY_LAYOUT_H #include +#include "sway/container.h" struct sway_container; @@ -11,10 +12,15 @@ struct sway_root { 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); diff --git a/sway/commands.c b/sway/commands.c index 0d4aa104a..6bb4db0bc 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -281,7 +281,10 @@ struct cmd_results *handle_command(char *_exec) { seat = sway_input_manager_get_default_seat(input_manager); } if (seat) { - config->handler_context.current_container = seat->focus; + config->handler_context.current_container = + (seat->has_focus ? + sway_seat_get_focus(seat, &root_container) : + NULL); struct cmd_results *res = handler->handle(argc-1, argv+1); if (res->status != CMD_SUCCESS) { free_argv(argc, argv); diff --git a/sway/commands/kill.c b/sway/commands/kill.c index cebf7f3c7..4b3666be2 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -10,11 +10,16 @@ struct cmd_results *cmd_kill(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "kill", "Command 'kill' cannot be used in the config file"); } + if (config->handler_context.current_container == NULL) { + wlr_log(L_DEBUG, "no container to kill"); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } enum swayc_types type = config->handler_context.current_container->type; - if (type != C_VIEW || type != C_CONTAINER) { + if (type != C_VIEW && type != C_CONTAINER) { return cmd_results_new(CMD_INVALID, NULL, "Can only kill views and containers with this command"); } + // TODO close arbitrary containers without a view struct sway_view *view = config->handler_context.current_container->sway_view; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 12984ed4a..e7d6cc9f9 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -90,7 +90,8 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { free(name); } workspace_switch(ws); - current_container = config->handler_context.seat->focus; + current_container = + sway_seat_get_focus(config->handler_context.seat, &root_container); swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); if (config->mouse_warping && old_output != new_output) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index ca56a9c01..04d890159 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -135,7 +135,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 *cont = new_view(seat->focus, sway_view); + swayc_t *focus = sway_seat_get_focus(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/input-manager.c b/sway/input/input-manager.c index d789c7eb8..a406636e5 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -282,7 +282,7 @@ 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) { + if (seat->has_focus && sway_seat_get_focus(seat, &root_container) == container) { return true; } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 5e87986d0..cbf05abd4 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -32,6 +32,44 @@ void sway_seat_destroy(struct sway_seat *seat) { wlr_seat_destroy(seat->wlr_seat); } +static void handle_seat_container_destroy(struct wl_listener *listener, + void *data) { + struct sway_seat_container *seat_con = + wl_container_of(listener, seat_con, destroy); + wl_list_remove(&seat_con->link); + wl_list_remove(&seat_con->destroy.link); + free(seat_con); +} + +static struct sway_seat_container *seat_container_from_container( + struct sway_seat *seat, swayc_t *con) { + struct sway_seat_container *seat_con = NULL; + wl_list_for_each(seat_con, &seat->focus_stack, link) { + if (seat_con->container == con) { + return seat_con; + } + } + + seat_con = calloc(1, sizeof(struct sway_seat_container)); + if (seat_con == NULL) { + wlr_log(L_ERROR, "could not allocate seat container"); + return NULL; + } + + seat_con->container = con; + wl_list_insert(seat->focus_stack.prev, &seat_con->link); + wl_signal_add(&con->events.destroy, &seat_con->destroy); + seat_con->destroy.notify = handle_seat_container_destroy; + + return seat_con; +} + +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; + seat_container_from_container(seat, con); +} + 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)); @@ -52,6 +90,24 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, return NULL; } + // init the focus stack + wl_list_init(&seat->focus_stack); + list_t *containers = container_list_children(&root_container); + if (containers == NULL) { + wlr_seat_destroy(seat->wlr_seat); + free(seat); + return NULL; + } + for (int i = containers->length - 1; i >= 0; --i) { + swayc_t *con = containers->items[i]; + seat_container_from_container(seat, con); + } + free(containers); + + wl_signal_add(&root_container.sway_root->events.new_container, + &seat->new_container); + seat->new_container.notify = handle_new_container; + seat->input = input; wl_list_init(&seat->devices); @@ -82,12 +138,15 @@ 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); - if (seat->focus && seat->focus->type == C_VIEW) { - // force notify reenter to pick up the new configuration - wlr_seat_keyboard_clear_focus(seat->wlr_seat); - wlr_seat_keyboard_notify_enter(seat->wlr_seat, - seat->focus->sway_view->surface, wlr_keyboard->keycodes, - wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); + if (seat->has_focus) { + swayc_t *focus = sway_seat_get_focus(seat, &root_container); + if (focus && focus->type == C_VIEW) { + // force notify reenter to pick up the new configuration + wlr_seat_keyboard_clear_focus(seat->wlr_seat); + wlr_seat_keyboard_notify_enter(seat->wlr_seat, + focus->sway_view->surface, wlr_keyboard->keycodes, + wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); + } } } @@ -211,35 +270,43 @@ static void handle_focus_destroy(struct wl_listener *listener, void *data) { } void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { - swayc_t *last_focus = seat->focus; + swayc_t *last_focus = + (seat->has_focus ? sway_seat_get_focus(seat, &root_container) : NULL); - if (last_focus == container) { + if (container && last_focus == container) { return; } - if (last_focus && last_focus->type == C_VIEW) { + if (last_focus) { wl_list_remove(&seat->focus_destroy.link); + seat->has_focus = false; } - if (container && container->type == C_VIEW) { - struct sway_view *view = container->sway_view; - view_set_activated(view, true); + if (container) { + struct sway_seat_container *seat_con = + seat_container_from_container(seat, container); wl_signal_add(&container->events.destroy, &seat->focus_destroy); seat->focus_destroy.notify = handle_focus_destroy; + seat->has_focus = true; - 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); - } else { - wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, - NULL, 0, NULL); + wl_list_remove(&seat_con->link); + wl_list_insert(&seat->focus_stack, &seat_con->link); + + 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); + if (keyboard) { + 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); + } } } - seat->focus = container; - 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; @@ -247,6 +314,30 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { } } +swayc_t *sway_seat_get_focus(struct sway_seat *seat, swayc_t *container) { + struct sway_seat_container *current = NULL; + swayc_t *parent = NULL; + wl_list_for_each(current, &seat->focus_stack, link) { + if (current->container->type < C_WORKSPACE) { + continue; + } + parent = current->container->parent; + + if (current->container == container) { + return current->container; + } + + while (parent) { + if (parent == container) { + return current->container; + } + parent = parent->parent; + } + } + + return NULL; +} + void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config) { // clear configs diff --git a/sway/tree/container.c b/sway/tree/container.c index 48aabd865..67fac5ee5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -158,12 +158,13 @@ swayc_t *new_output(struct sway_output *sway_output) { // struct instead of trying to do focus semantics like this struct sway_seat *seat = NULL; wl_list_for_each(seat, &input_manager->seats, link) { - if (!seat->focus) { - seat->focus = ws; + if (!seat->has_focus) { + sway_seat_set_focus(seat, ws); } } free(ws_name); + wl_signal_emit(&root_container.sway_root->events.new_container, output); return output; } @@ -185,6 +186,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { add_child(output, workspace); sort_workspaces(output); + wl_signal_emit(&root_container.sway_root->events.new_container, workspace); return workspace; } @@ -207,9 +209,9 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { add_child(sibling, swayc); } else { // Regular case, create as sibling of current container - // TODO WLR - //add_sibling(sibling, swayc); + add_sibling(sibling, swayc); } + wl_signal_emit(&root_container.sway_root->events.new_container, swayc); return swayc; } @@ -378,3 +380,26 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi f(container, data); } } + +/** + * Get a list of containers that are descendents of the container in rendering + * order + */ +list_t *container_list_children(swayc_t *con) { + list_t *list = create_list(); + list_t *queue = create_list(); + + list_add(queue, con); + + swayc_t *current = NULL; + while (queue->length) { + current = queue->items[0]; + list_del(queue, 0); + list_add(list, current); + // TODO floating containers + list_cat(queue, current->children); + } + + list_free(queue); + return list; +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 41ff81b2f..45f8c3ae3 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -48,10 +48,12 @@ void init_layout(void) { root_container.layout = L_NONE; root_container.name = strdup("root"); root_container.children = create_list(); + wl_signal_init(&root_container.events.destroy); root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); root_container.sway_root->output_layout = wlr_output_layout_create(); wl_list_init(&root_container.sway_root->unmanaged_views); + wl_signal_init(&root_container.sway_root->events.new_container); root_container.sway_root->output_layout_change.notify = output_layout_change_notify; @@ -59,6 +61,34 @@ void init_layout(void) { &root_container.sway_root->output_layout_change); } +int index_child(const swayc_t *child) { + // TODO handle floating + swayc_t *parent = child->parent; + int i, len; + len = parent->children->length; + for (i = 0; i < len; ++i) { + if (parent->children->items[i] == child) { + break; + } + } + + if (!sway_assert(i < len, "Stray container")) { + return -1; + } + return i; +} + +swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { + // TODO handle floating + swayc_t *parent = fixed->parent; + int i = index_child(fixed); + list_insert(parent->children, i + 1, active); + active->parent = parent; + // focus new child + parent->focused = active; + return active->parent; +} + 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, diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 23c630b65..ce5b425c5 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -63,9 +63,10 @@ static bool _workspace_by_name(swayc_t *view, void *data) { swayc_t *workspace_by_name(const char *name) { struct sway_seat *seat = input_manager_current_seat(input_manager); swayc_t *current_workspace = NULL, *current_output = NULL; - if (seat->focus) { - current_workspace = swayc_parent_by_type(seat->focus, C_WORKSPACE); - current_output = swayc_parent_by_type(seat->focus, C_OUTPUT); + if (seat->has_focus) { + swayc_t *focus = sway_seat_get_focus(seat, &root_container); + 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); @@ -102,7 +103,8 @@ swayc_t *workspace_create(const char *name) { } // Otherwise create a new one struct sway_seat *seat = input_manager_current_seat(input_manager); - parent = seat->focus; + swayc_t *focus = sway_seat_get_focus(seat, &root_container); + parent = focus; parent = swayc_parent_by_type(parent, C_OUTPUT); return new_workspace(parent, name); } @@ -193,12 +195,13 @@ bool workspace_switch(swayc_t *workspace) { return false; } struct sway_seat *seat = input_manager_current_seat(input_manager); - if (!seat || !seat->focus) { + swayc_t *focus = sway_seat_get_focus(seat, &root_container); + if (!seat || !focus) { return false; } - swayc_t *active_ws = seat->focus; + swayc_t *active_ws = focus; if (active_ws->type != C_WORKSPACE) { - swayc_parent_by_type(seat->focus, C_WORKSPACE); + swayc_parent_by_type(focus, C_WORKSPACE); } if (config->auto_back_and_forth From 7d8f2c52aa96e4cbe55fe6fb00895401a85f95b6 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 6 Feb 2018 18:54:10 -0500 Subject: [PATCH 181/522] make index_child static --- sway/tree/layout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 45f8c3ae3..16d5cbc5d 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -61,7 +61,7 @@ void init_layout(void) { &root_container.sway_root->output_layout_change); } -int index_child(const swayc_t *child) { +static int index_child(const swayc_t *child) { // TODO handle floating swayc_t *parent = child->parent; int i, len; From a7d49da23956c245f0e6b8f7dc9cb532eb14c4b9 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 7 Feb 2018 18:17:57 -0500 Subject: [PATCH 182/522] separate seat get focus and seat get focus inactive --- include/sway/input/seat.h | 4 +++- sway/commands.c | 4 +--- sway/commands/workspace.c | 2 +- sway/desktop/xdg_shell_v6.c | 2 +- sway/input/input-manager.c | 2 +- sway/input/seat.c | 32 +++++++++++++++++++------------- sway/tree/workspace.c | 8 ++++---- 7 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 8d5d6b75a..26a7e5dc2 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -56,7 +56,9 @@ void sway_seat_configure_xcursor(struct sway_seat *seat); void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); -swayc_t *sway_seat_get_focus(struct sway_seat *seat, swayc_t *container); +swayc_t *sway_seat_get_focus(struct sway_seat *seat); + +swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container); void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); diff --git a/sway/commands.c b/sway/commands.c index 6bb4db0bc..d8d29a1cf 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -282,9 +282,7 @@ struct cmd_results *handle_command(char *_exec) { } if (seat) { config->handler_context.current_container = - (seat->has_focus ? - sway_seat_get_focus(seat, &root_container) : - NULL); + sway_seat_get_focus(seat); struct cmd_results *res = handler->handle(argc-1, argv+1); if (res->status != CMD_SUCCESS) { free_argv(argc, argv); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index e7d6cc9f9..fa8913984 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -91,7 +91,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { } workspace_switch(ws); current_container = - sway_seat_get_focus(config->handler_context.seat, &root_container); + sway_seat_get_focus(config->handler_context.seat); swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); if (config->mouse_warping && old_output != new_output) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 04d890159..b44d9e54f 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -135,7 +135,7 @@ 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(seat, &root_container); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); swayc_t *cont = new_view(focus, sway_view); sway_view->swayc = cont; diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index a406636e5..90eb8cf63 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -282,7 +282,7 @@ 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->has_focus && sway_seat_get_focus(seat, &root_container) == container) { + if (sway_seat_get_focus(seat) == container) { return true; } } diff --git a/sway/input/seat.c b/sway/input/seat.c index cbf05abd4..d2ffca645 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -137,16 +137,14 @@ static void seat_configure_keyboard(struct sway_seat *seat, struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard; sway_keyboard_configure(seat_device->keyboard); wlr_seat_set_keyboard(seat->wlr_seat, - seat_device->input_device->wlr_device); - if (seat->has_focus) { - swayc_t *focus = sway_seat_get_focus(seat, &root_container); - if (focus && focus->type == C_VIEW) { - // force notify reenter to pick up the new configuration - wlr_seat_keyboard_clear_focus(seat->wlr_seat); - wlr_seat_keyboard_notify_enter(seat->wlr_seat, - focus->sway_view->surface, wlr_keyboard->keycodes, - wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); - } + seat_device->input_device->wlr_device); + 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); + wlr_seat_keyboard_notify_enter(seat->wlr_seat, + focus->sway_view->surface, wlr_keyboard->keycodes, + wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); } } @@ -266,12 +264,13 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { static void handle_focus_destroy(struct wl_listener *listener, void *data) { struct sway_seat *seat = wl_container_of(listener, seat, focus_destroy); swayc_t *container = data; + // TODO dont set focus to the parent, set focus to the next focus inactive + // of the parent sway_seat_set_focus(seat, container->parent); } void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { - swayc_t *last_focus = - (seat->has_focus ? sway_seat_get_focus(seat, &root_container) : NULL); + swayc_t *last_focus = sway_seat_get_focus(seat); if (container && last_focus == container) { return; @@ -314,7 +313,7 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { } } -swayc_t *sway_seat_get_focus(struct sway_seat *seat, swayc_t *container) { +swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container) { struct sway_seat_container *current = NULL; swayc_t *parent = NULL; wl_list_for_each(current, &seat->focus_stack, link) { @@ -338,6 +337,13 @@ swayc_t *sway_seat_get_focus(struct sway_seat *seat, swayc_t *container) { return NULL; } +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); +} + void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config) { // clear configs diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index ce5b425c5..29f07f74a 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -63,8 +63,8 @@ static bool _workspace_by_name(swayc_t *view, void *data) { swayc_t *workspace_by_name(const char *name) { struct sway_seat *seat = input_manager_current_seat(input_manager); swayc_t *current_workspace = NULL, *current_output = NULL; - if (seat->has_focus) { - swayc_t *focus = sway_seat_get_focus(seat, &root_container); + swayc_t *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); } @@ -103,7 +103,7 @@ 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(seat, &root_container); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); parent = focus; parent = swayc_parent_by_type(parent, C_OUTPUT); return new_workspace(parent, name); @@ -195,7 +195,7 @@ bool workspace_switch(swayc_t *workspace) { return false; } struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *focus = sway_seat_get_focus(seat, &root_container); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); if (!seat || !focus) { return false; } From bfd2e8536485c2a8c21eadaa46d03b0709e85fcf Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 10 Feb 2018 15:15:27 -0500 Subject: [PATCH 183/522] refactor workspace.h --- include/sway/workspace.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sway/workspace.h b/include/sway/workspace.h index 30bbdaa8a..ca6f9bdb1 100644 --- a/include/sway/workspace.h +++ b/include/sway/workspace.h @@ -1,7 +1,7 @@ #ifndef _SWAY_WORKSPACE_H #define _SWAY_WORKSPACE_H -struct sway_container; +#include extern char *prev_workspace_name; @@ -12,9 +12,9 @@ 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(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); +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 From 095ddb1561001f21b812dbe0daa5e06bc688ed98 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 10 Feb 2018 15:49:07 -0500 Subject: [PATCH 184/522] fix build for output damage --- sway/desktop/output.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a650665f4..6b6d727a8 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -125,8 +125,9 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, double width = surface->surface->current->width; double height = surface->surface->current->height; - struct wlr_xdg_surface_v6 *popup; - wl_list_for_each(popup, &surface->popups, popup_link) { + struct wlr_xdg_popup_v6 *popup_state; + wl_list_for_each(popup_state, &surface->popups, link) { + struct wlr_xdg_surface_v6 *popup = popup_state->base; if (!popup->configured) { continue; } @@ -216,7 +217,12 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; struct sway_server *server = soutput->server; - wlr_output_make_current(wlr_output); + float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; + struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); + wlr_renderer_clear(renderer, &clear_color); + + int buffer_age = -1; + wlr_output_make_current(wlr_output, &buffer_age); wlr_renderer_begin(server->renderer, wlr_output); swayc_t *workspace = soutput->swayc->focused; @@ -236,7 +242,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } wlr_renderer_end(server->renderer); - wlr_output_swap_buffers(wlr_output); + wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); From 145b4fdf582d3817a19819250cf01836b193c76f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 10 Feb 2018 16:52:45 -0500 Subject: [PATCH 185/522] use bfs iterator to collect focus stack --- include/sway/container.h | 6 +++--- sway/input/seat.c | 27 ++++++++++++++++----------- sway/tree/container.c | 15 +++++++-------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index 997240bd6..01e166add 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -163,9 +163,9 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); /** - * Get a list of containers that are descendents of the container in rendering - * order + * Apply the function for each child of the container breadth first. */ -list_t *container_list_children(swayc_t *con); +void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), + void *data); #endif diff --git a/sway/input/seat.c b/sway/input/seat.c index d2ffca645..ab751b54b 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -70,6 +70,20 @@ static void handle_new_container(struct wl_listener *listener, void *data) { seat_container_from_container(seat, con); } +static void collect_focus_iter(swayc_t *con, void *data) { + struct sway_seat *seat = data; + if (con->type > C_WORKSPACE) { + return; + } + struct sway_seat_container *seat_con = + seat_container_from_container(seat, con); + if (!seat_con) { + return; + } + wl_list_remove(&seat_con->link); + wl_list_insert(&seat->focus_stack, &seat_con->link); +} + 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)); @@ -92,17 +106,8 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, // init the focus stack wl_list_init(&seat->focus_stack); - list_t *containers = container_list_children(&root_container); - if (containers == NULL) { - wlr_seat_destroy(seat->wlr_seat); - free(seat); - return NULL; - } - for (int i = containers->length - 1; i >= 0; --i) { - swayc_t *con = containers->items[i]; - seat_container_from_container(seat, con); - } - free(containers); + + container_for_each_bfs(&root_container, collect_focus_iter, seat); wl_signal_add(&root_container.sway_root->events.new_container, &seat->new_container); diff --git a/sway/tree/container.c b/sway/tree/container.c index 67fac5ee5..ebf9f98e6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -381,13 +381,13 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi } } -/** - * Get a list of containers that are descendents of the container in rendering - * order - */ -list_t *container_list_children(swayc_t *con) { - list_t *list = create_list(); +void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), + void *data) { list_t *queue = create_list(); + if (queue == NULL) { + wlr_log(L_ERROR, "could not allocate list"); + return; + } list_add(queue, con); @@ -395,11 +395,10 @@ list_t *container_list_children(swayc_t *con) { while (queue->length) { current = queue->items[0]; list_del(queue, 0); - list_add(list, current); + f(current, data); // TODO floating containers list_cat(queue, current->children); } list_free(queue); - return list; } From ce3a1b3922850124c562e56ea9a783b090e969b9 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 10 Feb 2018 18:10:29 -0500 Subject: [PATCH 186/522] properly pick next focus --- sway/input/seat.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index ab751b54b..2abe8a1fa 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -36,13 +36,35 @@ static void handle_seat_container_destroy(struct wl_listener *listener, void *data) { 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; + + bool is_focus = (sway_seat_get_focus(seat) == con); + wl_list_remove(&seat_con->link); + + if (is_focus) { + // pick next focus + sway_seat_set_focus(seat, NULL); + swayc_t *next = sway_seat_get_focus_inactive(seat, con->parent); + if (next == NULL) { + next = con->parent; + } + sway_seat_set_focus(seat, next); + } + wl_list_remove(&seat_con->destroy.link); + free(seat_con); } static struct sway_seat_container *seat_container_from_container( struct sway_seat *seat, swayc_t *con) { + if (con->type < C_WORKSPACE) { + // these don't get seat containers ever + return NULL; + } + struct sway_seat_container *seat_con = NULL; wl_list_for_each(seat_con, &seat->focus_stack, link) { if (seat_con->container == con) { @@ -57,6 +79,7 @@ static struct sway_seat_container *seat_container_from_container( } seat_con->container = con; + seat_con->seat = seat; wl_list_insert(seat->focus_stack.prev, &seat_con->link); wl_signal_add(&con->events.destroy, &seat_con->destroy); seat_con->destroy.notify = handle_seat_container_destroy; @@ -266,14 +289,6 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -static void handle_focus_destroy(struct wl_listener *listener, void *data) { - struct sway_seat *seat = wl_container_of(listener, seat, focus_destroy); - swayc_t *container = data; - // TODO dont set focus to the parent, set focus to the next focus inactive - // of the parent - sway_seat_set_focus(seat, container->parent); -} - void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { swayc_t *last_focus = sway_seat_get_focus(seat); @@ -281,17 +296,12 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { return; } - if (last_focus) { - wl_list_remove(&seat->focus_destroy.link); - seat->has_focus = false; - } - if (container) { struct sway_seat_container *seat_con = seat_container_from_container(seat, container); - wl_signal_add(&container->events.destroy, &seat->focus_destroy); - seat->focus_destroy.notify = handle_focus_destroy; - seat->has_focus = true; + if (!seat_con) { + return; + } wl_list_remove(&seat_con->link); wl_list_insert(&seat->focus_stack, &seat_con->link); @@ -316,15 +326,14 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { struct sway_view *view = last_focus->sway_view; view_set_activated(view, false); } + + seat->has_focus = (container != NULL); } swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container) { struct sway_seat_container *current = NULL; swayc_t *parent = NULL; wl_list_for_each(current, &seat->focus_stack, link) { - if (current->container->type < C_WORKSPACE) { - continue; - } parent = current->container->parent; if (current->container == container) { From 93084c9cf80901b160e0eb50b72a8e607289a678 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 10 Feb 2018 19:53:50 -0500 Subject: [PATCH 187/522] remove old focus member --- include/sway/container.h | 4 ---- sway/desktop/output.c | 7 ++++++- sway/ipc-json.c | 4 ++-- sway/tree/container.c | 1 - sway/tree/layout.c | 5 ----- sway/tree/workspace.c | 20 +++++++++++--------- 6 files changed, 19 insertions(+), 22 deletions(-) diff --git a/include/sway/container.h b/include/sway/container.h index 01e166add..48363be62 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -106,10 +106,6 @@ struct sway_container { * The parent of this container. NULL for the root container. */ struct sway_container *parent; - /** - * Which of this container's children has focus. - */ - struct sway_container *focused; /** * Number of master views in auto layouts. diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6b6d727a8..6bbaf9381 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -225,7 +225,12 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { wlr_output_make_current(wlr_output, &buffer_age); wlr_renderer_begin(server->renderer, wlr_output); - swayc_t *workspace = soutput->swayc->focused; + 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 ? + focus : + swayc_parent_by_type(focus, C_WORKSPACE)); + swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); // render unmanaged views on top diff --git a/sway/ipc-json.c b/sway/ipc-json.c index bab9a2014..f0afdc9f6 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -74,8 +74,8 @@ static void ipc_json_describe_output(swayc_t *container, json_object *object) { json_object_object_add(object, "refresh", json_object_new_int(wlr_output->refresh)); json_object_object_add(object, "transform", json_object_new_string(ipc_json_get_output_transform(wlr_output->transform))); - json_object_object_add(object, "current_workspace", - (container->focused) ? json_object_new_string(container->focused->name) : NULL); + // TODO WLR need to set "current_workspace" to the currently focused + // workspace in a way that makes sense with multiseat } static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { diff --git a/sway/tree/container.c b/sway/tree/container.c index ebf9f98e6..d1fb7a79b 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -151,7 +151,6 @@ swayc_t *new_output(struct sway_output *sway_output) { 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); - output->focused = ws; // Set each seat's focus if not already set // TODO FOCUS: this is probably stupid, we shouldn't define focus in two // places. We should probably put the active workspace on the sway_output diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 16d5cbc5d..3651d2793 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -84,8 +84,6 @@ swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { int i = index_child(fixed); list_insert(parent->children, i + 1, active); active->parent = parent; - // focus new child - parent->focused = active; return active->parent; } @@ -96,9 +94,6 @@ void add_child(swayc_t *parent, swayc_t *child) { list_add(parent->children, child); child->parent = parent; // set focus for this container - if (!parent->focused) { - parent->focused = child; - } /* TODO WLR 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); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 29f07f74a..861fda4dd 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -120,9 +120,15 @@ swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { 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 ? + focus : + swayc_parent_by_type(focus, C_WORKSPACE)); + int i; for (i = 0; i < output->children->length; i++) { - if (output->children->items[i] == output->focused) { + if (output->children->items[i] == workspace) { return output->children->items[ wrap(i + (next ? 1 : -1), output->children->length)]; } @@ -225,16 +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); - // TODO FOCUS: Focus the last view this seat had focused on this workspace - if (workspace->children->length) { - // TODO FOCUS: This is really fucking stupid - sway_seat_set_focus(seat, workspace->children->items[0]); - } else { - sway_seat_set_focus(seat, workspace); + swayc_t *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); - // TODO FOCUS: take a look at this - output->focused = workspace; arrange_windows(output, -1, -1); return true; } From 946d9459c57fc38b2536d40a45b7d4c9186b6734 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 14 Feb 2018 14:30:27 -0500 Subject: [PATCH 188/522] get swayc in direction --- include/sway/input/seat.h | 3 + include/sway/layout.h | 14 +++ sway/input/seat.c | 10 +++ sway/tree/layout.c | 174 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 26a7e5dc2..f9244f432 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -60,6 +60,9 @@ swayc_t *sway_seat_get_focus(struct sway_seat *seat); swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container); +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); #endif diff --git a/include/sway/layout.h b/include/sway/layout.h index 69a666741..e82c4442a 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h @@ -4,6 +4,18 @@ #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 { @@ -25,5 +37,7 @@ 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/sway/input/seat.c b/sway/input/seat.c index 2abe8a1fa..648e79143 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -358,6 +358,16 @@ swayc_t *sway_seat_get_focus(struct sway_seat *seat) { 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); + if (focus->type == type) { + return focus; + } + + return swayc_parent_by_type(focus, type); +} + void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config) { // clear configs diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 3651d2793..9768279ae 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -10,6 +10,7 @@ #include "sway/layout.h" #include "sway/output.h" #include "sway/view.h" +#include "sway/input/seat.h" #include "list.h" #include "log.h" @@ -346,3 +347,176 @@ 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) { + // XXX is this really a seat function or can we do it with the default + // seat? + if (!output) { + return NULL; + } + + swayc_t *ws = sway_seat_get_focus_inactive(seat, output); + if (ws->type != C_WORKSPACE) { + ws = swayc_parent_by_type(ws, C_WORKSPACE); + } + + if (ws && ws->children->length > 0) { + switch (dir) { + case MOVE_LEFT: + // get most right child of new output + return ws->children->items[ws->children->length-1]; + case MOVE_RIGHT: + // get most left child of new output + return ws->children->items[0]; + case MOVE_UP: + case MOVE_DOWN: + { + swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); + if (focused && focused->parent) { + swayc_t *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]; + } else if (dir == MOVE_DOWN) { + // get child furthest up on new output + return parent->children->items[0]; + } + } + return focused; + } + break; + } + default: + break; + } + } + + return output; +} + +static void get_absolute_center_position(swayc_t *container, int *x, int *y) { + *x = container->x + container->width/2; + *y = container->y + container->height/2; +} + +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); + } + + swayc_t *parent = container->parent; + if (dir == MOVE_PARENT) { + if (parent->type == C_OUTPUT) { + return NULL; + } else { + return parent; + } + } + + if (dir == MOVE_PREV || dir == MOVE_NEXT) { + int focused_idx = index_child(container); + if (focused_idx == -1) { + return NULL; + } else { + int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) % + parent->children->length; + if (desired < 0) { + desired += parent->children->length; + } + return parent->children->items[desired]; + } + } + + // If moving to an adjacent output we need a starting position (since this + // output might border to multiple outputs). + //struct wlc_point abs_pos; + //get_absolute_center_position(container, &abs_pos); + + + // TODO WLR fullscreen + /* + 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); + get_absolute_center_position(container, &abs_pos); + 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) { + sway_log(L_DEBUG, "Moving to fullscreen view"); + return container->fullscreen; + } + */ + + swayc_t *wrap_candidate = NULL; + while (true) { + // Test if we can even make a difference here + bool can_move = false; + int desired; + int idx = index_child(container); + if (parent->type == C_ROOT) { + struct wlr_output_layout *layout = root_container.sway_root->output_layout; + wlr_output_layout_adjacent_output(layout, container->sway_output->wlr_output); + //swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); + if (!output || output == container) { + return wrap_candidate; + } + wlr_log(L_DEBUG, "Moving between outputs"); + return get_swayc_in_output_direction(output, dir, seat); + } else { + if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { + if (parent->layout == L_HORIZ || parent->layout == L_TABBED) { + can_move = true; + desired = idx + (dir == MOVE_LEFT ? -1 : 1); + } + } else { + if (parent->layout == L_VERT || parent->layout == L_STACKED) { + can_move = true; + desired = idx + (dir == MOVE_UP ? -1 : 1); + } + } + } + + if (can_move) { + // TODO handle floating + if (desired < 0 || desired >= parent->children->length) { + can_move = false; + int len = parent->children->length; + if (!wrap_candidate && len > 1) { + if (desired < 0) { + wrap_candidate = parent->children->items[len-1]; + } else { + wrap_candidate = parent->children->items[0]; + } + if (config->force_focus_wrapping) { + return wrap_candidate; + } + } + } else { + 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]; + } + } + + if (!can_move) { + container = parent; + parent = parent->parent; + if (!parent || container == limit) { + // wrapping is the last chance + return wrap_candidate; + } + } + } +} + +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); +} From 06c71f115bb0632ef1e75d881d509665198e1eef Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 14 Feb 2018 14:42:06 -0500 Subject: [PATCH 189/522] input device destroy --- include/sway/input/input-manager.h | 1 + sway/input/input-manager.c | 61 +++++++++++++++--------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 66ace2626..a76c38807 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -16,6 +16,7 @@ struct sway_input_device { struct wlr_input_device *wlr_device; struct input_config *config; struct wl_list link; + struct wl_listener device_destroy; }; struct sway_input_manager { diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index d789c7eb8..f59daea32 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -160,7 +160,32 @@ static void sway_input_manager_libinput_config_pointer(struct sway_input_device } } -static void input_add_notify(struct wl_listener *listener, void *data) { +static void handle_device_destroy(struct wl_listener *listener, void *data) { + struct wlr_input_device *device = data; + + struct sway_input_device *input_device = + input_sway_device_from_wlr(input_manager, device); + + if (!sway_assert(input_device, "could not find sway device")) { + return; + } + + wlr_log(L_DEBUG, "removing device: '%s'", + input_device->identifier); + + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input_manager->seats, link) { + sway_seat_remove_device(seat, input_device); + } + + wl_list_remove(&input_device->link); + wl_list_remove(&input_device->device_destroy.link); + free_input_config(input_device->config); + free(input_device->identifier); + free(input_device); +} + +static void handle_new_input(struct wl_listener *listener, void *data) { struct sway_input_manager *input = wl_container_of(listener, input, input_add); struct wlr_input_device *device = data; @@ -226,32 +251,9 @@ static void input_add_notify(struct wl_listener *listener, void *data) { "device '%s' is not configured on any seats", input_device->identifier); } -} -static void input_remove_notify(struct wl_listener *listener, void *data) { - struct sway_input_manager *input = - wl_container_of(listener, input, input_remove); - struct wlr_input_device *device = data; - - struct sway_input_device *input_device = - input_sway_device_from_wlr(input, device); - - if (!sway_assert(input_device, "could not find sway device")) { - return; - } - - wlr_log(L_DEBUG, "removing device: '%s'", - input_device->identifier); - - struct sway_seat *seat = NULL; - wl_list_for_each(seat, &input->seats, link) { - sway_seat_remove_device(seat, input_device); - } - - wl_list_remove(&input_device->link); - free_input_config(input_device->config); - free(input_device->identifier); - free(input_device); + wl_signal_add(&device->events.destroy, &input_device->device_destroy); + input_device->device_destroy.notify = handle_device_destroy; } struct sway_input_manager *sway_input_manager_create( @@ -269,11 +271,8 @@ struct sway_input_manager *sway_input_manager_create( // create the default seat input_manager_get_seat(input, default_seat); - input->input_add.notify = input_add_notify; - wl_signal_add(&server->backend->events.input_add, &input->input_add); - - input->input_remove.notify = input_remove_notify; - wl_signal_add(&server->backend->events.input_remove, &input->input_remove); + input->input_add.notify = handle_new_input; + wl_signal_add(&server->backend->events.new_input, &input->input_add); return input; } From 7dfbf06de9a5659d4c73edf53c38ee07068a2877 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 14 Feb 2018 14:51:51 -0500 Subject: [PATCH 190/522] output destroy --- include/sway/output.h | 1 + include/sway/server.h | 7 +++---- sway/desktop/output.c | 12 +++++++----- sway/server.c | 8 ++------ sway/tree/container.c | 2 ++ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 7ca02d7b5..95d647052 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -14,6 +14,7 @@ struct sway_output { struct timespec last_frame; struct wl_listener frame; + struct wl_listener output_destroy; }; #endif diff --git a/include/sway/server.h b/include/sway/server.h index d497e1328..1600babee 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -24,8 +24,7 @@ struct sway_server { struct sway_input_manager *input; - struct wl_listener output_add; - struct wl_listener output_remove; + struct wl_listener new_output; struct wl_listener output_frame; struct wlr_xdg_shell_v6 *xdg_shell_v6; @@ -45,8 +44,8 @@ bool server_init(struct sway_server *server); void server_fini(struct sway_server *server); void server_run(struct sway_server *server); -void output_add_notify(struct wl_listener *listener, void *data); -void output_remove_notify(struct wl_listener *listener, void *data); +void handle_new_output(struct wl_listener *listener, void *data); +void handle_output_destroy(struct wl_listener *listener, void *data); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); void handle_xwayland_surface(struct wl_listener *listener, void *data); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a650665f4..16183870f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -243,8 +243,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { soutput->last_frame = now; } -void output_add_notify(struct wl_listener *listener, void *data) { - struct sway_server *server = wl_container_of(listener, server, output_add); +void handle_new_output(struct wl_listener *listener, void *data) { + struct sway_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; wlr_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); @@ -269,12 +269,14 @@ void output_add_notify(struct wl_listener *listener, void *data) { sway_input_manager_configure_xcursor(input_manager); - output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); + output->frame.notify = output_frame_notify; + + wl_signal_add(&wlr_output->events.destroy, &output->output_destroy); + output->output_destroy.notify = handle_output_destroy; } -void output_remove_notify(struct wl_listener *listener, void *data) { - struct sway_server *server = wl_container_of(listener, server, output_remove); +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); diff --git a/sway/server.c b/sway/server.c index b5eb510be..0753d37e7 100644 --- a/sway/server.c +++ b/sway/server.c @@ -48,12 +48,8 @@ bool server_init(struct sway_server *server) { server->data_device_manager = wlr_data_device_manager_create(server->wl_display); - server->output_add.notify = output_add_notify; - wl_signal_add(&server->backend->events.output_add, &server->output_add); - - server->output_remove.notify = output_remove_notify; - wl_signal_add(&server->backend->events.output_remove, - &server->output_remove); + server->new_output.notify = handle_new_output; + wl_signal_add(&server->backend->events.new_output, &server->new_output); server->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display); wl_signal_add(&server->xdg_shell_v6->events.new_surface, diff --git a/sway/tree/container.c b/sway/tree/container.c index 48aabd865..1a468c199 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -235,6 +235,8 @@ swayc_t *destroy_output(swayc_t *output) { } } + wl_list_remove(&output->sway_output->output_destroy.link); + wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); free_swayc(output); From c6cb87be19dba185e32af59e1e7fd1217a15c08b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 14 Feb 2018 14:55:38 -0500 Subject: [PATCH 191/522] output damage fix --- sway/desktop/output.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 16183870f..a66601b56 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -125,8 +125,9 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, double width = surface->surface->current->width; double height = surface->surface->current->height; - struct wlr_xdg_surface_v6 *popup; - wl_list_for_each(popup, &surface->popups, popup_link) { + struct wlr_xdg_popup_v6 *popup_state; + wl_list_for_each(popup_state, &surface->popups, link) { + struct wlr_xdg_surface_v6 *popup = popup_state->base; if (!popup->configured) { continue; } @@ -215,8 +216,13 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct sway_output *soutput = wl_container_of(listener, soutput, frame); struct wlr_output *wlr_output = data; struct sway_server *server = soutput->server; + float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; + struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); + wlr_renderer_clear(renderer, &clear_color); - wlr_output_make_current(wlr_output); + int buffer_age = -1; + wlr_output_make_current(wlr_output, &buffer_age); + wlr_renderer_begin(server->renderer, wlr_output); wlr_renderer_begin(server->renderer, wlr_output); swayc_t *workspace = soutput->swayc->focused; @@ -236,7 +242,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } wlr_renderer_end(server->renderer); - wlr_output_swap_buffers(wlr_output); + wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); From 780d9fe1e3ee051a4d9eb08d1c049e19d72c1d6a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 14 Feb 2018 15:23:56 -0500 Subject: [PATCH 192/522] cleanup layout.c --- sway/tree/layout.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 205f42eb5..5e8f4c562 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -173,8 +173,8 @@ void arrange_windows(swayc_t *container, double width, double height) { height = floor(height); wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, - container->name, container->width, container->height, container->x, - container->y); + container->name, container->width, container->height, container->x, + container->y); double x = 0, y = 0; switch (container->type) { @@ -275,8 +275,8 @@ static void apply_horiz_layout(swayc_t *container, for (int i = start; i < end; ++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); + "Calculating arrangement for %p:%d (will scale %f by %f)", + child, child->type, width, scale); view_set_position(child->sway_view, child_x, y); if (i == end - 1) { @@ -325,8 +325,8 @@ void apply_vert_layout(swayc_t *container, for (i = start; i < end; ++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); + "Calculating arrangement for %p:%d (will scale %f by %f)", + child, child->type, height, scale); view_set_position(child->sway_view, x, child_y); if (i == end - 1) { @@ -373,24 +373,23 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output, // get most left child of new output return ws->children->items[0]; case MOVE_UP: - case MOVE_DOWN: - { - swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); - if (focused && focused->parent) { - swayc_t *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]; - } else if (dir == MOVE_DOWN) { - // get child furthest up on new output - return parent->children->items[0]; - } + case MOVE_DOWN: { + swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); + if (focused && focused->parent) { + swayc_t *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]; + } else if (dir == MOVE_DOWN) { + // get child furthest up on new output + return parent->children->items[0]; } - return focused; } - break; + return focused; } + break; + } default: break; } From 52670c636cf5115560ce6d20e2aaab1d55c49d0b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 14 Feb 2018 16:47:23 -0500 Subject: [PATCH 193/522] basic focus (without direction) --- sway/commands.c | 1 + sway/commands/focus.c | 32 ++++++++++++++++++++++++++++++++ sway/ipc-server.c | 1 + sway/meson.build | 1 + 4 files changed, 35 insertions(+) create mode 100644 sway/commands/focus.c diff --git a/sway/commands.c b/sway/commands.c index d8d29a1cf..bc2a85d7f 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -132,6 +132,7 @@ static struct cmd_handler handlers[] = { { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, { "exit", cmd_exit }, + { "focus", cmd_focus }, { "include", cmd_include }, { "input", cmd_input }, { "kill", cmd_kill }, diff --git a/sway/commands/focus.c b/sway/commands/focus.c new file mode 100644 index 000000000..5286851fb --- /dev/null +++ b/sway/commands/focus.c @@ -0,0 +1,32 @@ +#include +#include "log.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" +#include "sway/view.h" +#include "sway/commands.h" + +struct cmd_results *cmd_focus(int argc, char **argv) { + swayc_t *con = config->handler_context.current_container; + struct sway_seat *seat = config->handler_context.seat; + + if (!sway_assert(seat, "'focus' command called without seat context")) { + return cmd_results_new(CMD_FAILURE, "focus", + "Command 'focus' called without seat context (this is a bug in sway)"); + } + + if (config->reading) { + return cmd_results_new(CMD_FAILURE, "focus", + "Command 'focus' cannot be used in the config file"); + } + if (con == NULL) { + wlr_log(L_DEBUG, "no container to focus"); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + + if (argc == 0) { + sway_seat_set_focus(seat, con); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/ipc-server.c b/sway/ipc-server.c index a16a2b806..ee259c990 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -336,6 +336,7 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_COMMAND: { config_clear_handler_context(config); + config->handler_context.seat = input_manager_current_seat(input_manager); struct cmd_results *results = handle_command(buf); const char *json = cmd_results_to_json(results); char reply[256]; diff --git a/sway/meson.build b/sway/meson.build index 271d4a998..8d5a97d2e 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/focus.c', 'commands/kill.c', 'commands/include.c', 'commands/input.c', From a3ae67af4e47467b134b876e42a148b1895e7283 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 14 Feb 2018 17:12:21 -0500 Subject: [PATCH 194/522] basic focus in direction --- sway/commands/focus.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 5286851fb..ba47d1e13 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -1,3 +1,4 @@ +#include #include #include "log.h" #include "sway/input/input-manager.h" @@ -5,6 +6,30 @@ #include "sway/view.h" #include "sway/commands.h" +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) { + *out = MOVE_RIGHT; + } else if (strcasecmp(name, "up") == 0) { + *out = MOVE_UP; + } else if (strcasecmp(name, "down") == 0) { + *out = MOVE_DOWN; + } else if (strcasecmp(name, "parent") == 0) { + *out = MOVE_PARENT; + } else if (strcasecmp(name, "child") == 0) { + *out = MOVE_CHILD; + } else if (strcasecmp(name, "next") == 0) { + *out = MOVE_NEXT; + } else if (strcasecmp(name, "prev") == 0) { + *out = MOVE_PREV; + } else { + return false; + } + + return true; +} + struct cmd_results *cmd_focus(int argc, char **argv) { swayc_t *con = config->handler_context.current_container; struct sway_seat *seat = config->handler_context.seat; @@ -22,11 +47,27 @@ struct cmd_results *cmd_focus(int argc, char **argv) { wlr_log(L_DEBUG, "no container to focus"); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } + if (con->type < C_WORKSPACE) { + return cmd_results_new(CMD_FAILURE, "focus", + "Command 'focus' cannot be used above the workspace level"); + } if (argc == 0) { sway_seat_set_focus(seat, con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } + // TODO mode_toggle + enum movement_direction direction = 0; + if (!parse_movement_direction(argv[0], &direction)) { + return cmd_results_new(CMD_INVALID, "focus", + "Expected 'focus ' or 'focus output '"); + } + + swayc_t *next_focus = get_swayc_in_direction(con, seat, direction); + if (next_focus) { + sway_seat_set_focus(seat, next_focus); + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From 9510a20fcda00eecf077cc5cb06f5d47d87bccee Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 17 Feb 2018 13:32:04 -0500 Subject: [PATCH 195/522] arrange windows after output add --- sway/desktop/output.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index e250d4505..ba282c2ce 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -286,6 +286,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { wl_signal_add(&wlr_output->events.destroy, &output->output_destroy); output->output_destroy.notify = handle_output_destroy; + + arrange_windows(&root_container, -1, -1); } void handle_output_destroy(struct wl_listener *listener, void *data) { From 7c089442c3c9877eec2422780f6ce57315de2d11 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 17 Feb 2018 15:18:21 -0500 Subject: [PATCH 196/522] use box projection function --- sway/desktop/output.c | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index ba282c2ce..7b7fcbb9d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -57,46 +57,7 @@ static void render_surface(struct wlr_surface *surface, }; if (wlr_output_layout_intersects(layout, wlr_output, &render_box)) { float matrix[16]; - - float translate_center[16]; - wlr_matrix_translate(&translate_center, - (int)ox + render_width / 2, (int)oy + render_height / 2, 0); - - float rotate[16]; - wlr_matrix_rotate(&rotate, rotation); - - float translate_origin[16]; - wlr_matrix_translate(&translate_origin, -render_width / 2, - -render_height / 2, 0); - - float scale[16]; - wlr_matrix_scale(&scale, render_width, render_height, 1); - - float transform[16]; - wlr_matrix_mul(&translate_center, &rotate, &transform); - wlr_matrix_mul(&transform, &translate_origin, &transform); - wlr_matrix_mul(&transform, &scale, &transform); - - if (surface->current->transform != WL_OUTPUT_TRANSFORM_NORMAL) { - float surface_translate_center[16]; - wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0); - - float surface_transform[16]; - wlr_matrix_transform(surface_transform, - wlr_output_transform_invert(surface->current->transform)); - - float surface_translate_origin[16]; - wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0); - - wlr_matrix_mul(&transform, &surface_translate_center, - &transform); - wlr_matrix_mul(&transform, &surface_transform, &transform); - wlr_matrix_mul(&transform, &surface_translate_origin, - &transform); - } - - wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix); - + wlr_matrix_project_box(&matrix, &render_box, surface->current->transform, 0, &wlr_output->transform_matrix); wlr_render_with_matrix(server.renderer, surface->texture, &matrix); @@ -220,8 +181,6 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); wlr_renderer_clear(renderer, &clear_color); - wlr_renderer_clear(renderer, &clear_color); - int buffer_age = -1; wlr_output_make_current(wlr_output, &buffer_age); wlr_renderer_begin(server->renderer, wlr_output); From 80927985fbb40e0bdf2a3c4322d808a9681cca6a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 17 Feb 2018 16:30:32 -0500 Subject: [PATCH 197/522] fix output rendering issue --- sway/desktop/output.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 7b7fcbb9d..a3d9efd87 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -46,18 +46,22 @@ static void render_surface(struct wlr_surface *surface, int height = surface->current->height; int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; - double ox = lx, oy = ly; - wlr_output_layout_output_coords(layout, wlr_output, &ox, &oy); - ox *= wlr_output->scale; - oy *= wlr_output->scale; + int owidth, oheight; + wlr_output_effective_resolution(wlr_output, &owidth, &oheight); - struct wlr_box render_box = { - .x = lx, .y = ly, + // FIXME: view coords are inconsistently assumed to be in output or layout coords + struct wlr_box layout_box = { + .x = lx + owidth, .y = ly + oheight, .width = render_width, .height = render_height, }; - if (wlr_output_layout_intersects(layout, wlr_output, &render_box)) { + if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { + struct wlr_box render_box = { + .x = lx, .y = ly, + .width = render_width, .height = render_height + }; float matrix[16]; - wlr_matrix_project_box(&matrix, &render_box, surface->current->transform, 0, &wlr_output->transform_matrix); + wlr_matrix_project_box(&matrix, &render_box, + surface->current->transform, 0, &wlr_output->transform_matrix); wlr_render_with_matrix(server.renderer, surface->texture, &matrix); From fb37e802252b35fd63c68df6b19549b715474821 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 17 Feb 2018 18:33:02 -0500 Subject: [PATCH 198/522] basic move focus in direction across outputs --- sway/tree/layout.c | 86 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 5e8f4c562..6a5743039 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -398,9 +398,58 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output, return output; } -static void get_absolute_center_position(swayc_t *container, int *x, int *y) { - *x = container->x + container->width/2; - *y = container->y + container->height/2; +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 { + 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. + *x = output->x; + *y = output->y; + } else { + *x = output->x + container->x; + *y = output->y + container->y; + } + } +} + +static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) { + *out = 0; + switch (dir) { + case MOVE_UP: + *out = WLR_DIRECTION_UP; + break; + case MOVE_DOWN: + *out = WLR_DIRECTION_DOWN; + break; + case MOVE_LEFT: + *out = WLR_DIRECTION_LEFT; + break; + case MOVE_RIGHT: + *out = WLR_DIRECTION_RIGHT; + break; + default: + break; + } + + return *out != 0; +} + +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) { + swayc_t *o = root_container.children->items[i]; + if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) { + return o; + } + } + return NULL; } static swayc_t *get_swayc_in_direction_under(swayc_t *container, @@ -435,7 +484,7 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, // If moving to an adjacent output we need a starting position (since this // output might border to multiple outputs). //struct wlc_point abs_pos; - //get_absolute_center_position(container, &abs_pos); + //get_layout_center_position(container, &abs_pos); // TODO WLR fullscreen @@ -443,7 +492,7 @@ 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); - get_absolute_center_position(container, &abs_pos); + get_layout_center_position(container, &abs_pos); swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); return get_swayc_in_output_direction(output, dir); } @@ -460,17 +509,28 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, int desired; int idx = index_child(container); if (parent->type == C_ROOT) { - // TODO - /* + enum wlr_direction wlr_dir = 0; + if (!sway_assert(sway_dir_to_wlr(dir, &wlr_dir), + "got invalid direction: %d", dir)) { + return NULL; + } + int lx, ly; + get_layout_center_position(container, &lx, &ly); struct wlr_output_layout *layout = root_container.sway_root->output_layout; - wlr_output_layout_adjacent_output(layout, container->sway_output->wlr_output); - //swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); - if (!output || output == 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); + + if (!adjacent || adjacent == container) { return wrap_candidate; } - wlr_log(L_DEBUG, "Moving between outputs"); - return get_swayc_in_output_direction(output, dir, seat); - */ + // TODO descend into the focus-inactive of the physically closest + // view of the output + //swayc_t *new_con = get_swayc_in_output_direction(adjacent, dir, seat); + swayc_t *new_con = sway_seat_get_focus_inactive(seat, adjacent); + return new_con; + } else { if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { if (parent->layout == L_HORIZ || parent->layout == L_TABBED) { From 176d24f02dfaa0a7866dd4ea278d0cbf30fa23bb Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 17 Feb 2018 19:03:21 -0500 Subject: [PATCH 199/522] choose adjacent container between outputs --- sway/tree/layout.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 6a5743039..be494791c 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -364,7 +364,12 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output, ws = swayc_parent_by_type(ws, C_WORKSPACE); } - if (ws && ws->children->length > 0) { + if (ws == NULL) { + wlr_log(L_ERROR, "got an output without a workspace"); + return NULL; + } + + if (ws->children->length > 0) { switch (dir) { case MOVE_LEFT: // get most right child of new output @@ -395,7 +400,7 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output, } } - return output; + return ws; } static void get_layout_center_position(swayc_t *container, int *x, int *y) { @@ -525,12 +530,13 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, if (!adjacent || adjacent == container) { return wrap_candidate; } - // TODO descend into the focus-inactive of the physically closest - // view of the output - //swayc_t *new_con = get_swayc_in_output_direction(adjacent, dir, seat); - swayc_t *new_con = sway_seat_get_focus_inactive(seat, adjacent); - return new_con; - + swayc_t *next = get_swayc_in_output_direction(adjacent, dir, seat); + if (next->children->length) { + // TODO consider floating children as well + return sway_seat_get_focus_inactive(seat, next); + } else { + return next; + } } else { if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { if (parent->layout == L_HORIZ || parent->layout == L_TABBED) { From f0ca2cb5c367a0142b6988d04c6b996f1c296055 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 17 Feb 2018 19:05:17 -0500 Subject: [PATCH 200/522] use quotes for container include --- include/sway/workspace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sway/workspace.h b/include/sway/workspace.h index ca6f9bdb1..fee54255c 100644 --- a/include/sway/workspace.h +++ b/include/sway/workspace.h @@ -1,7 +1,7 @@ #ifndef _SWAY_WORKSPACE_H #define _SWAY_WORKSPACE_H -#include +#include "sway/container.h" extern char *prev_workspace_name; From 5e9fe97e36b5e33b9919c2cfee776fc8eac05959 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 18 Feb 2018 11:20:18 -0500 Subject: [PATCH 201/522] Add -Wno-unused-function This is temporary, it helps while we work on porting and large swaths of the code are commented out. --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index 493921263..fc995c815 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,7 @@ project( ) add_project_arguments('-Wno-unused-parameter', language: 'c') +add_project_arguments('-Wno-unused-function', language: 'c') cc = meson.get_compiler('c') From b88f06e70a62722e70855772dcfa5b20b3a10291 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 19 Feb 2018 17:55:16 -0500 Subject: [PATCH 202/522] bugfix: get right layout box for rendering views --- sway/desktop/output.c | 2 +- sway/tree/layout.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a3d9efd87..039aba254 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -51,7 +51,7 @@ static void render_surface(struct wlr_surface *surface, // FIXME: view coords are inconsistently assumed to be in output or layout coords struct wlr_box layout_box = { - .x = lx + owidth, .y = ly + oheight, + .x = lx + wlr_output->lx, .y = ly + wlr_output->ly, .width = render_width, .height = render_height, }; if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index be494791c..3c78b6bc5 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -531,7 +531,10 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container, return wrap_candidate; } swayc_t *next = get_swayc_in_output_direction(adjacent, dir, seat); - if (next->children->length) { + if (next == NULL) { + return NULL; + } + if (next->children && next->children->length) { // TODO consider floating children as well return sway_seat_get_focus_inactive(seat, next); } else { From 66a975038c2f6cc3d2ebb5210d182b0440bc0a88 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 20 Feb 2018 19:01:02 -0500 Subject: [PATCH 203/522] add doc to sway_seat_get_focus_inactive() --- include/sway/input/seat.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index f9244f432..1d55bec7a 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -58,6 +58,15 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); swayc_t *sway_seat_get_focus(struct sway_seat *seat); +/** + * Return the last container to be focused for the seat (or the most recently + * opened if no container has received focused) that is a child of the given + * container. The focus-inactive container of the root window is the focused + * container for the seat (if the seat does have focus). This function can be + * used to determine what container gets focused next if the focused container + * 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); swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, From 4c4cc9c99943b4f80f1551c421b372b016dd04e6 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 20 Feb 2018 19:04:03 -0500 Subject: [PATCH 204/522] remove old comments --- sway/tree/container.c | 3 --- sway/tree/layout.c | 2 -- 2 files changed, 5 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index a62681333..84e14ba69 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -152,9 +152,6 @@ swayc_t *new_output(struct sway_output *sway_output) { wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); swayc_t *ws = new_workspace(output, ws_name); // Set each seat's focus if not already set - // TODO FOCUS: this is probably stupid, we shouldn't define focus in two - // places. We should probably put the active workspace on the sway_output - // struct instead of trying to do focus semantics like this struct sway_seat *seat = NULL; wl_list_for_each(seat, &input_manager->seats, link) { if (!seat->has_focus) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 3c78b6bc5..91f0f36f5 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -353,8 +353,6 @@ void apply_vert_layout(swayc_t *container, */ static swayc_t *get_swayc_in_output_direction(swayc_t *output, enum movement_direction dir, struct sway_seat *seat) { - // XXX is this really a seat function or can we do it with the default - // seat? if (!output) { return NULL; } From 316effd7b1f6b60f70038f9a5df5d58eb879cf90 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 20 Feb 2018 19:06:56 -0500 Subject: [PATCH 205/522] make handle_output_destroy() static --- include/sway/server.h | 1 - sway/desktop/output.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index 1600babee..3fcdb1baf 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -45,7 +45,6 @@ void server_fini(struct sway_server *server); void server_run(struct sway_server *server); void handle_new_output(struct wl_listener *listener, void *data); -void handle_output_destroy(struct wl_listener *listener, void *data); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); void handle_xwayland_surface(struct wl_listener *listener, void *data); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 039aba254..8e0daeeaf 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -218,6 +218,26 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { soutput->last_frame = now; } +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); + + swayc_t *output_container = NULL; + for (int i = 0 ; i < root_container.children->length; ++i) { + swayc_t *child = root_container.children->items[i]; + if (child->type == C_OUTPUT && + child->sway_output->wlr_output == wlr_output) { + output_container = child; + break; + } + } + if (!output_container) { + return; + } + + destroy_output(output_container); +} + void handle_new_output(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; @@ -252,23 +272,3 @@ void handle_new_output(struct wl_listener *listener, void *data) { arrange_windows(&root_container, -1, -1); } - -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); - - swayc_t *output_container = NULL; - for (int i = 0 ; i < root_container.children->length; ++i) { - swayc_t *child = root_container.children->items[i]; - if (child->type == C_OUTPUT && - child->sway_output->wlr_output == wlr_output) { - output_container = child; - break; - } - } - if (!output_container) { - return; - } - - destroy_output(output_container); -} From 4b3aa59b8bfaa5d6136b54ba7f347f5d93fa210f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 20 Feb 2018 19:09:38 -0500 Subject: [PATCH 206/522] rename new_input listener on input-manager --- include/sway/input/input-manager.h | 4 ++-- sway/input/input-manager.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index a76c38807..eab7dc90f 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -20,11 +20,11 @@ struct sway_input_device { }; struct sway_input_manager { - struct wl_listener input_add; - struct wl_listener input_remove; struct sway_server *server; struct wl_list devices; struct wl_list seats; + + struct wl_listener new_input; }; struct sway_input_manager *sway_input_manager_create( diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index e6708bade..27c2c72eb 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -187,7 +187,7 @@ static void handle_device_destroy(struct wl_listener *listener, void *data) { static void handle_new_input(struct wl_listener *listener, void *data) { struct sway_input_manager *input = - wl_container_of(listener, input, input_add); + wl_container_of(listener, input, new_input); struct wlr_input_device *device = data; struct sway_input_device *input_device = @@ -271,8 +271,8 @@ struct sway_input_manager *sway_input_manager_create( // create the default seat input_manager_get_seat(input, default_seat); - input->input_add.notify = handle_new_input; - wl_signal_add(&server->backend->events.new_input, &input->input_add); + input->new_input.notify = handle_new_input; + wl_signal_add(&server->backend->events.new_input, &input->new_input); return input; } From 23e9f5dc350b8d1f399ffe2e5b761f21dc9c46a8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 20 Feb 2018 19:21:32 -0500 Subject: [PATCH 207/522] use wl_container_of() in output destroy callback --- sway/desktop/output.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 8e0daeeaf..63420d0cc 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -219,23 +219,11 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } static void handle_output_destroy(struct wl_listener *listener, void *data) { + struct sway_output *output = wl_container_of(listener, output, output_destroy); struct wlr_output *wlr_output = data; wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); - swayc_t *output_container = NULL; - for (int i = 0 ; i < root_container.children->length; ++i) { - swayc_t *child = root_container.children->items[i]; - if (child->type == C_OUTPUT && - child->sway_output->wlr_output == wlr_output) { - output_container = child; - break; - } - } - if (!output_container) { - return; - } - - destroy_output(output_container); + destroy_output(output->swayc); } void handle_new_output(struct wl_listener *listener, void *data) { From bcb870bcf2b31b4b03ef746bd60b74eb3ea9cb78 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 20 Feb 2018 19:47:48 -0500 Subject: [PATCH 208/522] bug: fix crash on focus up --- sway/tree/layout.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 91f0f36f5..3d04a1a74 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -421,7 +421,6 @@ 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) { - *out = 0; switch (dir) { case MOVE_UP: *out = WLR_DIRECTION_UP; @@ -436,10 +435,10 @@ static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out *out = WLR_DIRECTION_RIGHT; break; default: - break; + return false; } - return *out != 0; + return true; } static swayc_t *sway_output_from_wlr(struct wlr_output *output) { From 66d1e0b313c6bbee142bb08e4af07ce6f15cffca Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 22 Feb 2018 18:03:46 -0500 Subject: [PATCH 209/522] basic layout command --- include/sway/container.h | 2 ++ sway/commands.c | 1 + sway/commands/layout.c | 65 ++++++++++++++++++++++++++++++++++++++++ sway/meson.build | 1 + sway/tree/container.c | 12 ++++++++ 5 files changed, 81 insertions(+) create mode 100644 sway/commands/layout.c diff --git a/include/sway/container.h b/include/sway/container.h index 48363be62..f200a1a2e 100644 --- a/include/sway/container.h +++ b/include/sway/container.h @@ -164,4 +164,6 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, 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/sway/commands.c b/sway/commands.c index bc2a85d7f..a7eb6b4a6 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -136,6 +136,7 @@ static struct cmd_handler handlers[] = { { "include", cmd_include }, { "input", cmd_input }, { "kill", cmd_kill }, + { "layout", cmd_layout }, { "output", cmd_output }, { "reload", cmd_reload }, { "seat", cmd_seat }, diff --git a/sway/commands/layout.c b/sway/commands/layout.c new file mode 100644 index 000000000..d953abc8c --- /dev/null +++ b/sway/commands/layout.c @@ -0,0 +1,65 @@ +#include +#include +#include "sway/commands.h" +#include "sway/container.h" +#include "sway/layout.h" +#include "log.h" + +struct cmd_results *cmd_layout(int argc, char **argv) { + struct cmd_results *error = NULL; + if (config->reading) { + return cmd_results_new(CMD_FAILURE, "layout", "Can't be used in config file."); + } + if (!config->active) { + return cmd_results_new(CMD_FAILURE, "layout", "Can only be used when sway is running."); + } + if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { + return error; + } + swayc_t *parent = config->handler_context.current_container; + if (!sway_assert(parent != NULL, "command called without container context")) { + return NULL; + } + + // TODO: floating + /* + if (parent->is_floating) { + return cmd_results_new(CMD_FAILURE, "layout", "Unable to change layout of floating windows"); + } + */ + + while (parent->type == C_VIEW) { + parent = parent->parent; + } + + // TODO: stacks and tabs + + 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); + swayc_change_layout(parent, default_layout(output)); + } + } else { + if (parent->layout != L_TABBED && parent->layout != L_STACKED) { + parent->prev_layout = parent->layout; + } + + if (strcasecmp(argv[0], "splith") == 0) { + swayc_change_layout(parent, L_HORIZ); + } else if (strcasecmp(argv[0], "splitv") == 0) { + 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)) { + swayc_change_layout(parent, L_VERT); + } else { + swayc_change_layout(parent, L_HORIZ); + } + } + } + + arrange_windows(parent, parent->width, parent->height); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index 8d5a97d2e..26e56ad21 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -14,6 +14,7 @@ sway_sources = files( 'commands/kill.c', 'commands/include.c', 'commands/input.c', + 'commands/layout.c', 'commands/seat.c', 'commands/seat/attach.c', 'commands/seat/fallback.c', diff --git a/sway/tree/container.c b/sway/tree/container.c index 84e14ba69..b56e72e19 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -400,3 +400,15 @@ void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), list_free(queue); } + +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; +} From 6becfc14310e1443fc058b57c3ff756f3cb06af3 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 24 Feb 2018 12:49:42 -0500 Subject: [PATCH 210/522] update log.h for latest wlr --- include/log.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/log.h b/include/log.h index 350a59ef3..a97481274 100644 --- a/include/log.h +++ b/include/log.h @@ -5,11 +5,11 @@ void _sway_abort(const char *filename, ...) ATTRIB_PRINTF(1, 2); #define sway_abort(FMT, ...) \ - _sway_abort("[%s:%d] " FMT, _strip_path(__FILE__), __LINE__, ##__VA_ARGS__) + _sway_abort("[%s:%d] " FMT, wlr_strip_path(__FILE__), __LINE__, ##__VA_ARGS__) bool _sway_assert(bool condition, const char* format, ...) ATTRIB_PRINTF(2, 3); #define sway_assert(COND, FMT, ...) \ - _sway_assert(COND, "[%s:%d] %s:" FMT, _strip_path(__FILE__), __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) + _sway_assert(COND, "[%s:%d] %s:" FMT, wlr_strip_path(__FILE__), __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) void error_handler(int sig); From ac8269d536bf636bd0fbf8047cf6516912634864 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 24 Feb 2018 12:50:24 -0500 Subject: [PATCH 211/522] take seat param for handle_command and rename --- include/sway/commands.h | 4 ++-- sway/commands.c | 46 ++++++++++++++++++++++++----------------- sway/input/keyboard.c | 2 +- sway/ipc-server.c | 3 +-- sway/server.c | 2 +- 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/include/sway/commands.h b/include/sway/commands.h index 4ee7af2a3..9ff18823d 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -46,9 +46,9 @@ struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val); /** - * Parse and handles a command. + * Parse and executes a command. */ -struct cmd_results *handle_command(char *command); +struct cmd_results *execute_command(char *command, struct sway_seat *seat); /** * Parse and handles a command during config file loading. * diff --git a/sway/commands.c b/sway/commands.c index a7eb6b4a6..66614058c 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -198,7 +198,7 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { return res; } -struct cmd_results *handle_command(char *_exec) { +struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { // Even though this function will process multiple commands we will only // return the last error, if any (for now). (Since we have access to an // error string we could e.g. concatenate all errors there.) @@ -209,6 +209,16 @@ struct cmd_results *handle_command(char *_exec) { char *cmd; list_t *containers = NULL; + if (seat == NULL) { + // passing a NULL seat means we just pick the default seat + seat = sway_input_manager_get_default_seat(input_manager); + if (!sway_assert(seat, "could not find a seat to run the command on")) { + return NULL; + } + } + + config->handler_context.seat = seat; + head = exec; do { // Extract criteria (valid for this command list only). @@ -278,24 +288,22 @@ struct cmd_results *handle_command(char *_exec) { if (!has_criteria) { // without criteria, the command acts upon the focused // container - struct sway_seat *seat = config->handler_context.seat; - if (!seat) { - seat = sway_input_manager_get_default_seat(input_manager); + config->handler_context.current_container = + sway_seat_get_focus_inactive(seat, &root_container); + if (!sway_assert(config->handler_context.current_container, + "could not get focus-inactive for root container")) { + return NULL; } - if (seat) { - config->handler_context.current_container = - sway_seat_get_focus(seat); - 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; + 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); } - free_cmd_results(res); + results = res; + goto cleanup; } + free_cmd_results(res); } else { for (int i = 0; i < containers->length; ++i) { config->handler_context.current_container = containers->items[i]; @@ -322,13 +330,13 @@ cleanup: return results; } -// this is like handle_command above, except: +// this is like execute_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) +// 4) execute_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; diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 6dc57d461..996850525 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -95,7 +95,7 @@ static void keyboard_execute_command(struct sway_keyboard *keyboard, binding->command); config_clear_handler_context(config); config->handler_context.seat = keyboard->seat_device->sway_seat; - struct cmd_results *results = handle_command(binding->command); + struct cmd_results *results = execute_command(binding->command, NULL); if (results->status != CMD_SUCCESS) { wlr_log(L_DEBUG, "could not run command for binding: %s", binding->command); diff --git a/sway/ipc-server.c b/sway/ipc-server.c index ee259c990..4c0953e8a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -336,8 +336,7 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_COMMAND: { config_clear_handler_context(config); - config->handler_context.seat = input_manager_current_seat(input_manager); - struct cmd_results *results = handle_command(buf); + struct cmd_results *results = execute_command(buf, NULL); const char *json = cmd_results_to_json(results); char reply[256]; int length = snprintf(reply, sizeof(reply), "%s", json); diff --git a/sway/server.c b/sway/server.c index 0753d37e7..495769ee7 100644 --- a/sway/server.c +++ b/sway/server.c @@ -22,7 +22,7 @@ static void server_ready(struct wl_listener *listener, void *data) { config->active = true; while (config->cmd_queue->length) { char *line = config->cmd_queue->items[0]; - struct cmd_results *res = handle_command(line); + struct cmd_results *res = execute_command(line, NULL); if (res->status != CMD_SUCCESS) { wlr_log(L_ERROR, "Error on line '%s': %s", line, res->error); } From 5b219a15982b9626f85535c082ee2adb460ad11d Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 24 Feb 2018 13:20:34 -0500 Subject: [PATCH 212/522] separate config directives and commands --- sway/commands.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index 66614058c..ed8da3dcd 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -125,25 +125,35 @@ struct cmd_results *add_color(const char *name, char *buffer, const char *color) return NULL; } -/* Keep alphabetized */ +/** + * handlers that can run in either config or command context + * Keep alphabetized + */ static struct cmd_handler handlers[] = { { "bindcode", cmd_bindcode }, { "bindsym", cmd_bindsym }, { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, - { "exit", cmd_exit }, - { "focus", cmd_focus }, { "include", cmd_include }, { "input", cmd_input }, - { "kill", cmd_kill }, - { "layout", cmd_layout }, { "output", cmd_output }, - { "reload", cmd_reload }, { "seat", cmd_seat }, { "set", cmd_set }, { "workspace", cmd_workspace }, }; +/** + * Commands that can *not* run in the config loading context + * Keep alphabetized + */ +static struct cmd_handler command_handlers[] = { + { "exit", cmd_exit }, + { "focus", cmd_focus }, + { "kill", cmd_kill }, + { "layout", cmd_layout }, + { "reload", cmd_reload }, +}; + static int handler_compare(const void *_a, const void *_b) { const struct cmd_handler *a = _a; const struct cmd_handler *b = _b; @@ -181,20 +191,34 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { struct cmd_handler *res = NULL; wlr_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); + bool config_loading = config->reading || !config->active; + if (block == CMD_BLOCK_INPUT) { - res = bsearch(&d, input_handlers, + // input commands can run in either context + return 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, + // seat commands can run in either context + return 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), - sizeof(struct cmd_handler), handler_compare); } + if (!config_loading) { + res = bsearch(&d, command_handlers, + sizeof(command_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + + if (res) { + return res; + } + } + + res = bsearch(&d, handlers, + sizeof(handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + return res; } From 7262bf655f7a19af1d4c8681be74d70bfc6b8911 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 24 Feb 2018 13:22:57 -0500 Subject: [PATCH 213/522] remove checks for command handlers --- sway/commands/exit.c | 3 --- sway/commands/focus.c | 14 -------------- sway/commands/kill.c | 8 -------- sway/commands/layout.c | 9 --------- sway/commands/reload.c | 3 --- 5 files changed, 37 deletions(-) diff --git a/sway/commands/exit.c b/sway/commands/exit.c index 4bb6a97be..d5353c205 100644 --- a/sway/commands/exit.c +++ b/sway/commands/exit.c @@ -6,9 +6,6 @@ void sway_terminate(int exit_code); struct cmd_results *cmd_exit(int argc, char **argv) { struct cmd_results *error = NULL; - 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; } diff --git a/sway/commands/focus.c b/sway/commands/focus.c index ba47d1e13..f1a8078f7 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -33,20 +33,6 @@ 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_seat *seat = config->handler_context.seat; - - if (!sway_assert(seat, "'focus' command called without seat context")) { - return cmd_results_new(CMD_FAILURE, "focus", - "Command 'focus' called without seat context (this is a bug in sway)"); - } - - if (config->reading) { - return cmd_results_new(CMD_FAILURE, "focus", - "Command 'focus' cannot be used in the config file"); - } - if (con == NULL) { - wlr_log(L_DEBUG, "no container to focus"); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } if (con->type < C_WORKSPACE) { return cmd_results_new(CMD_FAILURE, "focus", "Command 'focus' cannot be used above the workspace level"); diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 4b3666be2..f408ce2a9 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -6,14 +6,6 @@ #include "sway/commands.h" struct cmd_results *cmd_kill(int argc, char **argv) { - if (config->reading) { - return cmd_results_new(CMD_FAILURE, "kill", - "Command 'kill' cannot be used in the config file"); - } - if (config->handler_context.current_container == NULL) { - wlr_log(L_DEBUG, "no container to kill"); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } enum swayc_types type = config->handler_context.current_container->type; if (type != C_VIEW && type != C_CONTAINER) { return cmd_results_new(CMD_INVALID, NULL, diff --git a/sway/commands/layout.c b/sway/commands/layout.c index d953abc8c..b0fc5d664 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -7,19 +7,10 @@ struct cmd_results *cmd_layout(int argc, char **argv) { struct cmd_results *error = NULL; - if (config->reading) { - return cmd_results_new(CMD_FAILURE, "layout", "Can't be used in config file."); - } - if (!config->active) { - return cmd_results_new(CMD_FAILURE, "layout", "Can only be used when sway is running."); - } if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { return error; } swayc_t *parent = config->handler_context.current_container; - if (!sway_assert(parent != NULL, "command called without container context")) { - return NULL; - } // TODO: floating /* diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 419c7de3d..d54d40db6 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -4,9 +4,6 @@ struct cmd_results *cmd_reload(int argc, char **argv) { struct cmd_results *error = NULL; - if (config->reading) { - return cmd_results_new(CMD_FAILURE, "reload", "Can't be used in config file."); - } if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { return error; } From 2154b7c7d623d99e2623f1928f6e77e95255a2d3 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 24 Feb 2018 13:34:47 -0500 Subject: [PATCH 214/522] add config handlers --- sway/commands.c | 19 ++++++++++++++++++- sway/commands/set.c | 1 - 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index ed8da3dcd..b52eb2006 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -138,10 +138,17 @@ static struct cmd_handler handlers[] = { { "input", cmd_input }, { "output", cmd_output }, { "seat", cmd_seat }, - { "set", cmd_set }, { "workspace", cmd_workspace }, }; +/** + * Commands that can *only* run in the config loading context + * Keep alphabetized + */ +static struct cmd_handler config_handlers[] = { + { "set", cmd_set }, +}; + /** * Commands that can *not* run in the config loading context * Keep alphabetized @@ -215,6 +222,16 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { } } + if (config->reading) { + res = bsearch(&d, config_handlers, + sizeof(config_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + + if (res) { + return res; + } + } + res = bsearch(&d, handlers, sizeof(handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); diff --git a/sway/commands/set.c b/sway/commands/set.c index 856c73e79..84e9b792c 100644 --- a/sway/commands/set.c +++ b/sway/commands/set.c @@ -27,7 +27,6 @@ void free_sway_variable(struct sway_variable *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; } From 1cca3965f395f624f698cc162946c6cbd6b10673 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 24 Feb 2018 14:30:47 -0500 Subject: [PATCH 215/522] static bfs queue --- sway/tree/container.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index b56e72e19..fafbdb03c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -17,6 +17,21 @@ #include "sway/workspace.h" #include "log.h" +static list_t *bfs_queue; + +static list_t *get_bfs_queue() { + if (!bfs_queue) { + bfs_queue = create_list(); + if (!bfs_queue) { + wlr_log(L_ERROR, "could not allocate list for bfs queue"); + return NULL; + } + } + bfs_queue->length = 0; + + return bfs_queue; +} + swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { if (!container->children) { @@ -273,7 +288,11 @@ 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) { - list_t *queue = create_list(); + list_t *queue = get_bfs_queue(); + if (!queue) { + return NULL; + } + list_add(queue, parent); swayc_t *swayc = NULL; @@ -313,7 +332,6 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, *sx = view_sx - popup_sx; *sy = view_sy - popup_sy; *surface = popup->surface; - list_free(queue); return swayc; } break; @@ -332,7 +350,6 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, *sx = view_sx - sub_x; *sy = view_sy - sub_y; *surface = subsurface->surface; - list_free(queue); return swayc; } @@ -344,7 +361,6 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, *sx = view_sx; *sy = view_sy; *surface = swayc->sway_view->surface; - list_free(queue); return swayc; } } else { @@ -352,8 +368,6 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, } } - list_free(queue); - return NULL; } @@ -381,7 +395,11 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), void *data) { - list_t *queue = create_list(); + list_t *queue = get_bfs_queue(); + if (!queue) { + return; + } + if (queue == NULL) { wlr_log(L_ERROR, "could not allocate list"); return; @@ -397,8 +415,6 @@ void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), // TODO floating containers list_cat(queue, current->children); } - - list_free(queue); } swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) { From 669f91b991b7bcc4108916f208cd4bbe14169460 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 25 Feb 2018 11:35:31 -0500 Subject: [PATCH 216/522] Document updates to the output command --- sway/sway.5.txt | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/sway/sway.5.txt b/sway/sway.5.txt index afd3c9fad..6c9bce7ad 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -353,35 +353,44 @@ The default colors are: Prevents windows matching from being focused automatically when they're created. This does not apply to the first window in a workspace. -**output** :: - Configures the specified output to use the given resolution. +**output** mode|resolution|res [@[Hz]]:: + Configures the specified output to use the given mode. Modes are a combination + of width and height (in pixels) and a refresh rate that your display can be + configured to use. For a list of available modes, use swaymsg -t get_outputs. + - _Note_: sway does not currently support setting the output mode. Your output's native - resolution will be used and the screen will be scaled from the resolution - specified to your native resolution. + Examples: + + + output HDMI-A-1 mode 1920x1080 + + + output HDMI-A-1 mode 1920x1080@60Hz -**output** :: +**output** position|pos :: Configures the specified output to be arranged at the given position. -**output** :: +**output** scale :: Configures the specified output to be scaled up by the specified integer - scaling factor (usually 2 for HiDPI screens). + scaling factor (usually 2 for HiDPI screens). Fractional scaling is supported. -**output** :: +**output** background|bg :: Sets the wallpaper for the given output to the specified file, using the given scaling mode (one of "stretch", "fill", "fit", "center", "tile"). -**output** solid_color:: +**output** background|bg solid_color:: Sets the background of the given output to the specified color. _color_ should be specified as an _#rrggbb_ (no alpha) color. +**output** transform :: + Sets the background transform to the given value. Can be one of "90", "180", + "270" for rotation; or "flipped", "flipped-90", "flipped-180", "flipped-270" + to apply a rotation and flip, or "normal" to apply no transform. + **output** disable:: Disables the specified output. **NOTES FOR THE OUTPUT COMMAND**:: You may combine output commands into one, like so: + - output HDMI-A-1 res 1920x1080 pos 1920,0 bg ~/wallpaper.png stretch + output HDMI-A-1 mode 1920x1080 pos 1920,0 bg ~/wallpaper.png stretch + You can get a list of output names like so: + From 61c1c3e7afd431de08e037205c4849b5f485ff4f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 25 Feb 2018 12:55:19 -0500 Subject: [PATCH 217/522] Use focus for new windows xwayland/wl_shell --- sway/desktop/wl_shell.c | 9 +++------ sway/desktop/xwayland.c | 7 +++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 0cde6583d..0356aa811 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -131,14 +131,11 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { sway_surface->destroy.notify = handle_destroy; wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); - // TODO: actual focus semantics - swayc_t *parent = root_container.children->items[0]; - parent = parent->children->items[0]; // workspace - - swayc_t *cont = new_view(parent, sway_view); + 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); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); - sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 7603d3ca9..7933f7b2c 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -233,10 +233,9 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { return; } - swayc_t *parent = root_container.children->items[0]; - parent = parent->children->items[0]; // workspace - - swayc_t *cont = new_view(parent, sway_view); + 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); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); From 8ad26c8afd2aed460ea70088b0aa98f65bf21de7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 25 Feb 2018 17:23:36 -0500 Subject: [PATCH 218/522] Send surface enter/leave events --- include/sway/view.h | 2 ++ sway/desktop/xdg_shell_v6.c | 1 + sway/tree/view.c | 42 +++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/include/sway/view.h b/include/sway/view.h index ac33e11a5..b28862113 100644 --- a/include/sway/view.h +++ b/include/sway/view.h @@ -115,4 +115,6 @@ 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/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index b44d9e54f..7371b829a 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -72,6 +72,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_surface, commit); struct sway_view *view = sway_surface->view; // NOTE: We intentionally discard the view's desired width here + // TODO: Store this for restoration when moving to floating plane // TODO: Let floating views do whatever view->width = sway_surface->pending_width; view->height = sway_surface->pending_height; diff --git a/sway/tree/view.c b/sway/tree/view.c index b46c3b172..9499adca7 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,3 +1,7 @@ +#include +#include +#include "sway/container.h" +#include "sway/layout.h" #include "sway/view.h" const char *view_get_title(struct sway_view *view) { @@ -30,13 +34,27 @@ const char *view_get_instance(struct sway_view *view) { void view_set_size(struct sway_view *view, int width, int height) { if (view->iface.set_size) { + struct wlr_box box = { + .x = view->swayc->x, + .y = view->swayc->y, + .width = view->width, + .height = view->height, + }; view->iface.set_size(view, width, height); + view_update_outputs(view, &box); } } void view_set_position(struct sway_view *view, double ox, double oy) { if (view->iface.set_position) { + struct wlr_box box = { + .x = view->swayc->x, + .y = view->swayc->y, + .width = view->width, + .height = view->height, + }; view->iface.set_position(view, ox, oy); + view_update_outputs(view, &box); } } @@ -51,3 +69,27 @@ void view_close(struct sway_view *view) { view->iface.close(view); } } + +void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; + struct wlr_box box = { + .x = view->swayc->x, + .y = view->swayc->y, + .width = view->width, + .height = view->height, + }; + struct wlr_output_layout_output *layout_output; + wl_list_for_each(layout_output, &output_layout->outputs, link) { + bool intersected = before != NULL && wlr_output_layout_intersects( + output_layout, layout_output->output, before); + bool intersects = wlr_output_layout_intersects(output_layout, + layout_output->output, &box); + if (intersected && !intersects) { + wlr_surface_send_leave(view->surface, layout_output->output); + } + if (!intersected && intersects) { + wlr_surface_send_enter(view->surface, layout_output->output); + } + } +} From 94f8bdf08146bae057233386ac2521b095396786 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 25 Feb 2018 17:52:39 -0500 Subject: [PATCH 219/522] Multiple output coords by scale --- sway/desktop/output.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 63420d0cc..2010e76ea 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -37,7 +37,7 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, static void render_surface(struct wlr_surface *surface, struct wlr_output *wlr_output, struct timespec *when, - double lx, double ly, float rotation) { + double ox, double oy, float rotation) { if (!wlr_surface_has_buffer(surface)) { return; } @@ -46,17 +46,16 @@ static void render_surface(struct wlr_surface *surface, int height = surface->current->height; int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; - int owidth, oheight; - wlr_output_effective_resolution(wlr_output, &owidth, &oheight); + ox *= wlr_output->scale; + oy *= wlr_output->scale; - // FIXME: view coords are inconsistently assumed to be in output or layout coords struct wlr_box layout_box = { - .x = lx + wlr_output->lx, .y = ly + wlr_output->ly, + .x = ox + wlr_output->lx, .y = oy + wlr_output->ly, .width = render_width, .height = render_height, }; if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { struct wlr_box render_box = { - .x = lx, .y = ly, + .x = ox, .y = oy, .width = render_width, .height = render_height }; float matrix[16]; @@ -78,8 +77,8 @@ static void render_surface(struct wlr_surface *surface, rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); render_surface(subsurface->surface, wlr_output, when, - lx + sx, - ly + sy, + ox + sx, + oy + sy, rotation); } } From 265378270ac4d4580bcbede59d7ed267ee3c2969 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 25 Feb 2018 17:55:49 -0500 Subject: [PATCH 220/522] Revert "Multiple output coords by scale" This reverts commit 94f8bdf08146bae057233386ac2521b095396786. --- sway/desktop/output.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2010e76ea..63420d0cc 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -37,7 +37,7 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, static void render_surface(struct wlr_surface *surface, struct wlr_output *wlr_output, struct timespec *when, - double ox, double oy, float rotation) { + double lx, double ly, float rotation) { if (!wlr_surface_has_buffer(surface)) { return; } @@ -46,16 +46,17 @@ static void render_surface(struct wlr_surface *surface, int height = surface->current->height; int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; - ox *= wlr_output->scale; - oy *= wlr_output->scale; + int owidth, oheight; + wlr_output_effective_resolution(wlr_output, &owidth, &oheight); + // FIXME: view coords are inconsistently assumed to be in output or layout coords struct wlr_box layout_box = { - .x = ox + wlr_output->lx, .y = oy + wlr_output->ly, + .x = lx + wlr_output->lx, .y = ly + wlr_output->ly, .width = render_width, .height = render_height, }; if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { struct wlr_box render_box = { - .x = ox, .y = oy, + .x = lx, .y = ly, .width = render_width, .height = render_height }; float matrix[16]; @@ -77,8 +78,8 @@ static void render_surface(struct wlr_surface *surface, rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); render_surface(subsurface->surface, wlr_output, when, - ox + sx, - oy + sy, + lx + sx, + ly + sy, rotation); } } From 4b781356a4501ea6fc648f3d3a4abcd061bf51cd Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 26 Feb 2018 19:04:57 -0500 Subject: [PATCH 221/522] Fix wlr_render_with_matrix call This takes an alpha parameter now. --- sway/desktop/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 63420d0cc..08fe58778 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -63,7 +63,7 @@ static void render_surface(struct wlr_surface *surface, wlr_matrix_project_box(&matrix, &render_box, surface->current->transform, 0, &wlr_output->transform_matrix); wlr_render_with_matrix(server.renderer, surface->texture, - &matrix); + &matrix, 1.0f); // TODO: configurable alpha wlr_surface_send_frame_done(surface, when); } From ad879c99e0f41b1003b764cb0fc8512319b0f517 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 26 Feb 2018 17:40:38 -0500 Subject: [PATCH 222/522] ipc show focused container --- sway/ipc-json.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index f0afdc9f6..213c8fb6f 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -5,6 +5,8 @@ #include "sway/ipc-json.h" #include "sway/container.h" #include "sway/output.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include #include @@ -95,11 +97,15 @@ json_object *ipc_json_describe_container(swayc_t *c) { return NULL; } + struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); + bool focused = sway_seat_get_focus(seat) == c; + json_object *object = json_object_new_object(); json_object_object_add(object, "id", json_object_new_int((int)c->id)); json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); json_object_object_add(object, "rect", ipc_json_create_rect(c)); + json_object_object_add(object, "focused", json_object_new_boolean(focused)); switch (c->type) { case C_ROOT: From 3c80498891a831b5cff356fd448efd62c77b031f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Feb 2018 08:25:43 -0500 Subject: [PATCH 223/522] Utilize wlr_xwayland_surface_is_unmanaged --- sway/desktop/xwayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 7933f7b2c..519c050ec 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -226,7 +226,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify); sway_surface->map_notify.notify = handle_map_notify; - if (xsurface->override_redirect) { + if (wlr_xwayland_surface_is_unmanaged(xsurface)) { // these don't get a container in the tree wl_list_insert(&root_container.sway_root->unmanaged_views, &sway_view->unmanaged_view_link); From 02804584e518fdf38e82eacedbe7606a87f004fc Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 27 Feb 2018 19:53:15 -0500 Subject: [PATCH 224/522] ipc new window event --- include/sway/ipc-server.h | 3 ++ sway/ipc-server.c | 90 +++++++++++++++++++++++++++++++++++++++ sway/tree/container.c | 12 ++++-- 3 files changed, 102 insertions(+), 3 deletions(-) diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index b85ff535d..bcf1c4338 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -1,6 +1,7 @@ #ifndef _SWAY_IPC_SERVER_H #define _SWAY_IPC_SERVER_H #include +#include "sway/container.h" #include "ipc.h" struct sway_server; @@ -9,4 +10,6 @@ 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); + #endif diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 4c0953e8a..156de3807 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -240,6 +240,57 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { return 0; } +static void ipc_send_event(const char *json_string, enum ipc_command_type event) { + static struct { + enum ipc_command_type event; + enum ipc_feature feature; + } security_mappings[] = { + { IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE }, + { IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT }, + { IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE }, + { IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW }, + { IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING }, + { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT } + }; + + uint32_t security_mask = 0; + for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) { + if (security_mappings[i].event == event) { + security_mask = security_mappings[i].feature; + break; + } + } + + int i; + struct ipc_client *client; + for (i = 0; i < ipc_client_list->length; i++) { + client = ipc_client_list->items[i]; + if (!(client->security_policy & security_mask)) { + continue; + } + if ((client->subscribed_events & event_mask(event)) == 0) { + continue; + } + client->current_command = event; + if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { + wlr_log_errno(L_INFO, "Unable to send reply to IPC client"); + ipc_client_disconnect(client); + } + } +} + +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)); + json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window)); + + const char *json_string = json_object_to_json_string(obj); + ipc_send_event(json_string, IPC_EVENT_WINDOW); + + json_object_put(obj); // free +} + int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; @@ -361,6 +412,45 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_SUBSCRIBE: + { + // TODO: Check if they're permitted to use these events + struct json_object *request = json_tokener_parse(buf); + if (request == NULL) { + ipc_send_reply(client, "{\"success\": false}", 18); + wlr_log_errno(L_INFO, "Failed to read request"); + goto exit_cleanup; + } + + // parse requested event types + for (size_t i = 0; i < json_object_array_length(request); i++) { + const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); + if (strcmp(event_type, "workspace") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_WORKSPACE); + } else if (strcmp(event_type, "barconfig_update") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); + } else if (strcmp(event_type, "mode") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_MODE); + } else if (strcmp(event_type, "window") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_WINDOW); + } else if (strcmp(event_type, "modifier") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER); + } else if (strcmp(event_type, "binding") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_BINDING); + } else { + ipc_send_reply(client, "{\"success\": false}", 18); + json_object_put(request); + wlr_log_errno(L_INFO, "Failed to parse request"); + goto exit_cleanup; + } + } + + json_object_put(request); + + ipc_send_reply(client, "{\"success\": true}", 17); + goto exit_cleanup; + } + case IPC_GET_INPUTS: { json_object *inputs = json_object_new_array(); diff --git a/sway/tree/container.c b/sway/tree/container.c index fafbdb03c..b424dd0af 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -15,6 +15,7 @@ #include "sway/server.h" #include "sway/view.h" #include "sway/workspace.h" +#include "sway/ipc-server.h" #include "log.h" static list_t *bfs_queue; @@ -32,6 +33,11 @@ static list_t *get_bfs_queue() { return bfs_queue; } +static void notify_new_container(swayc_t *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) { @@ -175,7 +181,7 @@ swayc_t *new_output(struct sway_output *sway_output) { } free(ws_name); - wl_signal_emit(&root_container.sway_root->events.new_container, output); + notify_new_container(output); return output; } @@ -197,7 +203,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { add_child(output, workspace); sort_workspaces(output); - wl_signal_emit(&root_container.sway_root->events.new_container, workspace); + notify_new_container(workspace); return workspace; } @@ -222,7 +228,7 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { // Regular case, create as sibling of current container add_sibling(sibling, swayc); } - wl_signal_emit(&root_container.sway_root->events.new_container, swayc); + notify_new_container(swayc); return swayc; } From 95963e4a1fa714858e3ff640945f015a8ba4795d Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sat, 3 Mar 2018 16:36:05 +0100 Subject: [PATCH 225/522] xwayland: do not send surface configure when no width/height The code in apply_horiz_layout systematically does `set_position` then `set_size`, so for new windows there is an invalid call. For old windows there are two calls when only one is needed, with the current code set_position could not send any surface configure without impact, but in the future it might be needed? Native wayland surfaces do not need to know where they are (the set_position handled only updates the sway internal view variable), why does X11 window need that? --- sway/desktop/xwayland.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 519c050ec..6b5e03f9c 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -67,6 +67,10 @@ static void set_position(struct sway_view *view, double ox, double oy) { view->swayc->x = ox; view->swayc->y = oy; + if (view->width == 0 || view->height == 0) { + return; + } + wlr_xwayland_surface_configure(view->wlr_xwayland_surface, ox + loutput->x, oy + loutput->y, view->width, view->height); From 659ee8639430b77da6d00f518494b9c86c2745ff Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 4 Mar 2018 16:37:48 -0500 Subject: [PATCH 226/522] Drop Travis in favor of builds.sr.ht --- .travis.yml | 35 ----------------------------------- README.de.md | 2 +- README.el.md | 2 +- README.fr.md | 2 +- README.it.md | 2 +- README.ja.md | 2 +- README.md | 2 +- README.pt.md | 2 +- README.ru.md | 2 +- README.uk.md | 2 +- 10 files changed, 9 insertions(+), 44 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index db7177188..000000000 --- a/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -sudo: required - -language: c - -compiler: - - gcc - - clang - -env: - - BUILD_TYPE=release - - BUILD_TYPE=debug - -arch: - packages: - - meson - - ninja - - xorg-server-xwayland - - json-c - - wayland - - wayland-protocols - - xcb-util-image - - pango - - cairo - - gdk-pixbuf2 - - libcap - - libinput - - libxkbcommon - script: - - git clone https://github.com/swaywm/wlroots - - 'cd wlroots && meson --prefix=/usr build && ninja -C build && sudo ninja -C build install' - - meson build --buildtype=$BUILD_TYPE - - ninja -C build - -script: - - "curl -s https://raw.githubusercontent.com/mikkeloscar/arch-travis/master/arch-travis.sh | bash" diff --git a/README.de.md b/README.de.md index 47084ad34..dbef4ee6a 100644 --- a/README.de.md +++ b/README.de.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Mit fosspay spenden](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway Der Fortschritt dieser Übersetzung kann [hier](https://github.com/swaywm/sway/issues/1318) eingesehen werden. diff --git a/README.el.md b/README.el.md index dd1889e43..8d8f0f3ea 100644 --- a/README.el.md +++ b/README.el.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway "Ο Sway (**S**irCmpwn's **Way**land) είναι ένας **υπό ανάπτυξη** [Wayland](http://wayland.freedesktop.org/) διαχειριστής παραθύρων συμβατός με τον αντίστοιχο διαχειριστή παραθύρων i3 για τον X11. Διαβάστε τις [Συνήθεις Ερωτήσεις](https://github.com/swaywm/sway/wiki). Συνδεθείτε στο [κανάλι μας στο IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway στο diff --git a/README.fr.md b/README.fr.md index 5baee7a8e..1ffcd4786 100644 --- a/README.fr.md +++ b/README.fr.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway "**S**irCmpwn's **Way**land compositor" est un compositeur [Wayland](http://wayland.freedesktop.org/) compatible avec i3, **en cours de développement**. diff --git a/README.it.md b/README.it.md index af3444050..ef5b81a72 100644 --- a/README.it.md +++ b/README.it.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway "**S**irCmpwn's **Way**land compositor" è un compositor [Wayland](http://wayland.freedesktop.org/) **in via di sviluppo** diff --git a/README.ja.md b/README.ja.md index cf89971cd..aa4208148 100644 --- a/README.ja.md +++ b/README.ja.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway "**S**irCmpwn's **Way**land compositor"は**開発中**の i3互換な[Wayland](http://wayland.freedesktop.org/)コンポジタです。 diff --git a/README.md b/README.md index cfe513462..ae12ea894 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway [**English**](https://github.com/swaywm/sway/blob/master/README.md#sway--) - [日本語](https://github.com/swaywm/sway/blob/master/README.ja.md#sway--) - [Deutsch](https://github.com/swaywm/sway/blob/master/README.de.md#sway--) - [Ελληνικά](https://github.com/swaywm/sway/blob/master/README.el.md#sway--) - [Français](https://github.com/swaywm/sway/blob/master/README.fr.md#sway--) - [Українська](https://github.com/swaywm/sway/blob/master/README.uk.md#sway--) - [Italiano](https://github.com/swaywm/sway/blob/master/README.it.md#sway--) - [Português](https://github.com/swaywm/sway/blob/master/README.pt.md#sway--) - [Русский](https://github.com/swaywm/sway/blob/master/README.ru.md#sway--) diff --git a/README.pt.md b/README.pt.md index ff51ac2c1..69c9538a3 100644 --- a/README.pt.md +++ b/README.pt.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Doe através do fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway "**S**irCmpwn's **Way**land compositor" é um compositor [Wayland](http://wayland.freedesktop.org/) compatível com o i3. Leia o [FAQ](https://github.com/swaywm/sway/wiki). Participe do diff --git a/README.ru.md b/README.ru.md index 12890d2d0..e1580c81a 100644 --- a/README.ru.md +++ b/README.ru.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Пожертвовать через fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway "**S**irCmpwn's **Way**land compositor" на данный момент **(в разработке)** i3-совместимый [Wayland](http://wayland.freedesktop.org/) композитор. diff --git a/README.uk.md b/README.uk.md index 37a33e4cf..71b354708 100644 --- a/README.uk.md +++ b/README.uk.md @@ -1,4 +1,4 @@ -# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) +# sway **Sway** ("**S**irCmpwn's **Way**land compositor") це сумісний з i3 композитор [Wayland](http://wayland.freedesktop.org/) (**у стані розробки**). From 4ab55060644a9c7f01e8f257b7dd34067adfaaf8 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 12 Mar 2018 13:48:42 +0100 Subject: [PATCH 227/522] ipc: add output modes --- sway/ipc-json.c | 14 ++++++++++++++ swaymsg/main.c | 26 ++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 213c8fb6f..977f1ecbc 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -78,6 +78,20 @@ static void ipc_json_describe_output(swayc_t *container, json_object *object) { json_object_new_string(ipc_json_get_output_transform(wlr_output->transform))); // TODO WLR need to set "current_workspace" to the currently focused // workspace in a way that makes sense with multiseat + + json_object *modes_array = json_object_new_array(); + struct wlr_output_mode *mode; + wl_list_for_each(mode, &wlr_output->modes, link) { + json_object *mode_object = json_object_new_object(); + json_object_object_add(mode_object, "width", + json_object_new_int(mode->width)); + json_object_object_add(mode_object, "height", + json_object_new_int(mode->height)); + json_object_object_add(mode_object, "refresh", + json_object_new_int(mode->refresh)); + json_object_array_add(modes_array, mode_object); + } + json_object_object_add(object, "modes", modes_array); } static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { diff --git a/swaymsg/main.c b/swaymsg/main.c index 88b14813e..c9be3a864 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -125,13 +125,16 @@ static void pretty_print_output(json_object *o) { json_object_object_get_ex(rect, "y", &y); json_object_object_get_ex(rect, "width", &width); json_object_object_get_ex(rect, "height", &height); + json_object *modes; + json_object_object_get_ex(o, "modes", &modes); + printf( "Output %s '%s %s %s'%s%s\n" - " Mode: %dx%d @ %f Hz\n" + " Current mode: %dx%d @ %f Hz\n" " Position: %d,%d\n" " Scale factor: %dx\n" " Transform: %s\n" - " Workspace: %s\n\n", + " Workspace: %s\n", json_object_get_string(name), json_object_get_string(make), json_object_get_string(model), @@ -145,6 +148,25 @@ static void pretty_print_output(json_object *o) { json_object_get_string(transform), json_object_get_string(ws) ); + + size_t modes_len = json_object_array_length(modes); + if (modes_len > 0) { + printf(" Available modes:\n"); + for (size_t i = 0; i < modes_len; ++i) { + json_object *mode = json_object_array_get_idx(modes, i); + + json_object *mode_width, *mode_height, *mode_refresh; + json_object_object_get_ex(mode, "width", &mode_width); + json_object_object_get_ex(mode, "height", &mode_height); + json_object_object_get_ex(mode, "refresh", &mode_refresh); + + printf(" %dx%d @ %f Hz\n", json_object_get_int(mode_width), + json_object_get_int(mode_height), + (float)json_object_get_int(mode_refresh) / 1000); + } + } + + printf("\n"); } static void pretty_print_version(json_object *v) { From bb173672ae1677967ebbe39facb432d06dccd884 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 12 Mar 2018 12:21:46 +0100 Subject: [PATCH 228/522] meson: allow wlroots to be a subproject --- .gitignore | 1 + meson.build | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b6e56f7ab..f48e22e57 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ build/ .lvimrc config-debug wayland-*-protocol.* +/subprojects/wlroots diff --git a/meson.build b/meson.build index fc995c815..f27ac451b 100644 --- a/meson.build +++ b/meson.build @@ -21,7 +21,7 @@ prefix = get_option('prefix') jsonc = dependency('json-c', version: '>=0.13') pcre = dependency('libpcre') -wlroots = dependency('wlroots') +wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots']) wayland_server = dependency('wayland-server') wayland_client = dependency('wayland-client') wayland_egl = dependency('wayland-egl') From 1004915796cf6d416124c6b3e92317b15d0c1424 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 15 Mar 2018 21:22:34 +0100 Subject: [PATCH 229/522] Update rendering code for wlroots matrix redesign --- sway/desktop/output.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 08fe58778..247c279ff 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -3,19 +3,19 @@ #include #include #include +#include +#include #include #include #include -#include -#include #include "log.h" #include "sway/container.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/layout.h" #include "sway/output.h" #include "sway/server.h" #include "sway/view.h" -#include "sway/input/input-manager.h" -#include "sway/input/seat.h" /** * Rotate a child's position relative to a parent. The parent size is (pw, ph), @@ -59,11 +59,11 @@ static void render_surface(struct wlr_surface *surface, .x = lx, .y = ly, .width = render_width, .height = render_height }; - float matrix[16]; - wlr_matrix_project_box(&matrix, &render_box, - surface->current->transform, 0, &wlr_output->transform_matrix); - wlr_render_with_matrix(server.renderer, surface->texture, - &matrix, 1.0f); // TODO: configurable alpha + float matrix[9]; + wlr_matrix_project_box(matrix, &render_box, surface->current->transform, + 0, wlr_output->transform_matrix); + wlr_render_texture_with_matrix(server.renderer, surface->texture, + matrix, 1.0f); // TODO: configurable alpha wlr_surface_send_frame_done(surface, when); } @@ -183,7 +183,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct sway_server *server = soutput->server; float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); - wlr_renderer_clear(renderer, &clear_color); + wlr_renderer_clear(renderer, clear_color); int buffer_age = -1; wlr_output_make_current(wlr_output, &buffer_age); From 01beee58263a3d1de6eb30951332f31ca46eb4d3 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 19 Mar 2018 23:31:18 +0100 Subject: [PATCH 230/522] Update wlroots API Breaking changes in wlr_xdg_shell_v6 and wlr_renderer have been made upstream. --- include/sway/server.h | 2 +- sway/desktop/output.c | 6 +++--- sway/server.c | 2 +- sway/tree/container.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index 3fcdb1baf..eb7fa2ffd 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include // TODO WLR: make Xwayland optional #include diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 247c279ff..96635db46 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -152,8 +152,8 @@ static void output_frame_view(swayc_t *view, void *data) { switch (sway_view->type) { case SWAY_XDG_SHELL_V6_VIEW: { - int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x; - int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y; + int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; + int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; render_surface(surface, wlr_output, &output->last_frame, view->x - window_offset_x, view->y - window_offset_y, diff --git a/sway/server.c b/sway/server.c index 495769ee7..ca08d7fb0 100644 --- a/sway/server.c +++ b/sway/server.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sway/tree/container.c b/sway/tree/container.c index b424dd0af..705221d7f 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -325,8 +325,8 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly, case SWAY_XDG_SHELL_V6_VIEW: // the top left corner of the sway container is the // coordinate of the top left corner of the window geometry - view_sx += sview->wlr_xdg_surface_v6->geometry->x; - view_sy += sview->wlr_xdg_surface_v6->geometry->y; + view_sx += sview->wlr_xdg_surface_v6->geometry.x; + view_sy += sview->wlr_xdg_surface_v6->geometry.y; // check for popups double popup_sx, popup_sy; From cbb2e3308e66c2e5b1852c7475e3f40a5bbdca1c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 13:28:43 -0400 Subject: [PATCH 231/522] Update API to match latest wlroots --- sway/desktop/output.c | 2 +- sway/desktop/xdg_shell_v6.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 96635db46..6c990c473 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -187,7 +187,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { int buffer_age = -1; wlr_output_make_current(wlr_output, &buffer_age); - wlr_renderer_begin(server->renderer, wlr_output); + wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); struct sway_seat *seat = input_manager_current_seat(input_manager); swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 7371b829a..7b550b307 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -63,7 +63,7 @@ static void close(struct sway_view *view) { } 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); + wlr_xdg_surface_v6_send_close(surface); } } From 53df5889d511dbcc8c05cfa5837da0f1ef30fd4b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 15:54:34 -0400 Subject: [PATCH 232/522] Fix lingering xdg shell issues --- sway/desktop/xdg_shell_v6.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 7b550b307..7bc171499 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -22,9 +22,9 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } switch (prop) { case VIEW_PROP_TITLE: - return view->wlr_xdg_surface_v6->title; + return view->wlr_xdg_surface_v6->toplevel->title; case VIEW_PROP_APP_ID: - return view->wlr_xdg_surface_v6->app_id; + return view->wlr_xdg_surface_v6->toplevel->app_id; default: return NULL; } @@ -100,7 +100,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { } wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", - xdg_surface->title, xdg_surface->app_id); + xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); wlr_xdg_surface_v6_ping(xdg_surface); struct sway_xdg_surface_v6 *sway_surface = From 5cbb2c4879675ad198fb82de9e2e3789f8744818 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 16:13:38 -0400 Subject: [PATCH 233/522] Move .build.yml repo references to github.com --- .build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.build.yml b/.build.yml index a2f855e94..8ed621a25 100644 --- a/.build.yml +++ b/.build.yml @@ -14,8 +14,8 @@ packages: - libinput - libxkbcommon sources: - - https://git.sr.ht/~sircmpwn/sway - - https://git.sr.ht/~sircmpwn/wlroots + - https://github.com/~sircmpwn/sway + - https://github.com/~sircmpwn/wlroots tasks: - wlroots: | cd wlroots From cf4db5141f939f6e55a1a8435e73452ca1868b84 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 16:16:25 -0400 Subject: [PATCH 234/522] Fix broken repo references --- .build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.build.yml b/.build.yml index 8ed621a25..40be2300f 100644 --- a/.build.yml +++ b/.build.yml @@ -14,8 +14,8 @@ packages: - libinput - libxkbcommon sources: - - https://github.com/~sircmpwn/sway - - https://github.com/~sircmpwn/wlroots + - https://github.com/swaywm/sway + - https://github.com/swaywm/wlroots tasks: - wlroots: | cd wlroots From 07616c7c247bff0b776c8040718ea143a5c8485f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 12:22:28 -0400 Subject: [PATCH 235/522] Add subprojects to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f48e22e57..1352970b9 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ build/ config-debug wayland-*-protocol.* /subprojects/wlroots +subprojects From 1e604f3e3583fb1d2a4971c8bf47b842596f20ed Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 12:22:45 -0400 Subject: [PATCH 236/522] Update input events per swaywm/wlroots#765 --- sway/input/cursor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 73a8ec5ce..8a0d1df59 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -74,8 +74,7 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, struct sway_cursor *cursor = wl_container_of(listener, cursor, motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; - wlr_cursor_warp_absolute(cursor->cursor, event->device, - event->x_mm / event->width_mm, event->y_mm / event->height_mm); + wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); cursor_update_position(cursor); cursor_send_pointer_motion(cursor, event->time_msec); } From eccf0b25987b2b194031edf3415e9f09a7ad7119 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 13:35:34 -0400 Subject: [PATCH 237/522] Add client protocols and swaybg skeleton --- meson.build | 2 + protocols/meson.build | 49 ++++ protocols/wlr-layer-shell-unstable-v1.xml | 281 ++++++++++++++++++++++ swaybg/main.c | 189 +-------------- swaybg/meson.build | 8 + 5 files changed, 347 insertions(+), 182 deletions(-) create mode 100644 protocols/meson.build create mode 100644 protocols/wlr-layer-shell-unstable-v1.xml create mode 100644 swaybg/meson.build diff --git a/meson.build b/meson.build index f27ac451b..622769a35 100644 --- a/meson.build +++ b/meson.build @@ -85,9 +85,11 @@ add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') sway_inc = include_directories('include') +subdir('protocols') subdir('common') subdir('sway') subdir('swaymsg') +subdir('swaybg') config = configuration_data() config.set('sysconfdir', join_paths(prefix, sysconfdir)) diff --git a/protocols/meson.build b/protocols/meson.build new file mode 100644 index 000000000..73a6fda50 --- /dev/null +++ b/protocols/meson.build @@ -0,0 +1,49 @@ +wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') + +wayland_scanner = find_program('wayland-scanner') + +wayland_scanner_server = generator( + wayland_scanner, + output: '@BASENAME@-protocol.h', + arguments: ['server-header', '@INPUT@', '@OUTPUT@'], +) + +wayland_scanner_code = generator( + wayland_scanner, + output: '@BASENAME@-protocol.c', + arguments: ['code', '@INPUT@', '@OUTPUT@'], +) + +wayland_scanner_client = generator( + wayland_scanner, + output: '@BASENAME@-client-protocol.h', + arguments: ['client-header', '@INPUT@', '@OUTPUT@'], +) + +protocols = [] + +client_protocols = [ + 'wlr-layer-shell-unstable-v1.xml', +] + +wl_protos_src = [] +wl_protos_headers = [] + +foreach p : protocols + xml = join_paths(p) + wl_protos_src += wayland_scanner_code.process(xml) + wl_protos_headers += wayland_scanner_server.process(xml) +endforeach + +foreach p : client_protocols + xml = join_paths(p) + wl_protos_headers += wayland_scanner_client.process(xml) +endforeach + +lib_wl_protos = static_library('wl_protos', wl_protos_src + wl_protos_headers, + dependencies: [wayland_client]) # for the include directory + +sway_protos = declare_dependency( + link_with: lib_wl_protos, + sources: wl_protos_headers, +) diff --git a/protocols/wlr-layer-shell-unstable-v1.xml b/protocols/wlr-layer-shell-unstable-v1.xml new file mode 100644 index 000000000..3181c0bbf --- /dev/null +++ b/protocols/wlr-layer-shell-unstable-v1.xml @@ -0,0 +1,281 @@ + + + + Copyright © 2017 Drew DeVault + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + Clients can use this interface to assign the surface_layer role to + wl_surfaces. Such surfaces are assigned to a "layer" of the output and + rendered with a defined z-depth respective to each other. They may also be + anchored to the edges and corners of a screen and specify input handling + semantics. This interface should be suitable for the implementation of + many desktop shell components, and a broad number of other applications + that interact with the desktop. + + + + + Create a layer surface for an existing surface. This assigns the role of + layer_surface, or raises a protocol error if another role is already + assigned. + + Creating a layer surface from a wl_surface which has a buffer attached + or committed is a client error, and any attempts by a client to attach + or manipulate a buffer prior to the first layer_surface.configure call + must also be treated as errors. + + Clients can specify a namespace that defines the purpose of the layer + surface. + + + + + + + + + + + + + + + + + These values indicate which layers a surface can be rendered in. They + are ordered by z depth, bottom-most first. Traditional shell surfaces + will typically be rendered between the bottom and top layers. + Fullscreen shell surfaces are typically rendered at the top layer. + Multiple surfaces can share a single layer, and ordering within a + single layer is undefined. + + + + + + + + + + + + An interface that may be implemented by a wl_surface, for surfaces that + are designed to be rendered as a layer of a stacked desktop-like + environment. + + Layer surface state (size, anchor, exclusive zone, margin, interactivity) + is double-buffered, and will be applied at the time wl_surface.commit of + the corresponding wl_surface is called. + + + + + Sets the size of the surface in surface-local coordinates. The + compositor will display the surface centered with respect to its + anchors. + + If you pass 0 for either value, the compositor will assign it and + inform you of the assignment in the configure event. You must set your + anchor to opposite edges in the dimensions you omit; not doing so is a + protocol error. Both values are 0 by default. + + Size is double-buffered, see wl_surface.commit. + + + + + + + + Requests that the compositor anchor the surface to the specified edges + and corners. If two orthoginal edges are specified (e.g. 'top' and + 'left'), then the anchor point will be the intersection of the edges + (e.g. the top left corner of the output); otherwise the anchor point + will be centered on that edge, or in the center if none is specified. + + Anchor is double-buffered, see wl_surface.commit. + + + + + + + Requests that the compositor avoids occluding an area of the surface + with other surfaces. The compositor's use of this information is + implementation-dependent - do not assume that this region will not + actually be occluded. + + A positive value is only meaningful if the surface is anchored to an + edge, rather than a corner. The zone is the number of surface-local + coordinates from the edge that are considered exclusive. + + Surfaces that do not wish to have an exclusive zone may instead specify + how they should interact with surfaces that do. If set to zero, the + surface indicates that it would like to be moved to avoid occluding + surfaces with a positive excluzive zone. If set to -1, the surface + indicates that it would not like to be moved to accomodate for other + surfaces, and the compositor should extend it all the way to the edges + it is anchored to. + + For example, a panel might set its exclusive zone to 10, so that + maximized shell surfaces are not shown on top of it. A notification + might set its exclusive zone to 0, so that it is moved to avoid + occluding the panel, but shell surfaces are shown underneath it. A + wallpaper or lock screen might set their exclusive zone to -1, so that + they stretch below or over the panel. + + The default value is 0. + + Exclusive zone is double-buffered, see wl_surface.commit. + + + + + + + Requests that the surface be placed some distance away from the anchor + point on the output, in surface-local coordinates. Setting this value + for edges you are not anchored to has no effect. + + The exclusive zone includes the margin. + + Margin is double-buffered, see wl_surface.commit. + + + + + + + + + + Set to 1 to request that the seat send keyboard events to this layer + surface. For layers below the shell surface layer, the seat will use + normal focus semantics. For layers above the shell surface layers, the + seat will always give exclusive keyboard focus to the top-most layer + which has keyboard interactivity set to true. + + Layer surfaces receive pointer, touch, and tablet events normally. If + you do not want to receive them, set the input region on your surface + to an empty region. + + Events is double-buffered, see wl_surface.commit. + + + + + + + This assigns an xdg_popup's parent to this layer_surface. This popup + should have been created via xdg_surface::get_popup with the parent set + to NULL, and this request must be invoked before committing the popup's + initial state. + + See the documentation of xdg_popup for more details about what an + xdg_popup is and how it is used. + + + + + + + When a configure event is received, if a client commits the + surface in response to the configure event, then the client + must make an ack_configure request sometime before the commit + request, passing along the serial of the configure event. + + If the client receives multiple configure events before it + can respond to one, it only has to ack the last configure event. + + A client is not required to commit immediately after sending + an ack_configure request - it may even ack_configure several times + before its next surface commit. + + A client may send multiple ack_configure requests before committing, but + only the last request sent before a commit indicates which configure + event the client really is responding to. + + + + + + + This request destroys the layer surface. + + + + + + The configure event asks the client to resize its surface. + + Clients should arrange their surface for the new states, and then send + an ack_configure request with the serial sent in this configure event at + some point before committing the new surface. + + The client is free to dismiss all but the last configure event it + received. + + The width and height arguments specify the size of the window in + surface-local coordinates. + + The size is a hint, in the sense that the client is free to ignore it if + it doesn't resize, pick a smaller size (to satisfy aspect ratio or + resize in steps of NxM pixels). If the client picks a smaller size and + is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the + surface will be centered on this axis. + + If the width or height arguments are zero, it means the client should + decide its own window dimension. + + + + + + + + + The closed event is sent by the compositor when the surface will no + longer be shown. The output may have been destroyed or the user may + have asked for it to be removed. Further changes to the surface will be + ignored. The client should destroy the resource after receiving this + event, and create a new surface if they so choose. + + + + + + + + + + + + + + + + + diff --git a/swaybg/main.c b/swaybg/main.c index 2fdd4220b..94e982282 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -1,20 +1,11 @@ -#include "wayland-desktop-shell-client-protocol.h" +#include #include #include #include -#include -#include -#include #include -#include "client/window.h" -#include "client/registry.h" -#include "client/cairo.h" -#include "log.h" -#include "list.h" -#include "util.h" - -list_t *surfaces; -struct registry *registry; +#include +#include +#include enum scaling_mode { SCALING_MODE_STRETCH, @@ -24,21 +15,11 @@ enum scaling_mode { SCALING_MODE_TILE, }; -void sway_terminate(int exit_code) { - int i; - for (i = 0; i < surfaces->length; ++i) { - struct window *window = surfaces->items[i]; - window_teardown(window); - } - list_free(surfaces); - registry_teardown(registry); - exit(exit_code); -} - bool is_valid_color(const char *color) { int len = strlen(color); if (len != 7 || color[0] != '#') { - sway_log(L_ERROR, "%s is not a valid color for swaybg. Color should be specified as #rrggbb (no alpha).", color); + wlr_log(L_ERROR, "%s is not a valid color for swaybg. " + "Color should be specified as #rrggbb (no alpha).", color); return false; } @@ -53,162 +34,6 @@ bool is_valid_color(const char *color) { } int main(int argc, const char **argv) { - init_log(L_INFO); - surfaces = create_list(); - registry = registry_poll(); - - if (argc != 4) { - sway_abort("Do not run this program manually. See man 5 sway and look for output options."); - } - - if (!registry->desktop_shell) { - sway_abort("swaybg requires the compositor to support the desktop-shell extension."); - } - - int desired_output = atoi(argv[1]); - sway_log(L_INFO, "Using output %d of %d", desired_output, registry->outputs->length); - int i; - struct output_state *output = registry->outputs->items[desired_output]; - struct window *window = window_setup(registry, - output->width, output->height, output->scale, false); - if (!window) { - sway_abort("Failed to create surfaces."); - } - desktop_shell_set_background(registry->desktop_shell, output->output, window->surface); - window_make_shell(window); - list_add(surfaces, window); - - if (strcmp(argv[3], "solid_color") == 0 && is_valid_color(argv[2])) { - cairo_set_source_u32(window->cairo, parse_color(argv[2])); - cairo_paint(window->cairo); - window_render(window); - } else { -#ifdef WITH_GDK_PIXBUF - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(argv[2], &err); - if (!pixbuf) { - sway_abort("Failed to load background image."); - } - cairo_surface_t *image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - cairo_surface_t *image = cairo_image_surface_create_from_png(argv[2]); -#endif //WITH_GDK_PIXBUF - if (!image) { - sway_abort("Failed to read background image."); - } - if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { - sway_abort("Failed to read background image: %s." -#ifndef WITH_GDK_PIXBUF - "\nSway was compiled without gdk_pixbuf support, so only" - "\nPNG images can be loaded. This is the likely cause." -#endif //WITH_GDK_PIXBUF - , cairo_status_to_string(cairo_surface_status(image))); - } - double width = cairo_image_surface_get_width(image); - double height = cairo_image_surface_get_height(image); - - const char *scaling_mode_str = argv[3]; - enum scaling_mode scaling_mode = SCALING_MODE_STRETCH; - if (strcmp(scaling_mode_str, "stretch") == 0) { - scaling_mode = SCALING_MODE_STRETCH; - } else if (strcmp(scaling_mode_str, "fill") == 0) { - scaling_mode = SCALING_MODE_FILL; - } else if (strcmp(scaling_mode_str, "fit") == 0) { - scaling_mode = SCALING_MODE_FIT; - } else if (strcmp(scaling_mode_str, "center") == 0) { - scaling_mode = SCALING_MODE_CENTER; - } else if (strcmp(scaling_mode_str, "tile") == 0) { - scaling_mode = SCALING_MODE_TILE; - } else { - sway_abort("Unsupported scaling mode: %s", scaling_mode_str); - } - - int wwidth = window->width * window->scale; - int wheight = window->height * window->scale; - - for (i = 0; i < surfaces->length; ++i) { - struct window *window = surfaces->items[i]; - if (window_prerender(window) && window->cairo) { - switch (scaling_mode) { - case SCALING_MODE_STRETCH: - cairo_scale(window->cairo, - (double) wwidth / width, - (double) wheight / height); - cairo_set_source_surface(window->cairo, image, 0, 0); - break; - case SCALING_MODE_FILL: - { - double window_ratio = (double) wwidth / wheight; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double) wwidth / width; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - 0, - (double) wheight/2 / scale - height/2); - } else { - double scale = (double) wheight / height; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 / scale - width/2, - 0); - } - break; - } - case SCALING_MODE_FIT: - { - double window_ratio = (double) wwidth / wheight; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double) wheight / height; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 / scale - width/2, - 0); - } else { - double scale = (double) wwidth / width; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - 0, - (double) wheight/2 / scale - height/2); - } - break; - } - case SCALING_MODE_CENTER: - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 - width/2, - (double) wheight/2 - height/2); - break; - case SCALING_MODE_TILE: - { - cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - cairo_set_source(window->cairo, pattern); - break; - } - default: - sway_abort("Scaling mode '%s' not implemented yet!", scaling_mode_str); - } - - cairo_paint(window->cairo); - - window_render(window); - } - } - - cairo_surface_destroy(image); - } - - while (wl_display_dispatch(registry->display) != -1); - - for (i = 0; i < surfaces->length; ++i) { - struct window *window = surfaces->items[i]; - window_teardown(window); - } - list_free(surfaces); - registry_teardown(registry); + wlr_log_init(L_DEBUG, NULL); return 0; } diff --git a/swaybg/meson.build b/swaybg/meson.build new file mode 100644 index 000000000..473150239 --- /dev/null +++ b/swaybg/meson.build @@ -0,0 +1,8 @@ +executable( + 'swaybg', + 'main.c', + include_directories: [sway_inc], + dependencies: [wayland_client, sway_protos, jsonc, wlroots], + link_with: [lib_sway_common], + install: true +) From 632bb948b7ffbb08a6e965dabf88347afd0a1fa8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 15:25:25 -0400 Subject: [PATCH 238/522] Add solid-color rendering to swaybg --- client/buffer-pool.c | 123 +++++++++++++++++++++++++++ client/meson.build | 21 +++++ common/cairo.c | 127 ++++++++++++++++++++++++++++ common/meson.build | 21 +++-- include/buffer_pool.h | 21 +++++ include/cairo.h | 18 ++++ meson.build | 8 ++ protocols/meson.build | 18 +--- swaybg/main.c | 187 ++++++++++++++++++++++++++++++++++++++++++ swaybg/meson.build | 18 +++- wayland/buffers.c | 27 +++--- 11 files changed, 550 insertions(+), 39 deletions(-) create mode 100644 client/buffer-pool.c create mode 100644 client/meson.build create mode 100644 common/cairo.c create mode 100644 include/buffer_pool.h create mode 100644 include/cairo.h diff --git a/client/buffer-pool.c b/client/buffer-pool.c new file mode 100644 index 000000000..26d0f7e51 --- /dev/null +++ b/client/buffer-pool.c @@ -0,0 +1,123 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "buffer_pool.h" + +static int create_pool_file(size_t size, char **name) { + static const char template[] = "sway-client-XXXXXX"; + const char *path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + return -1; + } + + int ts = (path[strlen(path) - 1] == '/'); + + *name = malloc( + strlen(template) + + strlen(path) + + (ts ? 0 : 1) + 1); + sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); + + int fd = mkstemp(*name); + + if (fd < 0) { + return -1; + } + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +static void buffer_release(void *data, struct wl_buffer *wl_buffer) { + struct pool_buffer *buffer = data; + buffer->busy = false; +} + +static const struct wl_buffer_listener buffer_listener = { + .release = buffer_release +}; + +static struct pool_buffer *create_buffer(struct wl_shm *shm, + struct pool_buffer *buf, int32_t width, int32_t height, + uint32_t format) { + uint32_t stride = width * 4; + uint32_t size = stride * height; + + char *name; + int fd = create_pool_file(size, &name); + assert(fd); + void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); + buf->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, stride, format); + wl_shm_pool_destroy(pool); + close(fd); + unlink(name); + free(name); + fd = -1; + + buf->width = width; + buf->height = height; + buf->surface = cairo_image_surface_create_for_data(data, + CAIRO_FORMAT_ARGB32, width, height, stride); + buf->cairo = cairo_create(buf->surface); + buf->pango = pango_cairo_create_context(buf->cairo); + + wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); + return buf; +} + +static void destroy_buffer(struct pool_buffer *buffer) { + if (buffer->buffer) { + wl_buffer_destroy(buffer->buffer); + } + if (buffer->cairo) { + cairo_destroy(buffer->cairo); + } + if (buffer->surface) { + cairo_surface_destroy(buffer->surface); + } + if (buffer->pango) { + g_object_unref(buffer->pango); + } + memset(buffer, 0, sizeof(struct pool_buffer)); +} + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { + struct pool_buffer *buffer = NULL; + + for (size_t i = 0; i < 2; ++i) { + if (pool[i].busy) { + continue; + } + buffer = &pool[i]; + } + + if (!buffer) { + return NULL; + } + + if (buffer->width != width || buffer->height != height) { + destroy_buffer(buffer); + } + + if (!buffer->buffer) { + if (!create_buffer(shm, buffer, width, height, + WL_SHM_FORMAT_ARGB8888)) { + return NULL; + } + } + return buffer; +} diff --git a/client/meson.build b/client/meson.build new file mode 100644 index 000000000..597899ce2 --- /dev/null +++ b/client/meson.build @@ -0,0 +1,21 @@ +deps = [ + cairo, + pango, + pangocairo, + wlroots, + wayland_client, +] + +if gdk_pixbuf.found() + deps += [gdk_pixbuf] +endif + +lib_sway_client = static_library( + 'sway-client', + files( + 'buffer-pool.c', + ), + dependencies: deps, + link_with: [lib_sway_common], + include_directories: sway_inc +) diff --git a/common/cairo.c b/common/cairo.c new file mode 100644 index 000000000..c6bd0da9e --- /dev/null +++ b/common/cairo.c @@ -0,0 +1,127 @@ +#include +#include +#include "cairo.h" +#ifdef WITH_GDK_PIXBUF +#include +#endif + +void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { + cairo_set_source_rgba(cairo, + (color >> (3*8) & 0xFF) / 255.0, + (color >> (2*8) & 0xFF) / 255.0, + (color >> (1*8) & 0xFF) / 255.0, + (color >> (0*8) & 0xFF) / 255.0); +} + +cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, + int width, int height) { + int image_width = cairo_image_surface_get_width(image); + int image_height = cairo_image_surface_get_height(image); + + cairo_surface_t *new = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo_t *cairo = cairo_create(new); + cairo_scale(cairo, (double)width / image_width, + (double)height / image_height); + cairo_set_source_surface(cairo, image, 0, 0); + + cairo_paint(cairo); + cairo_destroy(cairo); + return new; +} + +#ifdef WITH_GDK_PIXBUF +cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { + int chan = gdk_pixbuf_get_n_channels(gdkbuf); + if (chan < 3) { + return NULL; + } + + const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); + if (!gdkpix) { + return NULL; + } + gint w = gdk_pixbuf_get_width(gdkbuf); + gint h = gdk_pixbuf_get_height(gdkbuf); + int stride = gdk_pixbuf_get_rowstride(gdkbuf); + + cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; + cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); + cairo_surface_flush (cs); + if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { + return NULL; + } + + int cstride = cairo_image_surface_get_stride(cs); + unsigned char * cpix = cairo_image_surface_get_data(cs); + + if (chan == 3) { + int i; + for (i = h; i; --i) { + const guint8 *gp = gdkpix; + unsigned char *cp = cpix; + const guint8* end = gp + 3*w; + while (gp < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + cp[0] = gp[2]; + cp[1] = gp[1]; + cp[2] = gp[0]; +#else + cp[1] = gp[0]; + cp[2] = gp[1]; + cp[3] = gp[2]; +#endif + gp += 3; + cp += 4; + } + gdkpix += stride; + cpix += cstride; + } + } else { + /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 + * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) + * = z/256 + (z/256)/255 = (z + z/255)/256 + * # recurse once + * = (z + (z + z/255)/256)/256 + * = (z + z/256 + z/256/255) / 256 + * # only use 16bit uint operations, loose some precision, + * # result is floored. + * -> (z + z>>8)>>8 + * # add 0x80/255 = 0.5 to convert floor to round + * => (z+0x80 + (z+0x80)>>8 ) >> 8 + * ------ + * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] + */ +#define PREMUL_ALPHA(x,a,b,z) \ + G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ + G_STMT_END + int i; + for (i = h; i; --i) { + const guint8 *gp = gdkpix; + unsigned char *cp = cpix; + const guint8* end = gp + 4*w; + guint z1, z2, z3; + while (gp < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); + PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); + PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); + cp[3] = gp[3]; +#else + PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); + PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); + PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); + cp[0] = gp[3]; +#endif + gp += 4; + cp += 4; + } + gdkpix += stride; + cpix += cstride; + } +#undef PREMUL_ALPHA + } + cairo_surface_mark_dirty(cs); + return cs; +} +#endif //WITH_GDK_PIXBUF diff --git a/common/meson.build b/common/meson.build index abe0cdcfe..01736ca6b 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,12 +1,23 @@ -lib_sway_common = static_library('sway-common', +deps = [ + cairo, + wlroots +] + +if gdk_pixbuf.found() + deps += [gdk_pixbuf] +endif + +lib_sway_common = static_library( + 'sway-common', files( + 'cairo.c', + 'ipc-client.c', 'log.c', 'list.c', - 'util.c', - 'stringop.c', 'readline.c', - 'ipc-client.c' + 'stringop.c', + 'util.c' ), - dependencies: [ wlroots ], + dependencies: deps, include_directories: sway_inc ) diff --git a/include/buffer_pool.h b/include/buffer_pool.h new file mode 100644 index 000000000..cdebd64dc --- /dev/null +++ b/include/buffer_pool.h @@ -0,0 +1,21 @@ +#ifndef _SWAY_BUFFERS_H +#define _SWAY_BUFFERS_H +#include +#include +#include +#include +#include + +struct pool_buffer { + struct wl_buffer *buffer; + cairo_surface_t *surface; + cairo_t *cairo; + PangoContext *pango; + uint32_t width, height; + bool busy; +}; + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height); + +#endif diff --git a/include/cairo.h b/include/cairo.h new file mode 100644 index 000000000..f5f474d7a --- /dev/null +++ b/include/cairo.h @@ -0,0 +1,18 @@ +#ifndef _SWAY_CAIRO_H +#define _SWAY_CAIRO_H +#include +#include + +void cairo_set_source_u32(cairo_t *cairo, uint32_t color); + +cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, + int width, int height); + +#ifdef WITH_GDK_PIXBUF +#include + +cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( + const GdkPixbuf *gdkbuf); +#endif //WITH_GDK_PIXBUF + +#endif diff --git a/meson.build b/meson.build index 622769a35..0c35b0e54 100644 --- a/meson.build +++ b/meson.build @@ -27,7 +27,10 @@ wayland_client = dependency('wayland-client') wayland_egl = dependency('wayland-egl') wayland_protos = dependency('wayland-protocols') xkbcommon = dependency('xkbcommon') +cairo = dependency('cairo') pango = dependency('pango') +pangocairo = dependency('pangocairo') +gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false) pixman = dependency('pixman-1') libcap = dependency('libcap') libinput = dependency('libinput') @@ -35,6 +38,10 @@ math = cc.find_library('m') git = find_program('git', required: false) a2x = find_program('a2x', required: false) +if gdk_pixbuf.found() + add_project_arguments('-DWITH_GDK_PIXBUF', language : 'c') +endif + if a2x.found() mandir = get_option('mandir') man_files = [ @@ -89,6 +96,7 @@ subdir('protocols') subdir('common') subdir('sway') subdir('swaymsg') +subdir('client') subdir('swaybg') config = configuration_data() diff --git a/protocols/meson.build b/protocols/meson.build index 73a6fda50..1fda600e8 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -2,12 +2,6 @@ wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') wayland_scanner = find_program('wayland-scanner') -wayland_scanner_server = generator( - wayland_scanner, - output: '@BASENAME@-protocol.h', - arguments: ['server-header', '@INPUT@', '@OUTPUT@'], -) - wayland_scanner_code = generator( wayland_scanner, output: '@BASENAME@-protocol.c', @@ -20,10 +14,9 @@ wayland_scanner_client = generator( arguments: ['client-header', '@INPUT@', '@OUTPUT@'], ) -protocols = [] - -client_protocols = [ - 'wlr-layer-shell-unstable-v1.xml', +protocols = [ + [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], + ['wlr-layer-shell-unstable-v1.xml'] ] wl_protos_src = [] @@ -32,11 +25,6 @@ wl_protos_headers = [] foreach p : protocols xml = join_paths(p) wl_protos_src += wayland_scanner_code.process(xml) - wl_protos_headers += wayland_scanner_server.process(xml) -endforeach - -foreach p : client_protocols - xml = join_paths(p) wl_protos_headers += wayland_scanner_client.process(xml) endforeach diff --git a/swaybg/main.c b/swaybg/main.c index 94e982282..4473869b1 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -6,6 +6,10 @@ #include #include #include +#include "buffer_pool.h" +#include "cairo.h" +#include "util.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" enum scaling_mode { SCALING_MODE_STRETCH, @@ -13,6 +17,31 @@ enum scaling_mode { SCALING_MODE_FIT, SCALING_MODE_CENTER, SCALING_MODE_TILE, + SCALING_MODE_SOLID_COLOR, +}; + +struct swaybg_args { + int output_idx; + const char *path; + enum scaling_mode mode; +}; + +struct swaybg_state { + const struct swaybg_args *args; + + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; + + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + + bool run_display; + uint32_t width, height; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; }; bool is_valid_color(const char *color) { @@ -33,7 +62,165 @@ bool is_valid_color(const char *color) { return true; } +static void render_frame(struct swaybg_state *state) { + if (!state->run_display) { + return; + } + + state->current_buffer = get_next_buffer(state->shm, + state->buffers, state->width, state->height); + cairo_t *cairo = state->current_buffer->cairo; + + switch (state->args->mode) { + case SCALING_MODE_SOLID_COLOR: + cairo_set_source_u32(cairo, parse_color(state->args->path)); + cairo_paint(cairo); + break; + default: + exit(1); + break; + } + + wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); + wl_surface_damage(state->surface, 0, 0, state->width, state->height); + wl_surface_commit(state->surface); +} + +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t width, uint32_t height) { + struct swaybg_state *state = data; + state->width = width; + state->height = height; + render_frame(state); + zwlr_layer_surface_v1_ack_configure(surface, serial); +} + +static void layer_surface_closed(void *data, + struct zwlr_layer_surface_v1 *surface) { + struct swaybg_state *state = data; + zwlr_layer_surface_v1_destroy(state->layer_surface); + wl_surface_destroy(state->surface); + state->run_display = false; +} + +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 swaybg_state *state = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + state->compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + state->shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + static int output_idx = 0; + if (output_idx == state->args->output_idx) { + state->output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + } + output_idx++; + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + state->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); + } +} + +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares +} + +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; + int main(int argc, const char **argv) { + struct swaybg_args args = {0}; + struct swaybg_state state = {0}; + state.args = &args; wlr_log_init(L_DEBUG, NULL); + + if (argc != 4) { + wlr_log(L_ERROR, "Do not run this program manually. " + "See man 5 sway and look for output options."); + return 1; + } + args.output_idx = atoi(argv[1]); + args.path = argv[2]; + args.mode = atoi(argv[3]); + + args.mode = SCALING_MODE_STRETCH; + if (strcmp(argv[3], "stretch") == 0) { + args.mode = SCALING_MODE_STRETCH; + } else if (strcmp(argv[3], "fill") == 0) { + args.mode = SCALING_MODE_FILL; + } else if (strcmp(argv[3], "fit") == 0) { + args.mode = SCALING_MODE_FIT; + } else if (strcmp(argv[3], "center") == 0) { + args.mode = SCALING_MODE_CENTER; + } else if (strcmp(argv[3], "tile") == 0) { + args.mode = SCALING_MODE_TILE; + } else if (strcmp(argv[3], "solid_color") == 0) { + args.mode = SCALING_MODE_SOLID_COLOR; + } else { + wlr_log(L_ERROR, "Unsupported scaling mode: %s", argv[3]); + return 1; + } + + state.display = wl_display_connect(NULL); + if (!state.display) { + wlr_log(L_ERROR, "Failed to create display\n"); + return 1; + } + + struct wl_registry *registry = wl_display_get_registry(state.display); + wl_registry_add_listener(registry, ®istry_listener, &state); + wl_display_roundtrip(state.display); + + if (!state.compositor) { + wlr_log(L_DEBUG, "wl-compositor not available"); + return 1; + } + if (!state.layer_shell) { + wlr_log(L_ERROR, "layer-shell not available"); + return 1; + } + + state.surface = wl_compositor_create_surface(state.compositor); + if (!state.surface) { + wlr_log(L_ERROR, "failed to create wl_surface"); + return 1; + } + + state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( + state.layer_shell, state.surface, state.output, + ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); + if (!state.layer_surface) { + wlr_log(L_ERROR, "failed to create zwlr_layer_surface"); + return 1; + } + zwlr_layer_surface_v1_set_size(state.layer_surface, 0, 0); + zwlr_layer_surface_v1_set_anchor(state.layer_surface, + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); + zwlr_layer_surface_v1_add_listener(state.layer_surface, + &layer_surface_listener, &state); + wl_surface_commit(state.surface); + wl_display_roundtrip(state.display); + + state.run_display = true; + render_frame(&state); + while (wl_display_dispatch(state.display) != -1 && state.run_display) { + // This space intentionally left blank + } return 0; } diff --git a/swaybg/meson.build b/swaybg/meson.build index 473150239..7f5d6bd12 100644 --- a/swaybg/meson.build +++ b/swaybg/meson.build @@ -1,8 +1,22 @@ +deps = [ + cairo, + jsonc, + math, + pango, + pangocairo, + sway_protos, + wayland_client, +] + +if gdk_pixbuf.found() + deps += [gdk_pixbuf] +endif + executable( 'swaybg', 'main.c', include_directories: [sway_inc], - dependencies: [wayland_client, sway_protos, jsonc, wlroots], - link_with: [lib_sway_common], + dependencies: deps, + link_with: [lib_sway_common, lib_sway_client], install: true ) diff --git a/wayland/buffers.c b/wayland/buffers.c index e97809971..3b809e6f5 100644 --- a/wayland/buffers.c +++ b/wayland/buffers.c @@ -50,11 +50,8 @@ static const struct wl_buffer_listener buffer_listener = { .release = buffer_release }; -static struct buffer *create_buffer(struct window *window, struct buffer *buf, - int32_t width, int32_t height, int32_t scale, uint32_t format) { - - width *= scale; - height *= scale; +static struct buffer *create_buffer(struct wl_shm *shm, struct buffer *buf, + int32_t width, int32_t height, uint32_t format) { uint32_t stride = width * 4; uint32_t size = stride * height; @@ -65,7 +62,7 @@ static struct buffer *create_buffer(struct window *window, struct buffer *buf, return NULL; // never reached } void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - struct wl_shm_pool *pool = wl_shm_create_pool(window->registry->shm, fd, size); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); buf->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, format); wl_shm_pool_destroy(pool); @@ -101,34 +98,30 @@ static void destroy_buffer(struct buffer *buffer) { memset(buffer, 0, sizeof(struct buffer)); } -struct buffer *get_next_buffer(struct window *window) { +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[2], uint32_t width, uint32_t height) { struct buffer *buffer = NULL; - int i; - for (i = 0; i < 2; ++i) { - if (window->buffers[i].busy) { + for (size_t i = 0; i < sizeof(pool) / sizeof(pool[0]); ++i) { + if (buffers[i].busy) { continue; } - buffer = &window->buffers[i]; + buffer = &buffers[i]; } if (!buffer) { return NULL; } - if (buffer->width != window->width || buffer->height != window->height) { + if (buffer->width != width || buffer->height != height) { destroy_buffer(buffer); } if (!buffer->buffer) { - if (!create_buffer(window, buffer, - window->width, window->height, window->scale, + if (!create_buffer(shm, buffer, width, height, WL_SHM_FORMAT_ARGB8888)) { return NULL; } } - - window->cairo = buffer->cairo; - window->buffer = buffer; return buffer; } From f018d30fe4e9e35e602d54fbb7edcdfb0443e9ca Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 15:36:56 -0400 Subject: [PATCH 239/522] Implement image backgrounds --- swaybg/main.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/swaybg/main.c b/swaybg/main.c index 4473869b1..29cce2517 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -26,8 +26,14 @@ struct swaybg_args { enum scaling_mode mode; }; +struct swaybg_context { + uint32_t color; + cairo_surface_t *image; +}; + struct swaybg_state { const struct swaybg_args *args; + struct swaybg_context context; struct wl_display *display; struct wl_compositor *compositor; @@ -62,6 +68,71 @@ bool is_valid_color(const char *color) { return true; } +static void render_image(struct swaybg_state *state) { + cairo_t *cairo = state->current_buffer->cairo; + cairo_surface_t *image = state->context.image; + double width = cairo_image_surface_get_width(image); + double height = cairo_image_surface_get_height(image); + int wwidth = state->width; + int wheight = state->height; + + switch (state->args->mode) { + case SCALING_MODE_STRETCH: + cairo_scale(cairo, (double)wwidth / width, (double)wheight / height); + cairo_set_source_surface(cairo, image, 0, 0); + break; + case SCALING_MODE_FILL: { + double window_ratio = (double)wwidth / wheight; + double bg_ratio = width / height; + + if (window_ratio > bg_ratio) { + double scale = (double)wwidth / width; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + 0, (double)wheight / 2 / scale - height / 2); + } else { + double scale = (double)wheight / height; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + (double)wwidth / 2 / scale - width / 2, 0); + } + break; + } + case SCALING_MODE_FIT: { + double window_ratio = (double)wwidth / wheight; + double bg_ratio = width / height; + + if (window_ratio > bg_ratio) { + double scale = (double)wheight / height; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + (double)wwidth / 2 / scale - width / 2, 0); + } else { + double scale = (double)wwidth / width; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + 0, (double)wheight / 2 / scale - height / 2); + } + break; + } + case SCALING_MODE_CENTER: + cairo_set_source_surface(cairo, image, + (double)wwidth / 2 - width / 2, + (double)wheight / 2 - height / 2); + break; + case SCALING_MODE_TILE: { + cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); + cairo_set_source(cairo, pattern); + break; + } + case SCALING_MODE_SOLID_COLOR: + // Should never happen + break; + } + cairo_paint(cairo); +} + static void render_frame(struct swaybg_state *state) { if (!state->run_display) { return; @@ -73,11 +144,11 @@ static void render_frame(struct swaybg_state *state) { switch (state->args->mode) { case SCALING_MODE_SOLID_COLOR: - cairo_set_source_u32(cairo, parse_color(state->args->path)); + cairo_set_source_u32(cairo, state->context.color); cairo_paint(cairo); break; default: - exit(1); + render_image(state); break; } @@ -86,6 +157,41 @@ static void render_frame(struct swaybg_state *state) { wl_surface_commit(state->surface); } +static bool prepare_context(struct swaybg_state *state) { + if (state->args->mode == SCALING_MODE_SOLID_COLOR) { + state->context.color = parse_color(state->args->path); + return is_valid_color(state->args->path); + } +#ifdef WITH_GDK_PIXBUF + GError *err = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(state->args->path, &err); + if (!pixbuf) { + wlr_log(L_ERROR, "Failed to load background image."); + return false; + } + state->context.image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); + g_object_unref(pixbuf); +#else + state->context.image = cairo_image_surface_create_from_png( + state->args->path); +#endif //WITH_GDK_PIXBUF + if (!state->context.image) { + wlr_log(L_ERROR, "Failed to read background image."); + return false; + } + if (cairo_surface_status(state->context.image) != CAIRO_STATUS_SUCCESS) { + wlr_log(L_ERROR, "Failed to read background image: %s." +#ifndef WITH_GDK_PIXBUF + "\nSway was compiled without gdk_pixbuf support, so only" + "\nPNG images can be loaded. This is the likely cause." +#endif //WITH_GDK_PIXBUF + , cairo_status_to_string( + cairo_surface_status(state->context.image))); + return false; + } + return true; +} + static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height) { @@ -217,6 +323,10 @@ int main(int argc, const char **argv) { wl_surface_commit(state.surface); wl_display_roundtrip(state.display); + if (!prepare_context(&state)) { + return 1; + } + state.run_display = true; render_frame(&state); while (wl_display_dispatch(state.display) != -1 && state.run_display) { From 17e39f6291a62575437ce73bd61441bf21865622 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 16:00:34 -0400 Subject: [PATCH 240/522] s/scaling_mode/background_mode/g Since it now includes SOLID_COLOR this is a more appropriate name. --- swaybg/main.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/swaybg/main.c b/swaybg/main.c index 29cce2517..038b8ea69 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -11,19 +11,19 @@ #include "util.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -enum scaling_mode { - SCALING_MODE_STRETCH, - SCALING_MODE_FILL, - SCALING_MODE_FIT, - SCALING_MODE_CENTER, - SCALING_MODE_TILE, - SCALING_MODE_SOLID_COLOR, +enum background_mode { + BACKGROUND_MODE_STRETCH, + BACKGROUND_MODE_FILL, + BACKGROUND_MODE_FIT, + BACKGROUND_MODE_CENTER, + BACKGROUND_MODE_TILE, + BACKGROUND_MODE_SOLID_COLOR, }; struct swaybg_args { int output_idx; const char *path; - enum scaling_mode mode; + enum background_mode mode; }; struct swaybg_context { @@ -77,11 +77,11 @@ static void render_image(struct swaybg_state *state) { int wheight = state->height; switch (state->args->mode) { - case SCALING_MODE_STRETCH: + case BACKGROUND_MODE_STRETCH: cairo_scale(cairo, (double)wwidth / width, (double)wheight / height); cairo_set_source_surface(cairo, image, 0, 0); break; - case SCALING_MODE_FILL: { + case BACKGROUND_MODE_FILL: { double window_ratio = (double)wwidth / wheight; double bg_ratio = width / height; @@ -98,7 +98,7 @@ static void render_image(struct swaybg_state *state) { } break; } - case SCALING_MODE_FIT: { + case BACKGROUND_MODE_FIT: { double window_ratio = (double)wwidth / wheight; double bg_ratio = width / height; @@ -115,18 +115,18 @@ static void render_image(struct swaybg_state *state) { } break; } - case SCALING_MODE_CENTER: + case BACKGROUND_MODE_CENTER: cairo_set_source_surface(cairo, image, (double)wwidth / 2 - width / 2, (double)wheight / 2 - height / 2); break; - case SCALING_MODE_TILE: { + case BACKGROUND_MODE_TILE: { cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_set_source(cairo, pattern); break; } - case SCALING_MODE_SOLID_COLOR: + case BACKGROUND_MODE_SOLID_COLOR: // Should never happen break; } @@ -143,7 +143,7 @@ static void render_frame(struct swaybg_state *state) { cairo_t *cairo = state->current_buffer->cairo; switch (state->args->mode) { - case SCALING_MODE_SOLID_COLOR: + case BACKGROUND_MODE_SOLID_COLOR: cairo_set_source_u32(cairo, state->context.color); cairo_paint(cairo); break; @@ -158,7 +158,7 @@ static void render_frame(struct swaybg_state *state) { } static bool prepare_context(struct swaybg_state *state) { - if (state->args->mode == SCALING_MODE_SOLID_COLOR) { + if (state->args->mode == BACKGROUND_MODE_SOLID_COLOR) { state->context.color = parse_color(state->args->path); return is_valid_color(state->args->path); } @@ -262,21 +262,21 @@ int main(int argc, const char **argv) { args.path = argv[2]; args.mode = atoi(argv[3]); - args.mode = SCALING_MODE_STRETCH; + args.mode = BACKGROUND_MODE_STRETCH; if (strcmp(argv[3], "stretch") == 0) { - args.mode = SCALING_MODE_STRETCH; + args.mode = BACKGROUND_MODE_STRETCH; } else if (strcmp(argv[3], "fill") == 0) { - args.mode = SCALING_MODE_FILL; + args.mode = BACKGROUND_MODE_FILL; } else if (strcmp(argv[3], "fit") == 0) { - args.mode = SCALING_MODE_FIT; + args.mode = BACKGROUND_MODE_FIT; } else if (strcmp(argv[3], "center") == 0) { - args.mode = SCALING_MODE_CENTER; + args.mode = BACKGROUND_MODE_CENTER; } else if (strcmp(argv[3], "tile") == 0) { - args.mode = SCALING_MODE_TILE; + args.mode = BACKGROUND_MODE_TILE; } else if (strcmp(argv[3], "solid_color") == 0) { - args.mode = SCALING_MODE_SOLID_COLOR; + args.mode = BACKGROUND_MODE_SOLID_COLOR; } else { - wlr_log(L_ERROR, "Unsupported scaling mode: %s", argv[3]); + wlr_log(L_ERROR, "Unsupported background mode: %s", argv[3]); return 1; } From 53e3763b58575cda89562d0fa1a4f9270a9c74f6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 16:01:29 -0400 Subject: [PATCH 241/522] Fix style --- client/buffer-pool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/buffer-pool.c b/client/buffer-pool.c index 26d0f7e51..7f673ae98 100644 --- a/client/buffer-pool.c +++ b/client/buffer-pool.c @@ -13,7 +13,7 @@ static int create_pool_file(size_t size, char **name) { static const char template[] = "sway-client-XXXXXX"; const char *path = getenv("XDG_RUNTIME_DIR"); - if (!path) { + if (!path) { return -1; } From e9922ec52496068e0976d77ba52e5b9c0d074ce1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 15:37:24 -0400 Subject: [PATCH 242/522] Remove obsolete client code --- include/client/buffer.h | 8 -- include/client/cairo.h | 17 --- include/client/pango.h | 16 --- include/client/registry.h | 75 ---------- include/client/window.h | 67 --------- wayland/buffers.c | 127 ----------------- wayland/cairo.c | 134 ----------------- wayland/pango.c | 73 ---------- wayland/registry.c | 293 -------------------------------------- wayland/window.c | 177 ----------------------- 10 files changed, 987 deletions(-) delete mode 100644 include/client/buffer.h delete mode 100644 include/client/cairo.h delete mode 100644 include/client/pango.h delete mode 100644 include/client/registry.h delete mode 100644 include/client/window.h delete mode 100644 wayland/buffers.c delete mode 100644 wayland/cairo.c delete mode 100644 wayland/pango.c delete mode 100644 wayland/registry.c delete mode 100644 wayland/window.c diff --git a/include/client/buffer.h b/include/client/buffer.h deleted file mode 100644 index eb9973ed2..000000000 --- a/include/client/buffer.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _BUFFER_H -#define _BUFFER_H - -#include "client/window.h" - -struct buffer *get_next_buffer(struct window *state); - -#endif diff --git a/include/client/cairo.h b/include/client/cairo.h deleted file mode 100644 index e7ef7c7e5..000000000 --- a/include/client/cairo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _SWAY_CAIRO_H -#define _SWAY_CAIRO_H - -#include -#include - -void cairo_set_source_u32(cairo_t *cairo, uint32_t color); - -cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, int width, int height); - -#ifdef WITH_GDK_PIXBUF -#include - -cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf); -#endif //WITH_GDK_PIXBUF - -#endif diff --git a/include/client/pango.h b/include/client/pango.h deleted file mode 100644 index dd2f53c36..000000000 --- a/include/client/pango.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _SWAY_CLIENT_PANGO_H -#define _SWAY_CLIENT_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/client/registry.h b/include/client/registry.h deleted file mode 100644 index 9dfbd835d..000000000 --- a/include/client/registry.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _SWAY_CLIENT_REGISTRY_H -#define _SWAY_CLIENT_REGISTRY_H - -#include -#include -#include "wayland-desktop-shell-client-protocol.h" -#include "wayland-swaylock-client-protocol.h" -#include "list.h" - -enum mod_bit { - MOD_SHIFT = 1<<0, - MOD_CAPS = 1<<1, - MOD_CTRL = 1<<2, - MOD_ALT = 1<<3, - MOD_MOD2 = 1<<4, - MOD_MOD3 = 1<<5, - MOD_LOGO = 1<<6, - MOD_MOD5 = 1<<7, -}; - -enum mask { - MASK_SHIFT, - MASK_CAPS, - MASK_CTRL, - MASK_ALT, - MASK_MOD2, - MASK_MOD3, - MASK_LOGO, - MASK_MOD5, - MASK_LAST -}; - -struct output_state { - struct wl_output *output; - uint32_t flags; - uint32_t width, height; - uint32_t scale; -}; - -struct xkb { - struct xkb_state *state; - struct xkb_context *context; - struct xkb_keymap *keymap; - xkb_mod_mask_t masks[MASK_LAST]; -}; - -struct input { - struct xkb xkb; - - xkb_keysym_t sym; - uint32_t code; - uint32_t last_code; - uint32_t modifiers; - - void (*notify)(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint); -}; - -struct registry { - struct wl_compositor *compositor; - struct wl_display *display; - struct wl_pointer *pointer; - struct wl_keyboard *keyboard; - struct wl_seat *seat; - struct wl_shell *shell; - struct wl_shm *shm; - struct desktop_shell *desktop_shell; - struct lock *swaylock; - struct input *input; - list_t *outputs; -}; - -struct registry *registry_poll(void); -void registry_teardown(struct registry *registry); - -#endif diff --git a/include/client/window.h b/include/client/window.h deleted file mode 100644 index 8af8225c5..000000000 --- a/include/client/window.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _CLIENT_H -#define _CLIENT_H - -#include -#include "wayland-desktop-shell-client-protocol.h" -#include -#include -#include -#include "list.h" -#include "client/registry.h" - -struct window; - -struct buffer { - struct wl_buffer *buffer; - cairo_surface_t *surface; - cairo_t *cairo; - PangoContext *pango; - uint32_t width, height; - bool busy; -}; - -struct cursor { - struct wl_surface *surface; - struct wl_cursor_theme *cursor_theme; - struct wl_cursor *cursor; - struct wl_pointer *pointer; -}; - -enum scroll_direction { - SCROLL_UP, - SCROLL_DOWN, - SCROLL_LEFT, - SCROLL_RIGHT, -}; - -struct pointer_input { - int last_x; - int last_y; - - void (*notify_button)(struct window *window, int x, int y, uint32_t button, uint32_t state_w); - void (*notify_scroll)(struct window *window, enum scroll_direction direction); -}; - -struct window { - struct registry *registry; - struct buffer buffers[2]; - struct buffer *buffer; - struct wl_surface *surface; - struct wl_shell_surface *shell_surface; - struct wl_callback *frame_cb; - struct cursor cursor; - uint32_t width, height; - int32_t scale; - char *font; - cairo_t *cairo; - struct pointer_input pointer_input; -}; - -struct window *window_setup(struct registry *registry, uint32_t width, uint32_t height, - int32_t scale, bool shell_surface); -void window_teardown(struct window *state); -int window_prerender(struct window *state); -int window_render(struct window *state); -void window_make_shell(struct window *window); - -#endif diff --git a/wayland/buffers.c b/wayland/buffers.c deleted file mode 100644 index 3b809e6f5..000000000 --- a/wayland/buffers.c +++ /dev/null @@ -1,127 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "client/buffer.h" -#include "list.h" -#include "log.h" - -static int create_pool_file(size_t size, char **name) { - static const char template[] = "sway-client-XXXXXX"; - const char *path = getenv("XDG_RUNTIME_DIR"); - if (!path) { - return -1; - } - - int ts = (path[strlen(path) - 1] == '/'); - - *name = malloc( - strlen(template) + - strlen(path) + - (ts ? 0 : 1) + 1); - sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); - - int fd = mkstemp(*name); - - if (fd < 0) { - return -1; - } - - if (ftruncate(fd, size) < 0) { - close(fd); - return -1; - } - - return fd; -} - -static void buffer_release(void *data, struct wl_buffer *wl_buffer) { - struct buffer *buffer = data; - buffer->busy = false; -} - -static const struct wl_buffer_listener buffer_listener = { - .release = buffer_release -}; - -static struct buffer *create_buffer(struct wl_shm *shm, struct buffer *buf, - int32_t width, int32_t height, uint32_t format) { - uint32_t stride = width * 4; - uint32_t size = stride * height; - - char *name; - int fd = create_pool_file(size, &name); - if (fd == -1) { - sway_abort("Unable to allocate buffer"); - return NULL; // never reached - } - void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); - buf->buffer = wl_shm_pool_create_buffer(pool, 0, - width, height, stride, format); - wl_shm_pool_destroy(pool); - close(fd); - unlink(name); - free(name); - fd = -1; - - buf->width = width; - buf->height = height; - buf->surface = cairo_image_surface_create_for_data(data, - CAIRO_FORMAT_ARGB32, width, height, stride); - buf->cairo = cairo_create(buf->surface); - buf->pango = pango_cairo_create_context(buf->cairo); - - wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); - return buf; -} - -static void destroy_buffer(struct buffer *buffer) { - if (buffer->buffer) { - wl_buffer_destroy(buffer->buffer); - } - if (buffer->cairo) { - cairo_destroy(buffer->cairo); - } - if (buffer->surface) { - cairo_surface_destroy(buffer->surface); - } - if (buffer->pango) { - g_object_unref(buffer->pango); - } - memset(buffer, 0, sizeof(struct buffer)); -} - -struct pool_buffer *get_next_buffer(struct wl_shm *shm, - struct pool_buffer pool[2], uint32_t width, uint32_t height) { - struct buffer *buffer = NULL; - - for (size_t i = 0; i < sizeof(pool) / sizeof(pool[0]); ++i) { - if (buffers[i].busy) { - continue; - } - buffer = &buffers[i]; - } - - if (!buffer) { - return NULL; - } - - if (buffer->width != width || buffer->height != height) { - destroy_buffer(buffer); - } - - if (!buffer->buffer) { - if (!create_buffer(shm, buffer, width, height, - WL_SHM_FORMAT_ARGB8888)) { - return NULL; - } - } - return buffer; -} diff --git a/wayland/cairo.c b/wayland/cairo.c deleted file mode 100644 index 193205b1c..000000000 --- a/wayland/cairo.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "client/cairo.h" - -void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { - cairo_set_source_rgba(cairo, - (color >> (3*8) & 0xFF) / 255.0, - (color >> (2*8) & 0xFF) / 255.0, - (color >> (1*8) & 0xFF) / 255.0, - (color >> (0*8) & 0xFF) / 255.0); -} - -cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, int width, int height) { - int image_width = cairo_image_surface_get_width(image); - int image_height = cairo_image_surface_get_height(image); - - cairo_surface_t *new = - cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - - cairo_t *cairo = cairo_create(new); - - cairo_scale(cairo, (double) width / image_width, (double) height / image_height); - - cairo_set_source_surface(cairo, image, 0, 0); - cairo_paint(cairo); - - cairo_destroy(cairo); - - return new; -} - -#ifdef WITH_GDK_PIXBUF -#include - -#ifndef GDK_PIXBUF_CHECK_VERSION -#define GDK_PIXBUF_CHECK_VERSION(major,minor,micro) \ - (GDK_PIXBUF_MAJOR > (major) || \ - (GDK_PIXBUF_MAJOR == (major) && GDK_PIXBUF_MINOR > (minor)) || \ - (GDK_PIXBUF_MAJOR == (major) && GDK_PIXBUF_MINOR == (minor) && \ - GDK_PIXBUF_MICRO >= (micro))) -#endif - -cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { - int chan = gdk_pixbuf_get_n_channels(gdkbuf); - if (chan < 3) return NULL; - -#if GDK_PIXBUF_CHECK_VERSION(2,32,0) - const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); -#else - const guint8* gdkpix = gdk_pixbuf_get_pixels(gdkbuf); -#endif - if (!gdkpix) { - return NULL; - } - gint w = gdk_pixbuf_get_width(gdkbuf); - gint h = gdk_pixbuf_get_height(gdkbuf); - int stride = gdk_pixbuf_get_rowstride(gdkbuf); - - cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; - cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); - cairo_surface_flush (cs); - if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { - return NULL; - } - - int cstride = cairo_image_surface_get_stride(cs); - unsigned char * cpix = cairo_image_surface_get_data(cs); - - if (chan == 3) { - int i; - for (i = h; i; --i) { - const guint8 *gp = gdkpix; - unsigned char *cp = cpix; - const guint8* end = gp + 3*w; - while (gp < end) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - cp[0] = gp[2]; - cp[1] = gp[1]; - cp[2] = gp[0]; -#else - cp[1] = gp[0]; - cp[2] = gp[1]; - cp[3] = gp[2]; -#endif - gp += 3; - cp += 4; - } - gdkpix += stride; - cpix += cstride; - } - } else { - /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 - * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) - * = z/256 + (z/256)/255 = (z + z/255)/256 - * # recurse once - * = (z + (z + z/255)/256)/256 - * = (z + z/256 + z/256/255) / 256 - * # only use 16bit uint operations, loose some precision, - * # result is floored. - * -> (z + z>>8)>>8 - * # add 0x80/255 = 0.5 to convert floor to round - * => (z+0x80 + (z+0x80)>>8 ) >> 8 - * ------ - * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] - */ -#define PREMUL_ALPHA(x,a,b,z) G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } G_STMT_END - int i; - for (i = h; i; --i) { - const guint8 *gp = gdkpix; - unsigned char *cp = cpix; - const guint8* end = gp + 4*w; - guint z1, z2, z3; - while (gp < end) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); - PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); - PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); - cp[3] = gp[3]; -#else - PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); - PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); - PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); - cp[0] = gp[3]; -#endif - gp += 4; - cp += 4; - } - gdkpix += stride; - cpix += cstride; - } -#undef PREMUL_ALPHA - } - cairo_surface_mark_dirty(cs); - return cs; -} -#endif //WITH_GDK_PIXBUF diff --git a/wayland/pango.c b/wayland/pango.c deleted file mode 100644 index f9eec98cb..000000000 --- a/wayland/pango.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "log.h" - -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/wayland/registry.c b/wayland/registry.c deleted file mode 100644 index bbb43ad90..000000000 --- a/wayland/registry.c +++ /dev/null @@ -1,293 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "wayland-desktop-shell-client-protocol.h" -#include "wayland-swaylock-client-protocol.h" -#include "client/registry.h" -#include "stringop.h" -#include "log.h" - -static void display_handle_mode(void *data, struct wl_output *wl_output, - uint32_t flags, int32_t width, int32_t height, int32_t refresh) { - struct output_state *state = data; - if (flags & WL_OUTPUT_MODE_CURRENT) { - state->flags = flags; - state->width = width; - state->height = height; - sway_log(L_DEBUG, "Got mode %dx%d:0x%X for output %p", - width, height, flags, data); - } -} - -static void display_handle_geometry(void *data, struct wl_output *wl_output, - int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, - int32_t subpixel, const char *make, const char *model, int32_t transform) { - // this space intentionally left blank -} - -static void display_handle_done(void *data, struct wl_output *wl_output) { - // this space intentionally left blank -} - -static void display_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) { - struct output_state *state = data; - state->scale = factor; - sway_log(L_DEBUG, "Got scale factor %d for output %p", factor, data); -} - -static const struct wl_output_listener output_listener = { - .mode = display_handle_mode, - .geometry = display_handle_geometry, - .done = display_handle_done, - .scale = display_handle_scale -}; - -const char *XKB_MASK_NAMES[MASK_LAST] = { - XKB_MOD_NAME_SHIFT, - XKB_MOD_NAME_CAPS, - XKB_MOD_NAME_CTRL, - XKB_MOD_NAME_ALT, - "Mod2", - "Mod3", - XKB_MOD_NAME_LOGO, - "Mod5", -}; - -const enum mod_bit XKB_MODS[MASK_LAST] = { - MOD_SHIFT, - MOD_CAPS, - MOD_CTRL, - MOD_ALT, - MOD_MOD2, - MOD_MOD3, - MOD_LOGO, - MOD_MOD5 -}; - -static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, - uint32_t format, int fd, uint32_t size) { - // Keyboard errors are abort-worthy because you wouldn't be able to unlock your screen otherwise. - - struct registry *registry = data; - if (!data) { - close(fd); - return; - } - - if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { - close(fd); - sway_abort("Unknown keymap format %d, aborting", format); - } - - char *map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (map_str == MAP_FAILED) { - close(fd); - sway_abort("Unable to initialized shared keyboard memory, aborting"); - } - - struct xkb_keymap *keymap = xkb_keymap_new_from_string(registry->input->xkb.context, - map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); - munmap(map_str, size); - close(fd); - - if (!keymap) { - sway_abort("Failed to compile keymap, aborting"); - } - - struct xkb_state *state = xkb_state_new(keymap); - if (!state) { - xkb_keymap_unref(keymap); - sway_abort("Failed to create xkb state, aborting"); - } - - xkb_keymap_unref(registry->input->xkb.keymap); - xkb_state_unref(registry->input->xkb.state); - registry->input->xkb.keymap = keymap; - registry->input->xkb.state = state; - - int i; - for (i = 0; i < MASK_LAST; ++i) { - registry->input->xkb.masks[i] = 1 << xkb_keymap_mod_get_index(registry->input->xkb.keymap, XKB_MASK_NAMES[i]); - } -} - -static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, - uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { - // this space intentionally left blank -} - -static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, - uint32_t serial, struct wl_surface *surface) { - // this space intentionally left blank -} - -static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, - uint32_t serial, uint32_t time, uint32_t key, uint32_t state_w) { - struct registry *registry = data; - enum wl_keyboard_key_state state = state_w; - - if (!registry->input->xkb.state) { - return; - } - - xkb_keysym_t sym = xkb_state_key_get_one_sym(registry->input->xkb.state, key + 8); - registry->input->sym = (state == WL_KEYBOARD_KEY_STATE_PRESSED ? sym : XKB_KEY_NoSymbol); - registry->input->code = (state == WL_KEYBOARD_KEY_STATE_PRESSED ? key + 8 : 0); - uint32_t codepoint = xkb_state_key_get_utf32(registry->input->xkb.state, registry->input->code); - if (registry->input->notify) { - registry->input->notify(state, sym, key, codepoint); - } -} - -static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, - uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, - uint32_t mods_locked, uint32_t group) { - struct registry *registry = data; - - if (!registry->input->xkb.keymap) { - return; - } - - xkb_state_update_mask(registry->input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group); - xkb_mod_mask_t mask = xkb_state_serialize_mods(registry->input->xkb.state, - XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); - - registry->input->modifiers = 0; - for (uint32_t i = 0; i < MASK_LAST; ++i) { - if (mask & registry->input->xkb.masks[i]) { - registry->input->modifiers |= XKB_MODS[i]; - } - } -} - -static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard, - int32_t rate, int32_t delay) { - // this space intentionally left blank -} - -static const struct wl_keyboard_listener keyboard_listener = { - .keymap = keyboard_handle_keymap, - .enter = keyboard_handle_enter, - .leave = keyboard_handle_leave, - .key = keyboard_handle_key, - .modifiers = keyboard_handle_modifiers, - .repeat_info = keyboard_handle_repeat_info -}; - -static void seat_handle_capabilities(void *data, struct wl_seat *seat, - enum wl_seat_capability caps) { - struct registry *reg = data; - - if ((caps & WL_SEAT_CAPABILITY_POINTER) && !reg->pointer) { - reg->pointer = wl_seat_get_pointer(reg->seat); - } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && reg->pointer) { - wl_pointer_destroy(reg->pointer); - reg->pointer = NULL; - } - - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !reg->keyboard) { - reg->keyboard = wl_seat_get_keyboard(reg->seat); - wl_keyboard_add_listener(reg->keyboard, &keyboard_listener, reg); - } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && reg->keyboard) { - wl_keyboard_destroy(reg->keyboard); - reg->keyboard = NULL; - } -} - -static void seat_handle_name(void *data, struct wl_seat *seat, const char *name) { - // this space intentionally left blank -} - -static const struct wl_seat_listener seat_listener = { - .capabilities = seat_handle_capabilities, - .name = seat_handle_name, -}; - -static void registry_global(void *data, struct wl_registry *registry, - uint32_t name, const char *interface, uint32_t version) { - struct registry *reg = data; - - if (strcmp(interface, wl_compositor_interface.name) == 0) { - reg->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, version); - } else if (strcmp(interface, wl_shm_interface.name) == 0) { - reg->shm = wl_registry_bind(registry, name, &wl_shm_interface, version); - } else if (strcmp(interface, wl_shell_interface.name) == 0) { - reg->shell = wl_registry_bind(registry, name, &wl_shell_interface, version); - } else if (strcmp(interface, wl_seat_interface.name) == 0) { - reg->seat = wl_registry_bind(registry, name, &wl_seat_interface, version); - wl_seat_add_listener(reg->seat, &seat_listener, reg); - } else if (strcmp(interface, wl_output_interface.name) == 0) { - struct wl_output *output = wl_registry_bind(registry, name, &wl_output_interface, version); - struct output_state *ostate = malloc(sizeof(struct output_state)); - ostate->output = output; - ostate->scale = 1; - wl_output_add_listener(output, &output_listener, ostate); - list_add(reg->outputs, ostate); - } else if (strcmp(interface, desktop_shell_interface.name) == 0) { - reg->desktop_shell = wl_registry_bind(registry, name, &desktop_shell_interface, version); - } else if (strcmp(interface, lock_interface.name) == 0) { - reg->swaylock = wl_registry_bind(registry, name, &lock_interface, version); - } -} - -static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) { - // this space intentionally left blank -} - -static const struct wl_registry_listener registry_listener = { - .global = registry_global, - .global_remove = registry_global_remove -}; - -struct registry *registry_poll(void) { - struct registry *registry = malloc(sizeof(struct registry)); - memset(registry, 0, sizeof(struct registry)); - registry->outputs = create_list(); - registry->input = calloc(sizeof(struct input), 1); - registry->input->xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - - registry->display = wl_display_connect(NULL); - if (!registry->display) { - sway_log(L_ERROR, "Error opening display"); - registry_teardown(registry); - return NULL; - } - - struct wl_registry *reg = wl_display_get_registry(registry->display); - wl_registry_add_listener(reg, ®istry_listener, registry); - wl_display_dispatch(registry->display); - wl_display_roundtrip(registry->display); - wl_registry_destroy(reg); - - return registry; -} - -void registry_teardown(struct registry *registry) { - if (registry->pointer) { - wl_pointer_destroy(registry->pointer); - } - if (registry->seat) { - wl_seat_destroy(registry->seat); - } - if (registry->shell) { - wl_shell_destroy(registry->shell); - } - if (registry->shm) { - wl_shm_destroy(registry->shm); - } - if (registry->compositor) { - wl_compositor_destroy(registry->compositor); - } - if (registry->display) { - wl_display_disconnect(registry->display); - } - if (registry->outputs) { - free_flat_list(registry->outputs); - } - free(registry); -} diff --git a/wayland/window.c b/wayland/window.c deleted file mode 100644 index 8a5066562..000000000 --- a/wayland/window.c +++ /dev/null @@ -1,177 +0,0 @@ -#include -#include -#include "wayland-xdg-shell-client-protocol.h" -#include "wayland-desktop-shell-client-protocol.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "client/window.h" -#include "client/buffer.h" -#include "list.h" -#include "log.h" - -static void pointer_handle_enter(void *data, struct wl_pointer *pointer, - uint32_t serial, struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) { - struct window *window = data; - if (window->registry->pointer) { - struct wl_cursor_image *image = window->cursor.cursor->images[0]; - wl_pointer_set_cursor(pointer, serial, window->cursor.surface, image->hotspot_x, image->hotspot_y); - } -} - -static void pointer_handle_leave(void *data, struct wl_pointer *pointer, - uint32_t serial, struct wl_surface *surface) { -} - -static void pointer_handle_motion(void *data, struct wl_pointer *pointer, - uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) { - struct window *window = data; - - window->pointer_input.last_x = wl_fixed_to_int(sx_w); - window->pointer_input.last_y = wl_fixed_to_int(sy_w); -} - -static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, - uint32_t time, uint32_t button, uint32_t state_w) { - struct window *window = data; - struct pointer_input *input = &window->pointer_input; - - if (window->pointer_input.notify_button) { - window->pointer_input.notify_button(window, input->last_x, input->last_y, button, state_w); - } -} - -static void pointer_handle_axis(void *data, struct wl_pointer *pointer, - uint32_t time, uint32_t axis, wl_fixed_t value) { - struct window *window = data; - enum scroll_direction direction; - - switch (axis) { - case 0: - direction = wl_fixed_to_double(value) < 0 ? SCROLL_UP : SCROLL_DOWN; - break; - case 1: - direction = wl_fixed_to_double(value) < 0 ? SCROLL_LEFT : SCROLL_RIGHT; - break; - default: - sway_log(L_DEBUG, "Unexpected axis value on mouse scroll"); - return; - } - - if (window->pointer_input.notify_scroll) { - window->pointer_input.notify_scroll(window, direction); - } -} - -static const struct wl_pointer_listener pointer_listener = { - .enter = pointer_handle_enter, - .leave = pointer_handle_leave, - .motion = pointer_handle_motion, - .button = pointer_handle_button, - .axis = pointer_handle_axis -}; - -void shell_surface_configure(void *data, struct wl_shell_surface *wl_shell_surface, - uint32_t edges, int32_t width, int32_t height) { - struct window *window = data; - window->width = width; - window->height = height; -} - -static const struct wl_shell_surface_listener surface_listener = { - .configure = shell_surface_configure -}; - -void window_make_shell(struct window *window) { - window->shell_surface = wl_shell_get_shell_surface(window->registry->shell, window->surface); - wl_shell_surface_add_listener(window->shell_surface, &surface_listener, window); - wl_shell_surface_set_toplevel(window->shell_surface); -} - -struct window *window_setup(struct registry *registry, uint32_t width, uint32_t height, - int32_t scale, bool shell_surface) { - struct window *window = malloc(sizeof(struct window)); - memset(window, 0, sizeof(struct window)); - window->width = width; - window->height = height; - window->scale = scale; - window->registry = registry; - window->font = "monospace 10"; - - window->surface = wl_compositor_create_surface(registry->compositor); - if (shell_surface) { - window_make_shell(window); - } - if (registry->pointer) { - wl_pointer_add_listener(registry->pointer, &pointer_listener, window); - } - - get_next_buffer(window); - - if (registry->pointer) { - char *cursor_theme = getenv("SWAY_CURSOR_THEME"); - if (!cursor_theme) { - cursor_theme = "default"; - } - char *cursor_size = getenv("SWAY_CURSOR_SIZE"); - if (!cursor_size) { - cursor_size = "16"; - } - - sway_log(L_DEBUG, "Cursor scale: %d", scale); - window->cursor.cursor_theme = wl_cursor_theme_load(cursor_theme, - atoi(cursor_size) * scale, registry->shm); - window->cursor.cursor = wl_cursor_theme_get_cursor(window->cursor.cursor_theme, "left_ptr"); - window->cursor.surface = wl_compositor_create_surface(registry->compositor); - - struct wl_cursor_image *image = window->cursor.cursor->images[0]; - struct wl_buffer *cursor_buf = wl_cursor_image_get_buffer(image); - wl_surface_attach(window->cursor.surface, cursor_buf, 0, 0); - wl_surface_set_buffer_scale(window->cursor.surface, scale); - wl_surface_damage(window->cursor.surface, 0, 0, - image->width, image->height); - wl_surface_commit(window->cursor.surface); - } - - return window; -} - -static void frame_callback(void *data, struct wl_callback *callback, uint32_t time) { - struct window *window = data; - wl_callback_destroy(callback); - window->frame_cb = NULL; -} - -static const struct wl_callback_listener listener = { - frame_callback -}; - -int window_prerender(struct window *window) { - if (window->frame_cb) { - return 0; - } - - get_next_buffer(window); - return 1; -} - -int window_render(struct window *window) { - window->frame_cb = wl_surface_frame(window->surface); - wl_callback_add_listener(window->frame_cb, &listener, window); - - wl_surface_attach(window->surface, window->buffer->buffer, 0, 0); - wl_surface_set_buffer_scale(window->surface, window->scale); - wl_surface_damage(window->surface, 0, 0, window->width, window->height); - wl_surface_commit(window->surface); - - return 1; -} - -void window_teardown(struct window *window) { - // TODO -} From 653853062f15639c97d02a8d67443506ce3af69d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 23:08:51 -0400 Subject: [PATCH 243/522] Refactor configure/ack configure/commit flow --- swaybg/main.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/swaybg/main.c b/swaybg/main.c index 038b8ea69..62ddec6c7 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -134,10 +134,6 @@ static void render_image(struct swaybg_state *state) { } static void render_frame(struct swaybg_state *state) { - if (!state->run_display) { - return; - } - state->current_buffer = get_next_buffer(state->shm, state->buffers, state->width, state->height); cairo_t *cairo = state->current_buffer->cairo; @@ -198,8 +194,8 @@ static void layer_surface_configure(void *data, struct swaybg_state *state = data; state->width = width; state->height = height; - render_frame(state); zwlr_layer_surface_v1_ack_configure(surface, serial); + render_frame(state); } static void layer_surface_closed(void *data, @@ -280,6 +276,10 @@ int main(int argc, const char **argv) { return 1; } + if (!prepare_context(&state)) { + return 1; + } + state.display = wl_display_connect(NULL); if (!state.display) { wlr_log(L_ERROR, "Failed to create display\n"); @@ -323,12 +323,7 @@ int main(int argc, const char **argv) { wl_surface_commit(state.surface); wl_display_roundtrip(state.display); - if (!prepare_context(&state)) { - return 1; - } - state.run_display = true; - render_frame(&state); while (wl_display_dispatch(state.display) != -1 && state.run_display) { // This space intentionally left blank } From d39bda76c4007c42452a81883fefc671b816a74b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 12:21:50 -0400 Subject: [PATCH 244/522] Address review comments --- client/meson.build | 23 +++++-------- client/{buffer-pool.c => pool-buffer.c} | 3 +- common/cairo.c | 6 ++-- include/cairo.h | 3 +- include/meson.build | 1 + include/{buffer_pool.h => pool-buffer.h} | 0 meson.build | 5 ++- swaybg/main.c | 44 +++++++----------------- swaybg/meson.build | 36 +++++++++---------- 9 files changed, 50 insertions(+), 71 deletions(-) rename client/{buffer-pool.c => pool-buffer.c} (98%) create mode 100644 include/meson.build rename include/{buffer_pool.h => pool-buffer.h} (100%) diff --git a/client/meson.build b/client/meson.build index 597899ce2..2bdda457c 100644 --- a/client/meson.build +++ b/client/meson.build @@ -1,21 +1,16 @@ -deps = [ - cairo, - pango, - pangocairo, - wlroots, - wayland_client, -] - -if gdk_pixbuf.found() - deps += [gdk_pixbuf] -endif - lib_sway_client = static_library( 'sway-client', files( - 'buffer-pool.c', + 'pool-buffer.c', ), - dependencies: deps, + dependencies: [ + cairo, + gdk_pixbuf, + pango, + pangocairo, + wlroots, + wayland_client, + ], link_with: [lib_sway_common], include_directories: sway_inc ) diff --git a/client/buffer-pool.c b/client/pool-buffer.c similarity index 98% rename from client/buffer-pool.c rename to client/pool-buffer.c index 7f673ae98..93cfcfc5a 100644 --- a/client/buffer-pool.c +++ b/client/pool-buffer.c @@ -8,7 +8,8 @@ #include #include #include -#include "buffer_pool.h" +#include "config.h" +#include "pool-buffer.h" static int create_pool_file(size_t size, char **name) { static const char template[] = "sway-client-XXXXXX"; diff --git a/common/cairo.c b/common/cairo.c index c6bd0da9e..c267c77ca 100644 --- a/common/cairo.c +++ b/common/cairo.c @@ -1,7 +1,7 @@ #include #include #include "cairo.h" -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF #include #endif @@ -30,7 +30,7 @@ cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, return new; } -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { int chan = gdk_pixbuf_get_n_channels(gdkbuf); if (chan < 3) { @@ -124,4 +124,4 @@ cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdk cairo_surface_mark_dirty(cs); return cs; } -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF diff --git a/include/cairo.h b/include/cairo.h index f5f474d7a..316727059 100644 --- a/include/cairo.h +++ b/include/cairo.h @@ -8,7 +8,8 @@ void cairo_set_source_u32(cairo_t *cairo, uint32_t color); cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, int width, int height); -#ifdef WITH_GDK_PIXBUF +#include "config.h" +#ifdef HAVE_GDK_PIXBUF #include cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 000000000..65ed027ad --- /dev/null +++ b/include/meson.build @@ -0,0 +1 @@ +configure_file(output: 'config.h', configuration: conf_data) diff --git a/include/buffer_pool.h b/include/pool-buffer.h similarity index 100% rename from include/buffer_pool.h rename to include/pool-buffer.h diff --git a/meson.build b/meson.build index 0c35b0e54..b681f43a8 100644 --- a/meson.build +++ b/meson.build @@ -38,8 +38,10 @@ math = cc.find_library('m') git = find_program('git', required: false) a2x = find_program('a2x', required: false) +conf_data = configuration_data() + if gdk_pixbuf.found() - add_project_arguments('-DWITH_GDK_PIXBUF', language : 'c') + conf_data.set('HAVE_GDK_PIXBUF', true) endif if a2x.found() @@ -92,6 +94,7 @@ add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') sway_inc = include_directories('include') +subdir('include') subdir('protocols') subdir('common') subdir('sway') diff --git a/swaybg/main.c b/swaybg/main.c index 62ddec6c7..f431526cb 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,7 +7,7 @@ #include #include #include -#include "buffer_pool.h" +#include "pool-buffer.h" #include "cairo.h" #include "util.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" @@ -127,7 +128,7 @@ static void render_image(struct swaybg_state *state) { break; } case BACKGROUND_MODE_SOLID_COLOR: - // Should never happen + assert(0); break; } cairo_paint(cairo); @@ -158,7 +159,7 @@ static bool prepare_context(struct swaybg_state *state) { state->context.color = parse_color(state->args->path); return is_valid_color(state->args->path); } -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF GError *err = NULL; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(state->args->path, &err); if (!pixbuf) { @@ -170,17 +171,17 @@ static bool prepare_context(struct swaybg_state *state) { #else state->context.image = cairo_image_surface_create_from_png( state->args->path); -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF if (!state->context.image) { wlr_log(L_ERROR, "Failed to read background image."); return false; } if (cairo_surface_status(state->context.image) != CAIRO_STATUS_SUCCESS) { wlr_log(L_ERROR, "Failed to read background image: %s." -#ifndef WITH_GDK_PIXBUF +#ifndef HAVE_GDK_PIXBUF "\nSway was compiled without gdk_pixbuf support, so only" "\nPNG images can be loaded. This is the likely cause." -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF , cairo_status_to_string( cairo_surface_status(state->context.image))); return false; @@ -256,7 +257,6 @@ int main(int argc, const char **argv) { } args.output_idx = atoi(argv[1]); args.path = argv[2]; - args.mode = atoi(argv[3]); args.mode = BACKGROUND_MODE_STRETCH; if (strcmp(argv[3], "stretch") == 0) { @@ -280,38 +280,20 @@ int main(int argc, const char **argv) { return 1; } - state.display = wl_display_connect(NULL); - if (!state.display) { - wlr_log(L_ERROR, "Failed to create display\n"); - return 1; - } + assert(state.display = wl_display_connect(NULL)); struct wl_registry *registry = wl_display_get_registry(state.display); wl_registry_add_listener(registry, ®istry_listener, &state); wl_display_roundtrip(state.display); + assert(state.compositor && state.layer_shell && state.output && state.shm); - if (!state.compositor) { - wlr_log(L_DEBUG, "wl-compositor not available"); - return 1; - } - if (!state.layer_shell) { - wlr_log(L_ERROR, "layer-shell not available"); - return 1; - } - - state.surface = wl_compositor_create_surface(state.compositor); - if (!state.surface) { - wlr_log(L_ERROR, "failed to create wl_surface"); - return 1; - } + assert(state.surface = wl_compositor_create_surface(state.compositor)); state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( state.layer_shell, state.surface, state.output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); - if (!state.layer_surface) { - wlr_log(L_ERROR, "failed to create zwlr_layer_surface"); - return 1; - } + assert(state.layer_surface); + zwlr_layer_surface_v1_set_size(state.layer_surface, 0, 0); zwlr_layer_surface_v1_set_anchor(state.layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | @@ -320,10 +302,10 @@ int main(int argc, const char **argv) { ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); zwlr_layer_surface_v1_add_listener(state.layer_surface, &layer_surface_listener, &state); + state.run_display = true; wl_surface_commit(state.surface); wl_display_roundtrip(state.display); - state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { // This space intentionally left blank } diff --git a/swaybg/meson.build b/swaybg/meson.build index 7f5d6bd12..5e10f3c71 100644 --- a/swaybg/meson.build +++ b/swaybg/meson.build @@ -1,22 +1,18 @@ -deps = [ - cairo, - jsonc, - math, - pango, - pangocairo, - sway_protos, - wayland_client, -] - -if gdk_pixbuf.found() - deps += [gdk_pixbuf] -endif - executable( - 'swaybg', - 'main.c', - include_directories: [sway_inc], - dependencies: deps, - link_with: [lib_sway_common, lib_sway_client], - install: true + 'swaybg', + 'main.c', + include_directories: [sway_inc], + dependencies: [ + cairo, + gdk_pixbuf, + jsonc, + math, + pango, + pangocairo, + sway_protos, + wayland_client, + wlroots, + ], + link_with: [lib_sway_common, lib_sway_client], + install: true ) From 0c8a64942e087038806b353949c900e03fd764a8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 15:47:22 -0400 Subject: [PATCH 245/522] Add initial layer shell skeleton --- include/sway/layers.h | 24 ++++++++++ include/sway/output.h | 4 ++ include/sway/server.h | 5 ++ protocols/meson.build | 55 +++++++++++++++++----- sway/desktop/layer_shell.c | 96 ++++++++++++++++++++++++++++++++++++++ sway/desktop/output.c | 6 +++ sway/meson.build | 10 ++-- sway/server.c | 6 +++ swaybg/meson.build | 2 +- 9 files changed, 192 insertions(+), 16 deletions(-) create mode 100644 include/sway/layers.h create mode 100644 sway/desktop/layer_shell.c diff --git a/include/sway/layers.h b/include/sway/layers.h new file mode 100644 index 000000000..73fb7cb8b --- /dev/null +++ b/include/sway/layers.h @@ -0,0 +1,24 @@ +#ifndef _SWAY_LAYERS_H +#define _SWAY_LAYERS_H +#include +#include +#include +#include + +struct sway_layer_surface { + struct wlr_layer_surface *layer_surface; + struct wl_list link; + + struct wl_listener destroy; + struct wl_listener map; + struct wl_listener unmap; + struct wl_listener surface_commit; + struct wl_listener output_destroy; + struct wl_listener output_mode; + struct wl_listener output_transform; + + bool configured; + struct wlr_box geo; +}; + +#endif diff --git a/include/sway/output.h b/include/sway/output.h index 95d647052..769d44d03 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -2,6 +2,7 @@ #define _SWAY_OUTPUT_H #include #include +#include #include struct sway_server; @@ -13,6 +14,9 @@ struct sway_output { struct sway_server *server; struct timespec last_frame; + struct wl_list layers[4]; // sway_layer_surface::link + struct wlr_box usable_area; + struct wl_listener frame; struct wl_listener output_destroy; }; diff --git a/include/sway/server.h b/include/sway/server.h index eb7fa2ffd..25eb64fe8 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include // TODO WLR: make Xwayland optional @@ -27,6 +28,9 @@ struct sway_server { struct wl_listener new_output; struct wl_listener output_frame; + struct wlr_layer_shell *layer_shell; + struct wl_listener layer_shell_surface; + struct wlr_xdg_shell_v6 *xdg_shell_v6; struct wl_listener xdg_shell_v6_surface; @@ -46,6 +50,7 @@ void server_run(struct sway_server *server); void handle_new_output(struct wl_listener *listener, void *data); +void handle_layer_shell_surface(struct wl_listener *listener, void *data); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); void handle_xwayland_surface(struct wl_listener *listener, void *data); void handle_wl_shell_surface(struct wl_listener *listener, void *data); diff --git a/protocols/meson.build b/protocols/meson.build index 1fda600e8..3f79e7196 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -14,24 +14,57 @@ wayland_scanner_client = generator( arguments: ['client-header', '@INPUT@', '@OUTPUT@'], ) -protocols = [ +wayland_scanner_server = generator( + wayland_scanner, + output: '@BASENAME@-protocol.h', + arguments: ['server-header', '@INPUT@', '@OUTPUT@'], +) + +client_protocols = [ [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], ['wlr-layer-shell-unstable-v1.xml'] ] -wl_protos_src = [] -wl_protos_headers = [] +server_protocols = [ + ['wlr-layer-shell-unstable-v1.xml'] +] -foreach p : protocols +client_protos_src = [] +client_protos_headers = [] + +server_protos_src = [] +server_protos_headers = [] + +foreach p : client_protocols xml = join_paths(p) - wl_protos_src += wayland_scanner_code.process(xml) - wl_protos_headers += wayland_scanner_client.process(xml) + client_protos_src += wayland_scanner_code.process(xml) + client_protos_headers += wayland_scanner_client.process(xml) endforeach -lib_wl_protos = static_library('wl_protos', wl_protos_src + wl_protos_headers, - dependencies: [wayland_client]) # for the include directory +foreach p : server_protocols + xml = join_paths(p) + server_protos_src += wayland_scanner_code.process(xml) + server_protos_headers += wayland_scanner_server.process(xml) +endforeach -sway_protos = declare_dependency( - link_with: lib_wl_protos, - sources: wl_protos_headers, +lib_client_protos = static_library( + 'client_protos', + client_protos_src + client_protos_headers, + dependencies: [wayland_client] +) # for the include directory + +client_protos = declare_dependency( + link_with: lib_client_protos, + sources: client_protos_headers, +) + +lib_server_protos = static_library( + 'server_protos', + server_protos_src + server_protos_headers, + dependencies: [wayland_client] +) # for the include directory + +server_protos = declare_dependency( + link_with: lib_server_protos, + sources: server_protos_headers, ) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c new file mode 100644 index 000000000..3cf171bd1 --- /dev/null +++ b/sway/desktop/layer_shell.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include "sway/layers.h" +#include "sway/output.h" +#include "sway/server.h" + +static void arrange_layers(struct sway_output *output) { + // TODO +} + +static void handle_output_destroy(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_output_mode(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_output_transform(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_surface_commit(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_destroy(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_map(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_unmap(struct wl_listener *listener, void *data) { + // TODO +} + +void handle_layer_shell_surface(struct wl_listener *listener, void *data) { + struct wlr_layer_surface *layer_surface = data; + struct sway_server *server = + wl_container_of(listener, server, layer_shell_surface); + wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d anchor %d " + "size %dx%d margin %d,%d,%d,%d", + layer_surface->namespace, layer_surface->layer, layer_surface->layer, + layer_surface->client_pending.desired_width, + layer_surface->client_pending.desired_height, + layer_surface->client_pending.margin.top, + layer_surface->client_pending.margin.right, + layer_surface->client_pending.margin.bottom, + layer_surface->client_pending.margin.left); + + struct sway_layer_surface *sway_layer = + calloc(1, sizeof(struct sway_layer_surface)); + if (!sway_layer) { + return; + } + + sway_layer->surface_commit.notify = handle_surface_commit; + wl_signal_add(&layer_surface->surface->events.commit, + &sway_layer->surface_commit); + + sway_layer->output_destroy.notify = handle_output_destroy; + wl_signal_add(&layer_surface->output->events.destroy, + &sway_layer->output_destroy); + + sway_layer->output_mode.notify = handle_output_mode; + wl_signal_add(&layer_surface->output->events.mode, + &sway_layer->output_mode); + + sway_layer->output_transform.notify = handle_output_transform; + wl_signal_add(&layer_surface->output->events.transform, + &sway_layer->output_transform); + + sway_layer->destroy.notify = handle_destroy; + wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); + sway_layer->map.notify = handle_map; + wl_signal_add(&layer_surface->events.map, &sway_layer->map); + sway_layer->unmap.notify = handle_unmap; + wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap); + // TODO: Listen for subsurfaces + + sway_layer->layer_surface = layer_surface; + layer_surface->data = sway_layer; + + struct sway_output *output = layer_surface->output->data; + wl_list_insert(&output->layers[layer_surface->layer], &sway_layer->link); + + // Temporarily set the layer's current state to client_pending + // So that we can easily arrange it + struct wlr_layer_surface_state old_state = layer_surface->current; + layer_surface->current = layer_surface->client_pending; + arrange_layers(output); + layer_surface->current = old_state; +} diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6c990c473..a9aa47a69 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -236,6 +236,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { return; } output->wlr_output = wlr_output; + wlr_output->data = output; output->server = server; if (!wl_list_empty(&wlr_output->modes)) { @@ -250,6 +251,11 @@ void handle_new_output(struct wl_listener *listener, void *data) { return; } + size_t len = sizeof(output->layers) / sizeof(output->layers[0]); + for (size_t i = 0; i < len; ++i) { + wl_list_init(&output->layers[i]); + } + sway_input_manager_configure_xcursor(input_manager); wl_signal_add(&wlr_output->events.frame, &output->frame); diff --git a/sway/meson.build b/sway/meson.build index 26e56ad21..8bddb11ba 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -46,6 +46,7 @@ sway_sources = files( 'ipc-json.c', 'ipc-server.c', 'desktop/output.c', + 'desktop/layer_shell.c', 'desktop/wl_shell.c', 'desktop/xdg_shell_v6.c', 'desktop/xwayland.c', @@ -57,14 +58,15 @@ sway_sources = files( ) sway_deps = [ + jsonc, + libcap, + libinput, + math, pcre, pixman, + server_protos, wayland_server, - jsonc, wlroots, - libcap, - math, - libinput, xkbcommon, ] diff --git a/sway/server.c b/sway/server.c index ca08d7fb0..92f72f13f 100644 --- a/sway/server.c +++ b/sway/server.c @@ -7,6 +7,7 @@ #include #include #include +#include #include // TODO WLR: make Xwayland optional #include @@ -51,6 +52,11 @@ bool server_init(struct sway_server *server) { server->new_output.notify = handle_new_output; wl_signal_add(&server->backend->events.new_output, &server->new_output); + server->layer_shell = wlr_layer_shell_create(server->wl_display); + wl_signal_add(&server->layer_shell->events.new_surface, + &server->layer_shell_surface); + server->layer_shell_surface.notify = handle_layer_shell_surface; + server->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display); wl_signal_add(&server->xdg_shell_v6->events.new_surface, &server->xdg_shell_v6_surface); diff --git a/swaybg/meson.build b/swaybg/meson.build index 5e10f3c71..8704de6d3 100644 --- a/swaybg/meson.build +++ b/swaybg/meson.build @@ -4,12 +4,12 @@ executable( include_directories: [sway_inc], dependencies: [ cairo, + client_protos, gdk_pixbuf, jsonc, math, pango, pangocairo, - sway_protos, wayland_client, wlroots, ], From 68cfa7ef6705c530ff28d9754c5b6cab7b429150 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 16:38:11 -0400 Subject: [PATCH 246/522] Render layer surfaces and respect exclusive zone --- include/sway/layers.h | 3 + include/sway/output.h | 6 +- sway/commands/output.c | 2 +- sway/config/output.c | 31 +++-- sway/desktop/layer_shell.c | 239 +++++++++++++++++++++++++++++++++++-- sway/desktop/output.c | 53 +++++++- sway/desktop/xwayland.c | 4 +- sway/tree/container.c | 4 +- sway/tree/layout.c | 11 +- 9 files changed, 320 insertions(+), 33 deletions(-) diff --git a/include/sway/layers.h b/include/sway/layers.h index 73fb7cb8b..22054be1e 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -21,4 +21,7 @@ struct sway_layer_surface { struct wlr_box geo; }; +struct sway_output; +void arrange_layers(struct sway_output *output); + #endif diff --git a/include/sway/output.h b/include/sway/output.h index 769d44d03..44d009d17 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -4,6 +4,7 @@ #include #include #include +#include struct sway_server; struct sway_container; @@ -18,7 +19,10 @@ struct sway_output { struct wlr_box usable_area; struct wl_listener frame; - struct wl_listener output_destroy; + struct wl_listener destroy; + struct wl_listener mode; + + pid_t bg_pid; }; #endif diff --git a/sway/commands/output.c b/sway/commands/output.c index e747eb4e7..35bc80995 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -188,7 +188,7 @@ static struct cmd_results *cmd_output_background(struct output_config *output, } wordexp_t p; - char *src = join_args(argv + *i - 1, j); + char *src = join_args(argv + *i, j); if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { return cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s).", src); diff --git a/sway/config/output.c b/sway/config/output.c index 69e883f1d..c4168b4fb 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -1,9 +1,12 @@ #define _XOPEN_SOURCE 700 +#include #include #include -#include +#include +#include #include #include +#include #include "sway/config.h" #include "sway/output.h" #include "log.h" @@ -107,6 +110,16 @@ static void set_mode(struct wlr_output *output, int width, int height, } } +void terminate_swaybg(pid_t pid) { + int ret = kill(pid, SIGTERM); + if (ret != 0) { + wlr_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid); + } else { + int status; + waitpid(pid, &status, 0); + } +} + void apply_output_config(struct output_config *oc, swayc_t *output) { assert(output->type == C_OUTPUT); @@ -160,12 +173,12 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { } if (oc && oc->background) { - // TODO swaybg - /*if (output->bg_pid != 0) { - terminate_swaybg(output->bg_pid); + if (output->sway_output->bg_pid != 0) { + terminate_swaybg(output->sway_output->bg_pid); } - wlr_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); + wlr_log(L_DEBUG, "Setting background for output %d to %s", + output_i, oc->background); size_t bufsize = 12; char output_id[bufsize]; @@ -173,17 +186,17 @@ 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, NULL, }; - output->bg_pid = fork(); - if (output->bg_pid == 0) { + output->sway_output->bg_pid = fork(); + if (output->sway_output->bg_pid == 0) { execvp(cmd[0], cmd); - }*/ + } } } diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 3cf171bd1..a2506d211 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -1,40 +1,261 @@ +#include #include +#include #include +#include +#include +#include #include #include "sway/layers.h" +#include "sway/layout.h" #include "sway/output.h" #include "sway/server.h" -static void arrange_layers(struct sway_output *output) { - // TODO +static void apply_exclusive(struct wlr_box *usable_area, + uint32_t anchor, int32_t exclusive, + int32_t margin_top, int32_t margin_right, + int32_t margin_bottom, int32_t margin_left) { + if (exclusive <= 0) { + return; + } + struct { + uint32_t anchors; + int *positive_axis; + int *negative_axis; + int margin; + } edges[] = { + { + .anchors = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, + .positive_axis = &usable_area->y, + .negative_axis = &usable_area->height, + .margin = margin_top, + }, + { + .anchors = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .positive_axis = NULL, + .negative_axis = &usable_area->height, + .margin = margin_bottom, + }, + { + .anchors = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .positive_axis = &usable_area->x, + .negative_axis = &usable_area->width, + .margin = margin_left, + }, + { + .anchors = + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .positive_axis = NULL, + .negative_axis = &usable_area->width, + .margin = margin_right, + }, + }; + for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { + if ((anchor & edges[i].anchors) == edges[i].anchors) { + if (edges[i].positive_axis) { + *edges[i].positive_axis += exclusive + edges[i].margin; + } + if (edges[i].negative_axis) { + *edges[i].negative_axis -= exclusive + edges[i].margin; + } + } + } +} + +static void arrange_layer(struct sway_output *output, struct wl_list *list, + struct wlr_box *usable_area, bool exclusive) { + struct sway_layer_surface *sway_layer; + struct wlr_box full_area = { 0 }; + wlr_output_effective_resolution(output->wlr_output, + &full_area.width, &full_area.height); + wl_list_for_each(sway_layer, list, link) { + struct wlr_layer_surface *layer = sway_layer->layer_surface; + struct wlr_layer_surface_state *state = &layer->current; + if (exclusive != (state->exclusive_zone > 0)) { + continue; + } + struct wlr_box bounds; + if (state->exclusive_zone == -1) { + bounds = full_area; + } else { + bounds = *usable_area; + } + struct wlr_box box = { + .width = state->desired_width, + .height = state->desired_height + }; + // Horizontal axis + const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + if ((state->anchor & both_horiz) && box.width == 0) { + box.x = bounds.x; + box.width = bounds.width; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + box.x = bounds.x; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + box.x = bounds.x + (bounds.width - box.width); + } else { + box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); + } + // Vertical axis + const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + if ((state->anchor & both_vert) && box.height == 0) { + box.y = bounds.y; + box.height = bounds.height; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + box.y = bounds.y; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + box.y = bounds.y + (bounds.height - box.height); + } else { + box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); + } + // Margin + if ((state->anchor & both_horiz) == both_horiz) { + box.x += state->margin.left; + box.width -= state->margin.left + state->margin.right; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + box.x += state->margin.left; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + box.x -= state->margin.right; + } + if ((state->anchor & both_vert) == both_vert) { + box.y += state->margin.top; + box.height -= state->margin.top + state->margin.bottom; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + box.y += state->margin.top; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + box.y -= state->margin.bottom; + } + if (box.width < 0 || box.height < 0) { + // TODO: Bubble up a protocol error? + wlr_layer_surface_close(layer); + continue; + } + // Apply + sway_layer->geo = box; + apply_exclusive(usable_area, state->anchor, state->exclusive_zone, + state->margin.top, state->margin.right, + state->margin.bottom, state->margin.left); + wlr_layer_surface_configure(layer, box.width, box.height); + } +} + +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], + &usable_area, true); + arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + &usable_area, true); + arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + &usable_area, true); + arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + &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 non-exlusive surfaces from top->bottom + usable_area.x = usable_area.y = 0; + wlr_output_effective_resolution(output->wlr_output, + &usable_area.width, &usable_area.height); + arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + &usable_area, false); + arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + &usable_area, false); + arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + &usable_area, false); + arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + &usable_area, false); } static void handle_output_destroy(struct wl_listener *listener, void *data) { - // TODO + struct sway_layer_surface *sway_layer = + wl_container_of(listener, sway_layer, output_destroy); + sway_layer->layer_surface->output = NULL; + wl_list_remove(&sway_layer->output_destroy.link); + wl_list_remove(&sway_layer->output_mode.link); + wlr_layer_surface_close(sway_layer->layer_surface); } static void handle_output_mode(struct wl_listener *listener, void *data) { - // TODO + struct wlr_output *output = data; + arrange_layers((struct sway_output *)output->data); } static void handle_output_transform(struct wl_listener *listener, void *data) { - // TODO + struct wlr_output *output = data; + arrange_layers((struct sway_output *)output->data); } static void handle_surface_commit(struct wl_listener *listener, void *data) { - // TODO + struct sway_layer_surface *layer = + wl_container_of(listener, layer, surface_commit); + struct wlr_layer_surface *layer_surface = layer->layer_surface; + struct wlr_output *wlr_output = layer_surface->output; + if (wlr_output != NULL) { + struct sway_output *output = wlr_output->data; + struct wlr_box old_geo = layer->geo; + arrange_layers(output); + if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { + // TODO DAMAGE apply whole surface from previous and new geos + } else { + // TODO DAMAGE from surface damage + } + } +} + +static void unmap(struct wlr_layer_surface *layer_surface) { + // TODO DAMAGE } static void handle_destroy(struct wl_listener *listener, void *data) { - // TODO + struct sway_layer_surface *sway_layer = wl_container_of( + listener, sway_layer, destroy); + if (sway_layer->layer_surface->mapped) { + unmap(sway_layer->layer_surface); + } + wl_list_remove(&sway_layer->link); + wl_list_remove(&sway_layer->destroy.link); + wl_list_remove(&sway_layer->map.link); + wl_list_remove(&sway_layer->unmap.link); + wl_list_remove(&sway_layer->surface_commit.link); + wl_list_remove(&sway_layer->output_destroy.link); + wl_list_remove(&sway_layer->output_mode.link); + wl_list_remove(&sway_layer->output_transform.link); + struct sway_output *output = sway_layer->layer_surface->output->data; + arrange_layers(output); + free(sway_layer); } static void handle_map(struct wl_listener *listener, void *data) { - // TODO + // TODO DAMAGE } static void handle_unmap(struct wl_listener *listener, void *data) { - // TODO + struct sway_layer_surface *sway_layer = wl_container_of( + listener, sway_layer, unmap); + unmap(sway_layer->layer_surface); } void handle_layer_shell_surface(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a9aa47a69..59f79a81b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -4,14 +4,17 @@ #include #include #include +#include #include #include +#include #include #include #include "log.h" #include "sway/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" +#include "sway/layers.h" #include "sway/layout.h" #include "sway/output.h" #include "sway/server.h" @@ -177,6 +180,20 @@ static void output_frame_view(swayc_t *view, void *data) { } } +static void render_layer(struct sway_output *output, + const struct wlr_box *output_layout_box, + struct timespec *when, + struct wl_list *layer) { + struct sway_layer_surface *sway_layer; + wl_list_for_each(sway_layer, layer, link) { + struct wlr_layer_surface *layer = sway_layer->layer_surface; + render_surface(layer->surface, output->wlr_output, when, + sway_layer->geo.x + output_layout_box->x, + sway_layer->geo.y + output_layout_box->y, 0); + wlr_surface_send_frame_done(layer->surface, when); + } +} + static void output_frame_notify(struct wl_listener *listener, void *data) { struct sway_output *soutput = wl_container_of(listener, soutput, frame); struct wlr_output *wlr_output = data; @@ -189,6 +206,18 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { wlr_output_make_current(wlr_output, &buffer_age); wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + struct wlr_output_layout *layout = root_container.sway_root->output_layout; + const struct wlr_box *output_box = wlr_output_layout_get_box( + layout, wlr_output); + + render_layer(soutput, output_box, &now, + &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); + render_layer(soutput, output_box, &now, + &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 ? @@ -210,22 +239,32 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } } + // TODO: Consider revising this when fullscreen windows are supported + render_layer(soutput, output_box, &now, + &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); + render_layer(soutput, output_box, &now, + &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); + wlr_renderer_end(server->renderer); wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); soutput->last_frame = now; } static void handle_output_destroy(struct wl_listener *listener, void *data) { - struct sway_output *output = wl_container_of(listener, output, output_destroy); + struct sway_output *output = wl_container_of(listener, output, destroy); struct wlr_output *wlr_output = data; wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); destroy_output(output->swayc); } +static void handle_output_mode(struct wl_listener *listener, void *data) { + struct sway_output *output = wl_container_of(listener, output, mode); + arrange_layers(output); + arrange_windows(output->swayc, -1, -1); +} + void handle_new_output(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; @@ -260,9 +299,11 @@ void handle_new_output(struct wl_listener *listener, void *data) { wl_signal_add(&wlr_output->events.frame, &output->frame); output->frame.notify = output_frame_notify; + wl_signal_add(&wlr_output->events.destroy, &output->destroy); + output->destroy.notify = handle_output_destroy; + wl_signal_add(&wlr_output->events.mode, &output->mode); + output->mode.notify = handle_output_mode; - wl_signal_add(&wlr_output->events.destroy, &output->output_destroy); - output->output_destroy.notify = handle_output_destroy; - + arrange_layers(output); arrange_windows(&root_container, -1, -1); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 6b5e03f9c..f9b5242b6 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -84,7 +84,7 @@ static void set_activated(struct sway_view *view, bool activated) { wlr_xwayland_surface_activate(surface, activated); } -static void close(struct sway_view *view) { +static void close_view(struct sway_view *view) { if (!assert_xwayland(view)) { return; } @@ -203,7 +203,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->iface.close = close_view; sway_view->wlr_xwayland_surface = xsurface; sway_view->sway_xwayland_surface = sway_surface; sway_view->surface = xsurface->surface; diff --git a/sway/tree/container.c b/sway/tree/container.c index 705221d7f..bbafe9ec1 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -254,7 +254,9 @@ swayc_t *destroy_output(swayc_t *output) { } } - wl_list_remove(&output->sway_output->output_destroy.link); + wl_list_remove(&output->sway_output->frame.link); + wl_list_remove(&output->sway_output->destroy.link); + wl_list_remove(&output->sway_output->mode.link); wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); free_swayc(output); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 3d04a1a74..de9e7b586 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -204,10 +204,13 @@ void arrange_windows(swayc_t *container, double width, double height) { case C_WORKSPACE: { swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); - container->width = output->width; - container->height = output->height; - container->x = x; - container->y = y; + 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); + container->width = area->width; + container->height = area->height; + container->x = x = area->x; + container->y = y = area->y; wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", container->name, container->x, container->y); } From 8d6bce02afc656bf792815ed68121f4e614cd175 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 18:10:43 -0400 Subject: [PATCH 247/522] Address review feedback --- include/sway/output.h | 2 +- sway/config/output.c | 2 +- sway/desktop/layer_shell.c | 11 +++++++---- sway/desktop/output.c | 36 +++++++++++++++++++----------------- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 44d009d17..f899230f9 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -1,10 +1,10 @@ #ifndef _SWAY_OUTPUT_H #define _SWAY_OUTPUT_H #include +#include #include #include #include -#include struct sway_server; struct sway_container; diff --git a/sway/config/output.c b/sway/config/output.c index c4168b4fb..9e2118614 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -4,9 +4,9 @@ #include #include #include +#include #include #include -#include #include "sway/config.h" #include "sway/output.h" #include "log.h" diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index a2506d211..bd62f84a4 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -192,9 +192,10 @@ void arrange_layers(struct sway_output *output) { static void handle_output_destroy(struct wl_listener *listener, void *data) { struct sway_layer_surface *sway_layer = wl_container_of(listener, sway_layer, output_destroy); - sway_layer->layer_surface->output = NULL; wl_list_remove(&sway_layer->output_destroy.link); wl_list_remove(&sway_layer->output_mode.link); + wl_list_remove(&sway_layer->output_transform.link); + sway_layer->layer_surface->output = NULL; wlr_layer_surface_close(sway_layer->layer_surface); } @@ -240,9 +241,11 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&sway_layer->map.link); wl_list_remove(&sway_layer->unmap.link); wl_list_remove(&sway_layer->surface_commit.link); - wl_list_remove(&sway_layer->output_destroy.link); - wl_list_remove(&sway_layer->output_mode.link); - wl_list_remove(&sway_layer->output_transform.link); + if (sway_layer->layer_surface->output != NULL) { + wl_list_remove(&sway_layer->output_destroy.link); + wl_list_remove(&sway_layer->output_mode.link); + wl_list_remove(&sway_layer->output_transform.link); + } struct sway_output *output = sway_layer->layer_surface->output->data; arrange_layers(output); free(sway_layer); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 59f79a81b..9e7fbcc68 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -81,9 +81,7 @@ static void render_surface(struct wlr_surface *surface, rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); render_surface(subsurface->surface, wlr_output, when, - lx + sx, - ly + sy, - rotation); + lx + sx, ly + sy, rotation); } } @@ -142,9 +140,15 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, } } +struct render_data { + struct sway_output *output; + struct timespec *now; +}; static void output_frame_view(swayc_t *view, void *data) { - struct sway_output *output = data; + struct render_data *rdata = data; + struct sway_output *output = rdata->output; + struct timespec *now = rdata->now; struct wlr_output *wlr_output = output->wlr_output; struct sway_view *sway_view = view->sway_view; struct wlr_surface *surface = sway_view->surface; @@ -157,23 +161,18 @@ static void output_frame_view(swayc_t *view, void *data) { case SWAY_XDG_SHELL_V6_VIEW: { int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; - render_surface(surface, wlr_output, &output->last_frame, - view->x - window_offset_x, - view->y - window_offset_y, - 0); + render_surface(surface, wlr_output, now, + view->x - window_offset_x, view->y - window_offset_y, 0); render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, - &output->last_frame, - view->x - window_offset_x, view->y - window_offset_y, - 0); + now, view->x - window_offset_x, view->y - window_offset_y, 0); break; } case SWAY_WL_SHELL_VIEW: render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, - &output->last_frame, view->x, view->y, 0, false); + now, view->x, view->y, 0, false); break; case SWAY_XWAYLAND_VIEW: - render_surface(surface, wlr_output, &output->last_frame, view->x, - view->y, 0); + render_surface(surface, wlr_output, now, view->x, view->y, 0); break; default: break; @@ -224,7 +223,11 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { focus : swayc_parent_by_type(focus, C_WORKSPACE)); - swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); + struct render_data rdata = { + .output = soutput, + .now = &now, + }; + swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, &rdata); // render unmanaged views on top struct sway_view *view; @@ -246,8 +249,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); wlr_renderer_end(server->renderer); - wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); - + wlr_output_swap_buffers(wlr_output, &now, NULL); soutput->last_frame = now; } From 82da2b5990ca248a7db9dec0461a5d81a0c21a81 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 23:38:30 -0400 Subject: [PATCH 248/522] add xdg-protocol header --- protocols/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/meson.build b/protocols/meson.build index 3f79e7196..0887cf866 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -26,6 +26,7 @@ client_protocols = [ ] server_protocols = [ + [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], ['wlr-layer-shell-unstable-v1.xml'] ] From 874f009866abaf8ca43ed4cd88a69d22a3fbfc5a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 12:15:31 -0400 Subject: [PATCH 249/522] move tree includes to their own directory --- include/sway/config.h | 4 +- include/sway/criteria.h | 2 +- include/sway/ipc-json.h | 2 +- include/sway/ipc-server.h | 4 +- include/sway/{ => tree}/container.h | 75 ++++++++--------------------- include/sway/{ => tree}/layout.h | 12 ++++- include/sway/{ => tree}/view.h | 4 -- include/sway/{ => tree}/workspace.h | 8 ++- 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 +- 29 files changed, 89 insertions(+), 110 deletions(-) rename include/sway/{ => tree}/container.h (61%) rename include/sway/{ => tree}/layout.h (88%) rename include/sway/{ => tree}/view.h (96%) rename include/sway/{ => tree}/workspace.h (93%) diff --git a/include/sway/config.h b/include/sway/config.h index 48a8b0abb..48ebba3bf 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/criteria.h b/include/sway/criteria.h index 9b4b4befa..431cfa3a5 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 eef5a018c..76b7d45b2 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 bcf1c4338..db690b6ec 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/container.h b/include/sway/tree/container.h similarity index 61% rename from include/sway/container.h rename to include/sway/tree/container.h index f200a1a2e..5a2ae3499 100644 --- a/include/sway/container.h +++ b/include/sway/tree/container.h @@ -20,60 +20,43 @@ struct sway_seat; * 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_ROOT, + C_OUTPUT, + C_WORKSPACE, + C_CONTAINER, + C_VIEW, C_TYPES, }; -/** - * Different ways to arrange a container. - */ enum swayc_layouts { - L_NONE, /**< Used for containers that have no layout (views, root) */ + L_NONE, 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, + L_FLOATING, // Keep last L_LAYOUTS, }; enum swayc_border_types { - B_NONE, /**< No border */ - B_PIXEL, /**< 1px border */ - B_NORMAL, /**< Normal border with title bar */ + B_NONE, + B_PIXEL, + B_NORMAL, }; 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 + struct sway_root *sway_root; + struct sway_output *sway_output; + struct sway_view *sway_view; }; /** @@ -89,38 +72,17 @@ struct sway_container { 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). - */ + // TODO convert to layout coordinates double x, y; - /** - * Width and height of this container, without borders or gaps. - */ + // does not include 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; + list_t *marks; // list of char* struct { struct wl_signal destroy; @@ -130,8 +92,11 @@ struct sway_container { 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); @@ -145,10 +110,12 @@ swayc_t *next_view_sibling(struct sway_seat *seat); */ 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. */ diff --git a/include/sway/layout.h b/include/sway/tree/layout.h similarity index 88% rename from include/sway/layout.h rename to include/sway/tree/layout.h index e82c4442a..39b7fb24c 100644 --- a/include/sway/layout.h +++ b/include/sway/tree/layout.h @@ -2,7 +2,7 @@ #define _SWAY_LAYOUT_H #include -#include "sway/container.h" +#include "sway/tree/container.h" enum movement_direction { MOVE_LEFT, @@ -31,12 +31,20 @@ struct sway_root { }; 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); + +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); diff --git a/include/sway/view.h b/include/sway/tree/view.h similarity index 96% rename from include/sway/view.h rename to include/sway/tree/view.h index b28862113..e5f53f4e6 100644 --- a/include/sway/view.h +++ b/include/sway/tree/view.h @@ -62,10 +62,6 @@ enum sway_view_prop { 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; diff --git a/include/sway/workspace.h b/include/sway/tree/workspace.h similarity index 93% rename from include/sway/workspace.h rename to include/sway/tree/workspace.h index fee54255c..c8ce40d15 100644 --- a/include/sway/workspace.h +++ b/include/sway/tree/workspace.h @@ -1,20 +1,26 @@ #ifndef _SWAY_WORKSPACE_H #define _SWAY_WORKSPACE_H -#include "sway/container.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/sway/commands/exec_always.c b/sway/commands/exec_always.c index 61870c513..954950e76 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 f1a8078f7..18e9e0bf5 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 f408ce2a9..c0faed7ab 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 b0fc5d664..2b193136d 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 d54d40db6..8cef789ba 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 fa8913984..8751dffea 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 213e7680a..0b29735a6 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 2eee331c1..b8b581ed3 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 bd62f84a4..137b3260d 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 9e7fbcc68..debda396f 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 0356aa811..bb97fad43 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 7bc171499..25ffacbb5 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 f9b5242b6..7f66f746f 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 8a0d1df59..c0e142653 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 648e79143..56b397664 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 977f1ecbc..ebd5e43aa 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 f2f24be35..31bf617b8 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 bbafe9ec1..805d5644d 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 de9e7b586..5a15f3a2e 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 9499adca7..20e657a26 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 861fda4dd..3da3fde6a 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" From 83d09cf5945ba10a703dc5cc977a6d2814f0fd64 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 14:31:10 -0400 Subject: [PATCH 250/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 48ebba3bf..e9910be40 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 431cfa3a5..ec256ddbd 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 eab7dc90f..c6c73dbab 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 1d55bec7a..e43e6fd47 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 76b7d45b2..3d2fdc4fb 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 db690b6ec..d73006dc6 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 5a2ae3499..5def5e713 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 39b7fb24c..8bb9e075c 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 c8ce40d15..d73b29c1c 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 27c2c72eb..d421a03f1 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); From 941ca5c8fd289b6ca0178f65b697aa36fb4e71d3 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 15:39:07 -0400 Subject: [PATCH 251/522] Maximize xdg shell surfaces on creation Makes them look better yo In the future we might want to only do this for tiled windows, and let floating windows do their own thing. --- sway/desktop/xdg_shell_v6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 7bc171499..18e7d3993 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -102,6 +102,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); wlr_xdg_surface_v6_ping(xdg_surface); + wlr_xdg_toplevel_v6_set_maximized(xdg_surface, true); struct sway_xdg_surface_v6 *sway_surface = calloc(1, sizeof(struct sway_xdg_surface_v6)); From b90099b4b7df8068446c658ab99b58ff83648954 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 16:17:55 -0400 Subject: [PATCH 252/522] rename container functions --- include/sway/config.h | 8 +- include/sway/input/seat.h | 2 +- include/sway/tree/container.h | 76 +++++++------- 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, 290 insertions(+), 282 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index e9910be40..7fdd0be09 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 e43e6fd47..496bfd5d0 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 5def5e713..0dfed4555 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, +// TODO only one container create function and pass the type? +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 *sway_container_view_create( + struct sway_container *sibling, struct sway_view *sway_view); + +struct sway_container *sway_container_output_destroy( + struct sway_container *output); + +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); -// TODO only one container create function and pass the type? -struct sway_container *new_output(struct sway_output *sway_output); - -struct sway_container *new_workspace(struct sway_container *output, - const char *name); - -struct sway_container *new_view(struct sway_container *sibling, - struct sway_view *sway_view); - -struct sway_container *destroy_output(struct sway_container *output); -struct sway_container *destroy_view(struct sway_container *view); - +// 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 8bb9e075c..f73b3880f 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 18e9e0bf5..64b059047 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 c0faed7ab..f67747679 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 2b193136d..e10334e26 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 35bc80995..f7e3372ce 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 8751dffea..8b7139a9f 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 9e2118614..5763bd21a 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 b8b581ed3..70f8e3057 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 debda396f..3e7d85090 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 bb97fad43..bf41d7bfa 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 25ffacbb5..6b50d470c 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 7f66f746f..96edab51d 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 c0e142653..a0e4b9beb 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 56b397664..f03a03b45 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 ebd5e43aa..7caa2457a 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 156de3807..50d0bcf30 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 805d5644d..d31966b33 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 5a15f3a2e..068fb39c4 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 3da3fde6a..32e828453 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 93d1219c4..f9df0d10e 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); } From eca029f218fbb54ddf7316845be5d296e834358e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 17:06:29 -0400 Subject: [PATCH 253/522] more renaming things --- include/sway/tree/container.h | 21 ++++++------- include/sway/tree/layout.h | 16 +++++----- sway/commands/layout.c | 16 +++++----- sway/commands/reload.c | 2 +- sway/commands/workspace.c | 6 ++-- sway/config/output.c | 2 +- sway/desktop/layer_shell.c | 2 +- sway/desktop/output.c | 12 ++++---- sway/desktop/wl_shell.c | 8 ++--- sway/desktop/xdg_shell_v6.c | 8 ++--- sway/desktop/xwayland.c | 22 ++++++------- sway/input/seat.c | 2 +- sway/tree/container.c | 58 +++++++++++++++++------------------ sway/tree/layout.c | 34 ++++++++++---------- sway/tree/workspace.c | 22 ++++++------- swaybar/ipc.c | 2 +- 16 files changed, 115 insertions(+), 118 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 0dfed4555..572dd8e36 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -88,41 +88,38 @@ struct sway_container { }; // TODO only one container create function and pass the type? -struct sway_container *sway_container_output_create( +struct sway_container *container_output_create( struct sway_output *sway_output); -struct sway_container *sway_container_workspace_create( +struct sway_container *container_workspace_create( struct sway_container *output, const char *name); -struct sway_container *sway_container_view_create( +struct sway_container *container_view_create( struct sway_container *sibling, struct sway_view *sway_view); -struct sway_container *sway_container_output_destroy( +struct sway_container *container_output_destroy( struct sway_container *output); -struct sway_container *sway_container_view_destroy(struct sway_container *view); +struct sway_container *container_view_destroy(struct sway_container *view); -struct sway_container *sway_container_set_layout( +struct sway_container *container_set_layout( struct sway_container *container, enum sway_container_layout layout); -void sway_container_descendents(struct sway_container *root, +void 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 *sway_container_find(struct sway_container *container, +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 *sway_container_parent(struct sway_container *container, +struct sway_container *container_parent(struct sway_container *container, enum sway_container_type type); /** diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index f73b3880f..6980ec9ee 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -30,23 +30,23 @@ struct sway_root { } events; }; -void init_layout(void); +void layout_init(void); -void add_child(struct sway_container *parent, struct sway_container *child); +void container_add_child(struct sway_container *parent, struct sway_container *child); -struct sway_container *add_sibling(struct sway_container *parent, +struct sway_container *container_add_sibling(struct sway_container *parent, struct sway_container *child); -struct sway_container *remove_child(struct sway_container *child); +struct sway_container *container_remove_child(struct sway_container *child); -enum sway_container_layout default_layout(struct sway_container *output); +enum sway_container_layout container_get_default_layout(struct sway_container *output); -void sort_workspaces(struct sway_container *output); +void container_sort_workspaces(struct sway_container *output); -void arrange_windows(struct sway_container *container, +void container_arrange_windows(struct sway_container *container, double width, double height); -struct sway_container *get_swayc_in_direction(struct sway_container +struct sway_container *container_get_in_direction(struct sway_container *container, struct sway_seat *seat, enum movement_direction dir); #endif diff --git a/sway/commands/layout.c b/sway/commands/layout.c index e10334e26..e9cfeb8f1 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -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) { - struct sway_container *output = sway_container_parent(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,20 +37,20 @@ 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); } } } - arrange_windows(parent, parent->width, parent->height); + container_arrange_windows(parent, parent->width, parent->height); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 8cef789ba..83ecd75bb 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -13,6 +13,6 @@ struct cmd_results *cmd_reload(int argc, char **argv) { /* load_swaybars(); -- for when it's implemented */ - arrange_windows(&root_container, -1, -1); + container_arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 8b7139a9f..8f39e5fc8 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -23,9 +23,9 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (current_container->type == C_WORKSPACE) { old_workspace = current_container; } else { - old_workspace = sway_container_parent(current_container, C_WORKSPACE); + old_workspace = container_parent(current_container, C_WORKSPACE); } - old_output = sway_container_parent(current_container, C_OUTPUT); + old_output = container_parent(current_container, C_OUTPUT); } for (int i = 0; i < argc; ++i) { @@ -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 = sway_container_parent(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/output.c b/sway/config/output.c index 5763bd21a..7fc797393 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -127,7 +127,7 @@ void apply_output_config(struct output_config *oc, struct sway_container *output if (oc && oc->enabled == 0) { wlr_output_layout_remove(root_container.sway_root->output_layout, wlr_output); - sway_container_output_destroy(output); + container_output_destroy(output); return; } diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 137b3260d..4bfd1c45b 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -172,7 +172,7 @@ void arrange_layers(struct sway_output *output) { if (memcmp(&usable_area_before, &usable_area, sizeof(struct wlr_box)) != 0) { wlr_log(L_DEBUG, "arrange"); - arrange_windows(output->swayc, -1, -1); + container_arrange_windows(output->swayc, -1, -1); } // Arrange non-exlusive surfaces from top->bottom diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 3e7d85090..fa1b0680e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -221,13 +221,13 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct sway_container *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : - sway_container_parent(focus, C_WORKSPACE)); + container_parent(focus, C_WORKSPACE)); struct render_data rdata = { .output = soutput, .now = &now, }; - sway_container_descendents(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; @@ -258,13 +258,13 @@ 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); - sway_container_output_destroy(output->swayc); + container_output_destroy(output->swayc); } static void handle_output_mode(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, mode); arrange_layers(output); - arrange_windows(output->swayc, -1, -1); + container_arrange_windows(output->swayc, -1, -1); } void handle_new_output(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 = sway_container_output_create(output); + output->swayc = container_output_create(output); if (!output->swayc) { free(output); return; @@ -307,5 +307,5 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->mode.notify = handle_output_mode; arrange_layers(output); - arrange_windows(&root_container, -1, -1); + container_arrange_windows(&root_container, -1, -1); } diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index bf41d7bfa..ac1c7f262 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -74,10 +74,10 @@ 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 = sway_container_view_destroy(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); + container_arrange_windows(parent, -1, -1); } void handle_wl_shell_surface(struct wl_listener *listener, void *data) { @@ -133,9 +133,9 @@ void handle_wl_shell_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 = sway_container_view_create(focus, sway_view); + struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; - arrange_windows(cont->parent, -1, -1); + container_arrange_windows(cont->parent, -1, -1); 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 6b50d470c..616cb88f1 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -83,10 +83,10 @@ 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 = sway_container_view_destroy(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); + container_arrange_windows(parent, -1, -1); } void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { @@ -137,10 +137,10 @@ void handle_xdg_shell_v6_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 = sway_container_view_create(focus, sway_view); + struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; - arrange_windows(cont->parent, -1, -1); + container_arrange_windows(cont->parent, -1, -1); sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 96edab51d..fa1054f20 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; } - struct sway_container *output = sway_container_parent(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; } - struct sway_container *root = sway_container_parent(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,9 +114,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } } - struct sway_container *parent = sway_container_view_destroy(sway_surface->view->swayc); + struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); if (parent) { - arrange_windows(parent, -1, -1); + container_arrange_windows(parent, -1, -1); } free(sway_surface->view); @@ -132,9 +132,9 @@ static void handle_unmap_notify(struct wl_listener *listener, void *data) { } // take it out of the tree - struct sway_container *parent = sway_container_view_destroy(sway_surface->view->swayc); + struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); if (parent) { - arrange_windows(parent, -1, -1); + container_arrange_windows(parent, -1, -1); } sway_surface->view->swayc = NULL; @@ -155,15 +155,15 @@ 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; - sway_container_view_destroy(view->swayc); + container_view_destroy(view->swayc); struct sway_container *parent = root_container.children->items[0]; parent = parent->children->items[0]; // workspace - struct sway_container *cont = sway_container_view_create(parent, view); + struct sway_container *cont = container_view_create(parent, view); view->swayc = cont; - arrange_windows(cont->parent, -1, -1); + container_arrange_windows(cont->parent, -1, -1); sway_input_manager_set_focus(input_manager, cont); } } @@ -239,9 +239,9 @@ 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 = sway_container_view_create(focus, sway_view); + struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; - arrange_windows(cont->parent, -1, -1); + container_arrange_windows(cont->parent, -1, -1); sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/input/seat.c b/sway/input/seat.c index f03a03b45..8e2189de2 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -365,7 +365,7 @@ struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, return focus; } - return sway_container_parent(focus, type); + return container_parent(focus, type); } void sway_seat_set_config(struct sway_seat *seat, diff --git a/sway/tree/container.c b/sway/tree/container.c index d31966b33..b41626e19 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -67,7 +67,7 @@ static void free_swayc(struct sway_container *cont) { if (cont->children) { // remove children until there are no more, free_swayc calls - // remove_child, which removes child from this container + // container_remove_child, which removes child from this container while (cont->children->length) { free_swayc(cont->children->items[0]); } @@ -78,7 +78,7 @@ static void free_swayc(struct sway_container *cont) { list_free(cont->marks); } if (cont->parent) { - remove_child(cont); + container_remove_child(cont); } if (cont->name) { free(cont->name); @@ -86,7 +86,7 @@ static void free_swayc(struct sway_container *cont) { free(cont); } -struct sway_container *sway_container_output_create(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); @@ -131,12 +131,12 @@ struct sway_container *sway_container_output_create(struct sway_output *sway_out 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); - struct sway_container *ws = sway_container_workspace_create(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) { @@ -150,8 +150,8 @@ struct sway_container *sway_container_output_create(struct sway_output *sway_out return 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")) { +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); @@ -163,17 +163,17 @@ struct sway_container *sway_container_workspace_create(struct sway_container *ou 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; } -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")) { +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); @@ -188,17 +188,17 @@ struct sway_container *sway_container_view_create(struct sway_container *sibling 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; } -struct sway_container *sway_container_output_destroy(struct sway_container *output) { - if (!sway_assert(output, "null output passed to sway_container_output_destroy")) { +struct sway_container *container_output_destroy(struct sway_container *output) { + if (!sway_assert(output, "null output passed to container_output_destroy")) { return NULL; } @@ -211,11 +211,11 @@ struct sway_container *sway_container_output_destroy(struct sway_container *outp // Move workspace from this output to another output while (output->children->length) { struct sway_container *child = output->children->items[0]; - remove_child(child); - add_child(root_container.children->items[p], child); + 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]); + container_arrange_windows(root_container.children->items[p], -1, -1); } } @@ -229,7 +229,7 @@ struct sway_container *sway_container_output_destroy(struct sway_container *outp return &root_container; } -struct sway_container *sway_container_view_destroy(struct sway_container *view) { +struct sway_container *container_view_destroy(struct sway_container *view) { if (!view) { return NULL; } @@ -246,7 +246,7 @@ struct sway_container *sway_container_view_destroy(struct sway_container *view) return parent; } -struct sway_container *swayc_change_layout(struct sway_container *container, enum sway_container_layout layout) { +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) { @@ -258,7 +258,7 @@ struct sway_container *swayc_change_layout(struct sway_container *container, enu return container; } -void sway_container_descendents(struct sway_container *root, enum sway_container_type type, +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]; @@ -266,12 +266,12 @@ void sway_container_descendents(struct sway_container *root, enum sway_container func(item, data); } if (item->children && item->children->length) { - sway_container_descendents(item, type, func, data); + container_descendents(item, type, func, data); } } } -struct sway_container *sway_container_find(struct sway_container *container, +struct sway_container *container_find(struct sway_container *container, bool (*test)(struct sway_container *view, void *data), void *data) { if (!container->children) { return NULL; @@ -282,7 +282,7 @@ struct sway_container *sway_container_find(struct sway_container *container, if (test(child, data)) { return child; } else { - struct sway_container *res = sway_container_find(child, test, data); + struct sway_container *res = container_find(child, test, data); if (res) { return res; } @@ -291,7 +291,7 @@ struct sway_container *sway_container_find(struct sway_container *container, return NULL; } -struct sway_container *sway_container_parent(struct sway_container *container, enum sway_container_type type) { +struct sway_container *container_parent(struct sway_container *container, enum sway_container_type type) { if (!sway_assert(container, "container is NULL")) { return NULL; } @@ -341,7 +341,7 @@ struct sway_container *sway_container_at(struct sway_container *parent, double l list_del(queue, 0); if (swayc->type == C_VIEW) { struct sway_view *sview = swayc->sway_view; - struct sway_container *soutput = sway_container_parent(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, diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 068fb39c4..07534620d 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -40,7 +40,7 @@ static void output_layout_change_notify(struct wl_listener *listener, void *data output_container->height = output_box->height; } - arrange_windows(&root_container, -1, -1); + container_arrange_windows(&root_container, -1, -1); } void init_layout(void) { @@ -79,7 +79,7 @@ static int index_child(const struct sway_container *child) { return i; } -struct sway_container *add_sibling(struct sway_container *fixed, struct sway_container *active) { +struct sway_container *container_add_sibling(struct sway_container *fixed, struct sway_container *active) { // TODO handle floating struct sway_container *parent = fixed->parent; int i = index_child(fixed); @@ -88,7 +88,7 @@ struct sway_container *add_sibling(struct sway_container *fixed, struct sway_con return active->parent; } -void add_child(struct sway_container *parent, struct sway_container *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); @@ -102,7 +102,7 @@ void add_child(struct sway_container *parent, struct sway_container *child) { */ } -struct sway_container *remove_child(struct sway_container *child) { +struct sway_container *container_remove_child(struct sway_container *child) { int i; struct sway_container *parent = child->parent; for (i = 0; i < parent->children->length; ++i) { @@ -115,7 +115,7 @@ struct sway_container *remove_child(struct sway_container *child) { return parent; } -enum sway_container_layout default_layout(struct sway_container *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; @@ -146,7 +146,7 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { return retval; } -void sort_workspaces(struct sway_container *output) { +void container_sort_workspaces(struct sway_container *output) { list_stable_sort(output->children, sort_workspace_cmp_qsort); } @@ -160,7 +160,7 @@ static void apply_vert_layout(struct sway_container *container, const double x, const double height, const int start, const int end); -void arrange_windows(struct sway_container *container, double width, double height) { +void container_arrange_windows(struct sway_container *container, double width, double height) { int i; if (width == -1 || height == -1) { width = container->width; @@ -184,7 +184,7 @@ void arrange_windows(struct sway_container *container, double width, double heig 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); + container_arrange_windows(output, -1, -1); } return; case C_OUTPUT: @@ -198,12 +198,12 @@ void arrange_windows(struct sway_container *container, double width, double heig // arrange all workspaces: for (i = 0; i < container->children->length; ++i) { struct sway_container *child = container->children->items[i]; - arrange_windows(child, -1, -1); + container_arrange_windows(child, -1, -1); } return; case C_WORKSPACE: { - struct sway_container *output = sway_container_parent(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); @@ -284,9 +284,9 @@ static void apply_horiz_layout(struct sway_container *container, if (i == end - 1) { double remaining_width = x + width - child_x; - arrange_windows(child, remaining_width, height); + container_arrange_windows(child, remaining_width, height); } else { - arrange_windows(child, child->width * scale, height); + container_arrange_windows(child, child->width * scale, height); } child_x += child->width; } @@ -334,9 +334,9 @@ void apply_vert_layout(struct sway_container *container, if (i == end - 1) { double remaining_height = y + height - child_y; - arrange_windows(child, width, remaining_height); + container_arrange_windows(child, width, remaining_height); } else { - arrange_windows(child, width, child->height * scale); + container_arrange_windows(child, width, child->height * scale); } child_y += child->height; } @@ -362,7 +362,7 @@ static struct sway_container *get_swayc_in_output_direction(struct sway_containe struct sway_container *ws = sway_seat_get_focus_inactive(seat, output); if (ws->type != C_WORKSPACE) { - ws = sway_container_parent(ws, C_WORKSPACE); + ws = container_parent(ws, C_WORKSPACE); } if (ws == NULL) { @@ -410,7 +410,7 @@ static void get_layout_center_position(struct sway_container *container, int *x, *x = container->x + container->width/2; *y = container->y + container->height/2; } else { - struct sway_container *output = sway_container_parent(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. @@ -496,7 +496,7 @@ static struct sway_container *get_swayc_in_direction_under(struct sway_container /* if (container->type == C_VIEW && swayc_is_fullscreen(container)) { wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); - container = sway_container_parent(container, C_OUTPUT); + container = container_parent(container, C_OUTPUT); get_layout_center_position(container, &abs_pos); struct sway_container *output = swayc_adjacent_output(container, dir, &abs_pos, true); return get_swayc_in_output_direction(output, dir); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 32e828453..0fdd99753 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -52,7 +52,7 @@ struct sway_container *workspace_by_number(const char* name) { if (wbnd.len <= 0) { return NULL; } - return sway_container_find(&root_container, _workspace_by_number, (void *) &wbnd); + return container_find(&root_container, _workspace_by_number, (void *) &wbnd); } static bool _workspace_by_name(struct sway_container *view, void *data) { @@ -65,8 +65,8 @@ struct sway_container *workspace_by_name(const char *name) { struct sway_container *current_workspace = NULL, *current_output = NULL; struct sway_container *focus = sway_seat_get_focus(seat); if (focus) { - current_workspace = sway_container_parent(focus, C_WORKSPACE); - current_output = sway_container_parent(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,7 +79,7 @@ struct sway_container *workspace_by_name(const char *name) { } else if (strcmp(name, "current") == 0) { return current_workspace; } else { - return sway_container_find(&root_container, _workspace_by_name, (void *) name); + return container_find(&root_container, _workspace_by_name, (void *) name); } } @@ -95,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 sway_container_workspace_create(parent, name); + return container_workspace_create(parent, name); } } break; @@ -105,8 +105,8 @@ struct sway_container *workspace_create(const char *name) { struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); parent = focus; - parent = sway_container_parent(parent, C_OUTPUT); - return sway_container_workspace_create(parent, name); + parent = container_parent(parent, C_OUTPUT); + return container_workspace_create(parent, name); } /** @@ -124,7 +124,7 @@ struct sway_container *workspace_output_prev_next_impl(struct sway_container *ou struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : - sway_container_parent(focus, C_WORKSPACE)); + container_parent(focus, C_WORKSPACE)); int i; for (i = 0; i < output->children->length; i++) { @@ -207,7 +207,7 @@ bool workspace_switch(struct sway_container *workspace) { } struct sway_container *active_ws = focus; if (active_ws->type != C_WORKSPACE) { - sway_container_parent(focus, C_WORKSPACE); + container_parent(focus, C_WORKSPACE); } if (config->auto_back_and_forth @@ -236,7 +236,7 @@ bool workspace_switch(struct sway_container *workspace) { next = workspace; } sway_seat_set_focus(seat, next); - struct sway_container *output = sway_container_parent(workspace, C_OUTPUT); - arrange_windows(output, -1, -1); + struct sway_container *output = container_parent(workspace, C_OUTPUT); + container_arrange_windows(output, -1, -1); return true; } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index f9df0d10e..2d2b3b694 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 = sway_container_output_create(name); + struct output *bar_output = container_output_create(name); bar_output->idx = i; list_add(bar->outputs, bar_output); } From ed2cedb54430af0c1400846cf36c9cf539801067 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 17:13:37 -0400 Subject: [PATCH 254/522] rename layout init --- sway/main.c | 2 +- sway/tree/layout.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/main.c b/sway/main.c index 31bf617b8..ded922ee7 100644 --- a/sway/main.c +++ b/sway/main.c @@ -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/layout.c b/sway/tree/layout.c index 07534620d..5152e5230 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -43,7 +43,7 @@ static void output_layout_change_notify(struct wl_listener *listener, void *data container_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; From e5491bf4981934736b43e239404550c3b66bb1f4 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 18:17:03 -0400 Subject: [PATCH 255/522] rename container destroy func --- sway/tree/container.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index b41626e19..b343d2362 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -58,18 +58,18 @@ static struct sway_container *new_swayc(enum sway_container_type type) { return c; } -static void free_swayc(struct sway_container *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 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); } @@ -125,7 +125,7 @@ struct sway_container *container_output_create(struct sway_output *sway_output) output->sway_output = sway_output; output->name = strdup(name); if (output->name == NULL) { - free_swayc(output); + container_destroy(output); return NULL; } @@ -224,7 +224,7 @@ 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); - free_swayc(output); + container_destroy(output); return &root_container; } @@ -235,7 +235,7 @@ struct sway_container *container_view_destroy(struct sway_container *view) { } wlr_log(L_DEBUG, "Destroying view '%s'", view->name); struct sway_container *parent = view->parent; - free_swayc(view); + container_destroy(view); // TODO WLR: Destroy empty containers /* From 62d1b4cb96f87274d695a9c11a041c42cf59ddc1 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 18:17:31 -0400 Subject: [PATCH 256/522] fix container_get_in_direction name --- include/sway/tree/container.h | 7 +++---- sway/commands/focus.c | 2 +- sway/tree/layout.c | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 572dd8e36..3548afc13 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -97,13 +97,12 @@ struct sway_container *container_workspace_create( 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_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); +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, diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 64b059047..64f079f4e 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -51,7 +51,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) { "Expected 'focus ' or 'focus output '"); } - struct sway_container *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/tree/layout.c b/sway/tree/layout.c index 5152e5230..fb34573ff 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -587,7 +587,7 @@ static struct sway_container *get_swayc_in_direction_under(struct sway_container } } -struct sway_container *get_swayc_in_direction(struct sway_container *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); } From 4ec8bf4ceead0b78407c92bf90a42b95740123f9 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 18:38:43 -0400 Subject: [PATCH 257/522] 80col --- sway/tree/container.c | 40 +++++++++++++++--------- sway/tree/layout.c | 73 ++++++++++++++++++++++++++++--------------- sway/tree/workspace.c | 30 ++++++++++++------ 3 files changed, 94 insertions(+), 49 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index b343d2362..1f5370254 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -86,7 +86,8 @@ static void container_destroy(struct sway_container *cont) { free(cont); } -struct sway_container *container_output_create(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); @@ -150,8 +151,10 @@ struct sway_container *container_output_create(struct sway_output *sway_output) 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")) { +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); @@ -172,8 +175,10 @@ struct sway_container *container_workspace_create(struct sway_container *output, 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")) { +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); @@ -198,7 +203,8 @@ struct sway_container *container_view_create(struct sway_container *sibling, str } struct sway_container *container_output_destroy(struct sway_container *output) { - if (!sway_assert(output, "null output passed to container_output_destroy")) { + if (!sway_assert(output, + "null output passed to container_output_destroy")) { return NULL; } @@ -215,7 +221,8 @@ struct sway_container *container_output_destroy(struct sway_container *output) { container_add_child(root_container.children->items[p], child); } container_sort_workspaces(root_container.children->items[p]); - container_arrange_windows(root_container.children->items[p], -1, -1); + container_arrange_windows(root_container.children->items[p], + -1, -1); } } @@ -246,7 +253,8 @@ 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) { +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) { @@ -258,7 +266,8 @@ struct sway_container *container_set_layout(struct sway_container *container, en return container; } -void container_descendents(struct sway_container *root, enum sway_container_type type, +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]; @@ -291,7 +300,8 @@ struct sway_container *container_find(struct sway_container *container, return NULL; } -struct sway_container *container_parent(struct sway_container *container, enum sway_container_type type) { +struct sway_container *container_parent(struct sway_container *container, + enum sway_container_type type) { if (!sway_assert(container, "container is NULL")) { return NULL; } @@ -304,7 +314,8 @@ struct sway_container *container_parent(struct sway_container *container, enum s return container; } -void sway_container_for_each(struct sway_container *container, void (*f)(struct sway_container *view, void *data), void *data) { +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) { @@ -326,7 +337,8 @@ void sway_container_for_each(struct sway_container *container, void (*f)(struct } } -struct sway_container *sway_container_at(struct sway_container *parent, double lx, double ly, +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) { @@ -411,8 +423,8 @@ struct sway_container *sway_container_at(struct sway_container *parent, double l return NULL; } -void sway_container_for_each_bfs(struct sway_container *con, void (*f)(struct sway_container *con, void *data), - 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) { return; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index fb34573ff..53ff9ffa9 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -16,14 +16,16 @@ 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) { - struct sway_container *output_container = root_container.children->items[i]; + struct sway_container *output_container = + root_container.children->items[i]; if (output_container->type != C_OUTPUT) { continue; } @@ -79,7 +81,8 @@ 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) { +struct sway_container *container_add_sibling(struct sway_container *fixed, + struct sway_container *active) { // TODO handle floating struct sway_container *parent = fixed->parent; int i = index_child(fixed); @@ -88,7 +91,8 @@ struct sway_container *container_add_sibling(struct sway_container *fixed, struc return active->parent; } -void container_add_child(struct sway_container *parent, struct sway_container *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,7 +100,9 @@ void container_add_child(struct sway_container *parent, struct sway_container *c 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); } */ @@ -115,7 +121,8 @@ 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 sway_container_layout container_get_default_layout( + struct sway_container *output) { /* TODO WLR if (config->default_layout != L_NONE) { //return config->default_layout; @@ -160,7 +167,8 @@ static void apply_vert_layout(struct sway_container *container, const double x, const double height, const int start, const int end); -void container_arrange_windows(struct sway_container *container, double width, double height) { +void container_arrange_windows(struct sway_container *container, + double width, double height) { int i; if (width == -1 || height == -1) { width = container->width; @@ -203,7 +211,8 @@ void container_arrange_windows(struct sway_container *container, double width, d return; case C_WORKSPACE: { - struct sway_container *output = container_parent(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); @@ -259,7 +268,8 @@ static void apply_horiz_layout(struct sway_container *container, 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 = + &((struct sway_container *)container->children->items[i])->width; if (*old_width <= 0) { if (end - start > 1) { *old_width = width / (end - start - 1); @@ -309,7 +319,8 @@ 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 = + &((struct sway_container *)container->children->items[i])->height; if (*old_height <= 0) { if (end - start > 1) { *old_height = height / (end - start - 1); @@ -354,8 +365,9 @@ 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 struct sway_container *get_swayc_in_output_direction( + struct sway_container *output, enum movement_direction dir, + struct sway_seat *seat) { if (!output) { return NULL; } @@ -380,13 +392,15 @@ static struct sway_container *get_swayc_in_output_direction(struct sway_containe return ws->children->items[0]; case MOVE_UP: case MOVE_DOWN: { - struct sway_container *focused = sway_seat_get_focus_inactive(seat, ws); + struct sway_container *focused = + sway_seat_get_focus_inactive(seat, ws); if (focused && 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,7 +418,8 @@ static struct sway_container *get_swayc_in_output_direction(struct sway_containe return ws; } -static void get_layout_center_position(struct sway_container *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; @@ -423,7 +438,8 @@ static void get_layout_center_position(struct sway_container *container, int *x, } } -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; @@ -457,8 +473,9 @@ 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 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); } @@ -498,7 +515,8 @@ static struct sway_container *get_swayc_in_direction_under(struct sway_container wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); container = container_parent(container, C_OUTPUT); get_layout_center_position(container, &abs_pos); - struct sway_container *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) { @@ -521,16 +539,19 @@ static struct sway_container *get_swayc_in_direction_under(struct sway_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); - struct sway_container *adjacent = sway_output_from_wlr(wlr_adjacent); + struct sway_container *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); + struct sway_container *next = + get_swayc_in_output_direction(adjacent, dir, seat); if (next == NULL) { return NULL; } @@ -570,8 +591,9 @@ static struct sway_container *get_swayc_in_direction_under(struct sway_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, + "%s cont %d-%p dir %i sibling %d: %p", __func__, idx, + container, dir, desired, parent->children->items[desired]); return parent->children->items[desired]; } } @@ -587,7 +609,8 @@ static struct sway_container *get_swayc_in_direction_under(struct sway_container } } -struct sway_container *container_get_in_direction(struct sway_container *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/workspace.c b/sway/tree/workspace.c index 0fdd99753..369cf14c9 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -52,7 +52,8 @@ struct sway_container *workspace_by_number(const char* name) { if (wbnd.len <= 0) { return NULL; } - return container_find(&root_container, _workspace_by_number, (void *) &wbnd); + return container_find(&root_container, + _workspace_by_number, (void *) &wbnd); } static bool _workspace_by_name(struct sway_container *view, void *data) { @@ -79,7 +80,8 @@ 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 container_find(&root_container, _workspace_by_name, + (void *)name); } } @@ -103,7 +105,8 @@ 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); + struct sway_container *focus = + sway_seat_get_focus_inactive(seat, &root_container); parent = focus; parent = container_parent(parent, C_OUTPUT); return container_workspace_create(parent, name); @@ -114,7 +117,8 @@ 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) { +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; @@ -134,7 +138,8 @@ struct sway_container *workspace_output_prev_next_impl(struct sway_container *ou } } - // 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,7 +149,8 @@ struct sway_container *workspace_output_prev_next_impl(struct sway_container *ou * 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) { +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; @@ -166,7 +172,8 @@ struct sway_container *workspace_prev_next_impl(struct sway_container *workspace } } - // 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) { @@ -176,7 +183,8 @@ struct sway_container *workspace_prev_next_impl(struct sway_container *workspace } } - // 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; } @@ -201,7 +209,8 @@ bool workspace_switch(struct sway_container *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); + struct sway_container *focus = + sway_seat_get_focus_inactive(seat, &root_container); if (!seat || !focus) { return false; } @@ -230,7 +239,8 @@ bool workspace_switch(struct sway_container *workspace) { // TODO: Deal with sticky containers - wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); + 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; From 4c394a0e9ee04b46ed349f7b3ddf67c53719b3b6 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 21:19:57 -0400 Subject: [PATCH 258/522] address feedback --- include/sway/tree/container.h | 14 ++++--------- sway/criteria.c | 2 +- sway/input/cursor.c | 4 ++-- sway/input/seat.c | 2 +- sway/tree/container.c | 39 +++++++---------------------------- 5 files changed, 16 insertions(+), 45 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 3548afc13..92ff2b670 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -70,10 +70,10 @@ struct sway_container { enum sway_container_layout prev_layout; enum sway_container_layout workspace_layout; - // TODO convert to layout coordinates + // TODO convert to layout coordinates double x, y; - // does not include borders or gaps. + // does not include borders or gaps. double width, height; list_t *children; @@ -121,23 +121,17 @@ struct sway_container *container_find(struct sway_container *container, struct sway_container *container_parent(struct sway_container *container, enum sway_container_type type); -/** - * Run a function for each child. - */ -void sway_container_for_each(struct sway_container *container, - void (*f)(struct sway_container *view, void *data), void *data); - /** * Find a container at the given coordinates. */ -struct sway_container *sway_container_at(struct sway_container *parent, +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 sway_container_for_each_bfs(struct sway_container *container, +void container_for_each(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data); #endif diff --git a/sway/criteria.c b/sway/criteria.c index 70f8e3057..46961a604 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -435,7 +435,7 @@ list_t *container_for_crit_tokens(list_t *tokens) { struct list_tokens list_tokens = (struct list_tokens){create_list(), tokens}; - sway_container_for_each(&root_container, + container_for_each(&root_container, (void (*)(struct sway_container *, void *))container_match_add, &list_tokens); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index a0e4b9beb..d57ac3e3e 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -50,7 +50,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, } struct sway_container *swayc = - sway_container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + 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); @@ -88,7 +88,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { struct wlr_surface *surface = NULL; double sx, sy; struct sway_container *swayc = - sway_container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); + 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 8e2189de2..be0e15deb 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -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); - sway_container_for_each_bfs(&root_container, collect_focus_iter, seat); + container_for_each(&root_container, collect_focus_iter, seat); wl_signal_add(&root_container.sway_root->events.new_container, &seat->new_container); diff --git a/sway/tree/container.c b/sway/tree/container.c index 1f5370254..dade8f541 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -38,7 +38,7 @@ static void notify_new_container(struct sway_container *container) { ipc_event_window(container, "new"); } -static struct sway_container *new_swayc(enum sway_container_type 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; struct sway_container *c = calloc(1, sizeof(struct sway_container)); @@ -122,7 +122,7 @@ struct sway_container *container_output_create( return NULL; } - struct sway_container *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) { @@ -151,14 +151,14 @@ struct sway_container *container_output_create( return output; } -struct sway_container *container_workspace_create(struct sway_container - *output, const char *name) { +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); - struct sway_container *workspace = new_swayc(C_WORKSPACE); + struct sway_container *workspace = container_create(C_WORKSPACE); workspace->x = output->x; workspace->y = output->y; @@ -182,7 +182,7 @@ struct sway_container *container_view_create(struct sway_container *sibling, return NULL; } const char *title = view_get_title(sway_view); - struct sway_container *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 @@ -314,30 +314,7 @@ struct sway_container *container_parent(struct sway_container *container, return container; } -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, +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(); @@ -423,7 +400,7 @@ struct sway_container *sway_container_at(struct sway_container *parent, return NULL; } -void sway_container_for_each_bfs(struct sway_container *con, +void container_for_each(struct sway_container *con, void (*f)(struct sway_container *con, void *data), void *data) { list_t *queue = get_bfs_queue(); if (!queue) { From c8e7437b82a49d38f55d59b41d3bc2699fcae40d Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Fri, 30 Mar 2018 14:38:14 +1300 Subject: [PATCH 259/522] Clear buffer after beginning renderer --- sway/desktop/output.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9e7fbcc68..b8253ace2 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -197,14 +197,15 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct sway_output *soutput = wl_container_of(listener, soutput, frame); struct wlr_output *wlr_output = data; struct sway_server *server = soutput->server; - float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); - wlr_renderer_clear(renderer, clear_color); int buffer_age = -1; wlr_output_make_current(wlr_output, &buffer_age); wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); + float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; + wlr_renderer_clear(renderer, clear_color); + struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); From 382e8af418a7e1b8cf93d3398509b93c6874cb0d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 21:21:36 -0400 Subject: [PATCH 260/522] Allow sway IPC clients to fall back to i3 socket --- common/ipc-client.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/common/ipc-client.c b/common/ipc-client.c index 582c5e863..117e99108 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -1,4 +1,4 @@ -#define _POSIX_C_SOURCE 2 +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -14,13 +14,31 @@ static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; static const size_t ipc_header_size = sizeof(ipc_magic)+8; char *get_socketpath(void) { - FILE *fp = popen("sway --get-socketpath", "r"); - if (!fp) { - return NULL; + const char *swaysock = getenv("SWAYSOCK"); + if (swaysock) { + return strdup(swaysock); } - char *line = read_line(fp); - pclose(fp); - return line; + FILE *fp = popen("sway --get-socketpath 2>/dev/null", "r"); + if (fp) { + char *line = read_line(fp); + pclose(fp); + if (line && *line) { + return line; + } + } + const char *i3sock = getenv("I3SOCK"); + if (i3sock) { + return strdup(i3sock); + } + fp = popen("i3 --get-socketpath 2>/dev/null", "r"); + if (fp) { + char *line = read_line(fp); + pclose(fp); + if (line && *line) { + return line; + } + } + return NULL; } int ipc_open_socket(const char *socket_path) { From cab1352801b62d1b8a12ca1c995cb24445ce4bc9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 23:04:20 -0400 Subject: [PATCH 261/522] 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 | 91 +++--- 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 | 450 +++++++---------------------- swaybar/config.c | 37 +-- swaybar/event_loop.c | 10 +- swaybar/ipc.c | 410 --------------------------- swaybar/main.c | 35 ++- swaybar/meson.build | 25 ++ swaybar/render.c | 384 +++---------------------- 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, 345 insertions(+), 3787 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 diff --git a/common/meson.build b/common/meson.build index 01736ca6b..4ad470774 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 000000000..212d96cfa --- /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 000000000..f6325f280 --- /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 48a8b0abb..8c9e04dee 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 50d36e76b..3ae8c0b30 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; - int ipc_event_socketfd; - int ipc_socketfd; - int status_read_fd; - int status_write_fd; - pid_t status_command_pid; +struct swaybar { + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; + + 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; + + uint32_t width, height; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; }; -struct workspace { - int num; - char *name; - bool focused; - bool visible; - bool urgent; -}; +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); -/** Global bar state */ -extern struct bar swaybar; - -/** 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 651f0ee3f..1bfe4843d 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); +struct swaybar_config *init_config(); +void free_config(struct swaybar_config *config); -/** - * 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); - -#endif /* _SWAYBAR_CONFIG_H */ +#endif diff --git a/include/swaybar/event_loop.h b/include/swaybar/event_loop.h index a0cde07fe..99f6ed36c 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 c11931d0f..57a1b925f 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 114f43f43..071e2298a 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 b681f43a8..49824b30c 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 f12923a8d..e1d594b4b 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 -#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 +#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; - } - } - - 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; - } - } - - const char *workspace_name = direction == SCROLL_UP ? "prev_on_output" : "next_on_output"; - ipc_send_workspace_command(workspace_name); +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); } -void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { - /* initialize bar with default values */ +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); + } +} + +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares +} + +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; + +void bar_setup(struct swaybar *bar, + const char *socket_path, const char *bar_id) { bar_init(bar); - - /* Initialize event loop lists */ init_event_loop(); - /* connect to sway ipc */ - bar->ipc_socketfd = ipc_open_socket(socket_path); - bar->ipc_event_socketfd = ipc_open_socket(socket_path); + assert(bar->display = wl_display_connect(NULL)); - ipc_bar_init(bar, bar_id); + 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); - 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, + // 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); - } - /* 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); + render_frame(bar, output); } } -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); +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 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); - } - 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); - } +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); } } -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 8fe552f2d..0c2b57e05 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 0d1be1da8..748372edf 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 93d1219c4..000000000 --- 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 0abd07551..c897e1c92 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -4,23 +4,22 @@ #include #include #include +#include #include "swaybar/bar.h" #include "ipc-client.h" -#include "log.h" -/* global bar state */ -struct bar swaybar; - -void sway_terminate(int exit_code) { - bar_teardown(&swaybar); - exit(exit_code); -} +static struct swaybar swaybar; void sig_handler(int signal) { bar_teardown(&swaybar); exit(0); } +void sway_terminate(int code) { + bar_teardown(&swaybar); + exit(code); +} + int main(int argc, char **argv) { char *socket_path = NULL; char *bar_id = NULL; @@ -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) { + wlr_log_init(L_DEBUG, NULL); + } else { + wlr_log_init(L_ERROR, NULL); } - if (debug) { - init_log(L_DEBUG); - } else { - init_log(L_ERROR); + 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 000000000..fd87e51d4 --- /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 6fc09078b..2eaa01953 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" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" +static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, + struct swaybar_output *output) { + struct swaybar_config *config = bar->config; -/* 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; - - // 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 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 + // TODO: use actual height + return 20; +} - // Command output - if (is_focused) { - cairo_set_source_u32(cairo, config->colors.focused_statusline); +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); + // 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); } -} - -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; + cairo_surface_destroy(recorder); + cairo_destroy(cairo); } diff --git a/swaybar/status_line.c b/swaybar/status_line.c deleted file mode 100644 index 87e90caf4..000000000 --- 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 8e719fd9e..000000000 --- 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 c146bf325..000000000 --- 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 c9d00657e..000000000 --- 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 86453e702..000000000 --- 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 91c3af065..000000000 --- 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(); - } -} From 5c9ad035db1bebba3f1954dd1f4328c6421776d4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 23:56:02 -0400 Subject: [PATCH 262/522] Wire up basic IPC support --- include/swaybar/bar.h | 3 + include/swaybar/config.h | 17 ++-- include/swaybar/ipc.h | 5 +- swaybar/bar.c | 11 +++ swaybar/config.c | 14 +-- swaybar/ipc.c | 199 +++++++++++++++++++++++++++++++++++++++ swaybar/meson.build | 1 + 7 files changed, 225 insertions(+), 25 deletions(-) create mode 100644 swaybar/ipc.c diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 3ae8c0b30..df685f472 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -17,6 +17,9 @@ struct swaybar { struct swaybar_config *config; struct swaybar_output *focused_output; + int ipc_event_socketfd; + int ipc_socketfd; + struct wl_list outputs; }; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 1bfe4843d..4b3b5b346 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -2,21 +2,20 @@ #define _SWAYBAR_CONFIG_H #include #include -#include "list.h" +#include #include "util.h" -/** - * Colors for a box with background, border and text colors. - */ struct box_colors { uint32_t border; uint32_t background; uint32_t text; }; -/** - * Swaybar config. - */ +struct config_output { + struct wl_list link; + char *name; +}; + struct swaybar_config { char *status_command; bool pango_markup; @@ -28,8 +27,7 @@ struct swaybar_config { bool binding_mode_indicator; bool wrap_scroll; bool workspace_buttons; - bool all_outputs; - list_t *outputs; + struct wl_list outputs; int height; struct { @@ -51,5 +49,6 @@ struct swaybar_config { struct swaybar_config *init_config(); void free_config(struct swaybar_config *config); +uint32_t parse_position(const char *position); #endif diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 57a1b925f..7f71a5065 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -2,8 +2,7 @@ #define _SWAYBAR_IPC_H #include "swaybar/bar.h" -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); +void ipc_get_config(struct swaybar *bar, const char *bar_id); +void handle_ipc_event(struct swaybar *bar); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index e1d594b4b..433e29486 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -14,6 +14,8 @@ #include "swaybar/config.h" #include "swaybar/event_loop.h" #include "swaybar/bar.h" +#include "swaybar/ipc.h" +#include "ipc-client.h" #include "list.h" #include "pango.h" #include "pool-buffer.h" @@ -92,6 +94,10 @@ void bar_setup(struct swaybar *bar, bar_init(bar); init_event_loop(); + bar->ipc_socketfd = ipc_open_socket(socket_path); + bar->ipc_event_socketfd = ipc_open_socket(socket_path); + ipc_get_config(bar, bar_id); + assert(bar->display = wl_display_connect(NULL)); struct wl_registry *registry = wl_display_get_registry(bar->display); @@ -122,6 +128,11 @@ static void display_in(int fd, short mask, void *_bar) { } } +static void ipc_in(int fd, short mask, void *_bar) { + struct swaybar *bar = (struct swaybar *)_bar; + handle_ipc_event(bar); +} + void bar_run(struct swaybar *bar) { add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); while (1) { diff --git a/swaybar/config.c b/swaybar/config.c index 0c2b57e05..83cf23095 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -22,17 +22,6 @@ uint32_t parse_position(const char *position) { } } -char *parse_font(const char *font) { - char *new_font = NULL; - if (strncmp("pango:", font, 6) == 0) { - font += 6; - } - - new_font = strdup(font); - - return new_font; -} - struct swaybar_config *init_config() { struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); config->status_command = NULL; @@ -45,8 +34,7 @@ struct swaybar_config *init_config() { config->binding_mode_indicator = true; config->wrap_scroll = false; config->workspace_buttons = true; - config->all_outputs = false; - config->outputs = create_list(); + wl_list_init(&config->outputs); /* height */ config->height = 0; diff --git a/swaybar/ipc.c b/swaybar/ipc.c new file mode 100644 index 000000000..cef784d0c --- /dev/null +++ b/swaybar/ipc.c @@ -0,0 +1,199 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include "swaybar/config.h" +#include "swaybar/ipc.h" +#include "ipc-client.h" + +char *parse_font(const char *font) { + char *new_font = NULL; + if (strncmp("pango:", font, 6) == 0) { + font += 6; + } + new_font = strdup(font); + return new_font; +} + +static void ipc_parse_colors( + struct swaybar_config *config, json_object *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)); + } +} + +static void ipc_parse_config( + struct swaybar_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; + 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); + } + + struct config_output *output, *tmp; + wl_list_for_each_safe(output, tmp, &config->outputs, link) { + wl_list_remove(&output->link); + free(output->name); + free(output); + } + if (outputs) { + int length = json_object_array_length(outputs); + for (int i = 0; i < length; ++i) { + json_object *output = json_object_array_get_idx(outputs, i); + const char *name = json_object_get_string(output); + if (strcmp("*", name) == 0) { + // TODO: do we need to clear out the list here or something + break; + } + struct config_output *coutput = calloc( + 1, sizeof(struct config_output)); + coutput->name = strdup(name); + wl_list_insert(&config->outputs, &coutput->link); + } + } + + if (colors) { + ipc_parse_colors(config, colors); + } + + json_object_put(bar_config); +} + +void ipc_get_config(struct swaybar *bar, const char *bar_id) { + 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); +} + +void handle_ipc_event(struct swaybar *bar) { + struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); + free_ipc_response(resp); +} diff --git a/swaybar/meson.build b/swaybar/meson.build index fd87e51d4..6dc7c5642 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -4,6 +4,7 @@ executable( 'bar.c', 'config.c', 'event_loop.c', + 'ipc.c', 'main.c', 'render.c', ], From e5e8094dc3119584ae611c3197b38243b6c016c9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 00:07:35 -0400 Subject: [PATCH 263/522] Only utilize the configured outputs --- include/swaybar/bar.h | 2 +- include/swaybar/config.h | 1 + swaybar/bar.c | 32 ++++++++++++++++++++------------ swaybar/ipc.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index df685f472..6e1ab66d4 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -31,7 +31,7 @@ struct swaybar_output { struct zwlr_layer_surface_v1 *layer_surface; char *name; - int idx; + size_t index; bool focused; uint32_t width, height; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 4b3b5b346..6bcefe642 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -14,6 +14,7 @@ struct box_colors { struct config_output { struct wl_list link; char *name; + size_t index; }; struct swaybar_config { diff --git a/swaybar/bar.c b/swaybar/bar.c index 433e29486..a6e3b7809 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -65,13 +65,13 @@ static void handle_global(void *data, struct wl_registry *registry, bar->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { - static int idx = 0; + static size_t index = 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++; + output->index = index++; wl_list_insert(&bar->outputs, &output->link); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { bar->layer_shell = wl_registry_bind( @@ -108,16 +108,24 @@ void bar_setup(struct swaybar *bar, // 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); - render_frame(bar, output); + struct config_output *coutput; + wl_list_for_each(coutput, &bar->config->outputs, link) { + if (coutput->index != output->index) { + continue; + } + 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); + render_frame(bar, output); + break; + } } } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index cef784d0c..d3ee170c3 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 500 +#include #include #include #include @@ -174,6 +175,7 @@ static void ipc_parse_config( struct config_output *coutput = calloc( 1, sizeof(struct config_output)); coutput->name = strdup(name); + coutput->index = SIZE_MAX; wl_list_insert(&config->outputs, &coutput->link); } } @@ -185,12 +187,47 @@ static void ipc_parse_config( json_object_put(bar_config); } +static void ipc_get_outputs(struct swaybar *bar) { + uint32_t len = 0; + char *res = ipc_single_command(bar->ipc_socketfd, + IPC_GET_OUTPUTS, NULL, &len); + json_object *outputs = json_tokener_parse(res); + for (size_t i = 0; i < json_object_array_length(outputs); ++i) { + json_object *output = json_object_array_get_idx(outputs, i); + json_object *output_name, *output_active; + json_object_object_get_ex(output, "name", &output_name); + json_object_object_get_ex(output, "active", &output_active); + const char *name = json_object_get_string(output_name); + bool active = json_object_get_boolean(output_active); + if (!active) { + continue; + } + if (wl_list_empty(&bar->config->outputs)) { + struct config_output *coutput = calloc( + 1, sizeof(struct config_output)); + coutput->name = strdup(name); + coutput->index = i; + wl_list_insert(&bar->config->outputs, &coutput->link); + } else { + struct config_output *coutput; + wl_list_for_each(coutput, &bar->config->outputs, link) { + if (strcmp(name, coutput->name) == 0) { + coutput->index = i; + break; + } + } + } + } + free(res); +} + void ipc_get_config(struct swaybar *bar, const char *bar_id) { 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); + ipc_get_outputs(bar); } void handle_ipc_event(struct swaybar *bar) { From 3399ad9840f0d3d42b377f4404115d887f65e18a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 00:21:05 -0400 Subject: [PATCH 264/522] Round up workspaces on each output --- include/swaybar/bar.h | 16 +++++++++-- include/swaybar/ipc.h | 3 ++- swaybar/bar.c | 9 +++++-- swaybar/ipc.c | 63 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 85 insertions(+), 6 deletions(-) diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 6e1ab66d4..c89aa61c5 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -30,6 +30,8 @@ struct swaybar_output { struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; + struct wl_list workspaces; + char *name; size_t index; bool focused; @@ -39,9 +41,19 @@ struct swaybar_output { struct pool_buffer *current_buffer; }; +struct swaybar_workspace { + struct wl_list link; + int num; + char *name; + bool focused; + bool visible; + bool urgent; +}; + +// TODO: Rename stuff to match wlroots conventions (init/create/etc) void bar_setup(struct swaybar *bar, - const char *socket_path, - const char *bar_id); + const char *socket_path, + const char *bar_id); void bar_run(struct swaybar *bar); void bar_teardown(struct swaybar *bar); diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 7f71a5065..f3881bd0f 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -2,7 +2,8 @@ #define _SWAYBAR_IPC_H #include "swaybar/bar.h" -void ipc_get_config(struct swaybar *bar, const char *bar_id); +void ipc_initialize(struct swaybar *bar, const char *bar_id); void handle_ipc_event(struct swaybar *bar); +void ipc_get_workspaces(struct swaybar *bar); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index a6e3b7809..68dea4086 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -72,6 +72,7 @@ static void handle_global(void *data, struct wl_registry *registry, output->output = wl_registry_bind(registry, name, &wl_output_interface, 1); output->index = index++; + wl_list_init(&output->workspaces); wl_list_insert(&bar->outputs, &output->link); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { bar->layer_shell = wl_registry_bind( @@ -96,7 +97,7 @@ void bar_setup(struct swaybar *bar, bar->ipc_socketfd = ipc_open_socket(socket_path); bar->ipc_event_socketfd = ipc_open_socket(socket_path); - ipc_get_config(bar, bar_id); + ipc_initialize(bar, bar_id); assert(bar->display = wl_display_connect(NULL)); @@ -113,6 +114,7 @@ void bar_setup(struct swaybar *bar, if (coutput->index != output->index) { continue; } + output->name = strdup(coutput->name); assert(output->surface = wl_compositor_create_surface( bar->compositor)); output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( @@ -123,10 +125,13 @@ void bar_setup(struct swaybar *bar, &layer_surface_listener, output); zwlr_layer_surface_v1_set_anchor(output->layer_surface, bar->config->position); - render_frame(bar, output); break; } } + ipc_get_workspaces(bar); + wl_list_for_each(output, &bar->outputs, link) { + render_frame(bar, output); + } } static void display_in(int fd, short mask, void *_bar) { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index d3ee170c3..6b8320705 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -187,6 +187,65 @@ static void ipc_parse_config( json_object_put(bar_config); } +static void free_workspaces(struct wl_list *list) { + struct swaybar_workspace *ws, *tmp; + wl_list_for_each_safe(ws, tmp, list, link) { + wl_list_remove(&ws->link); + free(ws->name); + free(ws); + } +} + +void ipc_get_workspaces(struct swaybar *bar) { + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + free_workspaces(&output->workspaces); + } + 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; + } + size_t length = json_object_array_length(results); + json_object *ws_json; + json_object *num, *name, *visible, *focused, *out, *urgent; + for (size_t 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); + + wl_list_for_each(output, &bar->outputs, link) { + const char *ws_output = json_object_get_string(out); + if (strcmp(ws_output, output->name) == 0) { + struct swaybar_workspace *ws = + calloc(1, sizeof(struct swaybar_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); + wl_list_insert(&output->workspaces, &ws->link); + } + } + } + free(res); +} + static void ipc_get_outputs(struct swaybar *bar) { uint32_t len = 0; char *res = ipc_single_command(bar->ipc_socketfd, @@ -218,16 +277,18 @@ static void ipc_get_outputs(struct swaybar *bar) { } } } + json_object_put(outputs); free(res); } -void ipc_get_config(struct swaybar *bar, const char *bar_id) { +void ipc_initialize(struct swaybar *bar, const char *bar_id) { 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); ipc_get_outputs(bar); + // TODO: subscribe to stuff } void handle_ipc_event(struct swaybar *bar) { From 3a458cd7b55bdfad1b04a01064f4fe8fa86ed0de Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 00:49:59 -0400 Subject: [PATCH 265/522] Implement workspace button rendering --- swaybar/render.c | 92 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 4 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index 2eaa01953..226e4ce31 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -10,8 +10,79 @@ #include "swaybar/render.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, - struct swaybar_output *output) { +static const char *strip_workspace_number(const char *ws_name) { + size_t len = strlen(ws_name); + for (size_t i = 0; i < len; ++i) { + if (ws_name[i] < '0' || ws_name[i] > '9') { + if (':' == ws_name[i] && i < len - 1 && i > 0) { + return ws_name + i + 1; + } + return ws_name; + } + } + return ws_name; +} + +static uint32_t render_workspace_button(cairo_t *cairo, + struct swaybar_config *config, struct swaybar_workspace *ws, + double *x, uint32_t height) { + static const int ws_horizontal_padding = 5; + static const double ws_vertical_padding = 1.5; + static const int ws_spacing = 1; + + const char *name = ws->name; + if (config->strip_workspace_numbers) { + name = strip_workspace_number(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 text_width, text_height; + get_text_size(cairo, config->font, &text_width, &text_height, + 1, true, "%s", name); + uint32_t ideal_height = ws_vertical_padding * 2 + text_height; + if (height < ideal_height) { + height = ideal_height; + } + uint32_t width = ws_horizontal_padding * 2 + text_width; + + cairo_set_source_u32(cairo, box_colors.background); + cairo_rectangle(cairo, *x, 0, width - 1, height); + cairo_fill(cairo); + + cairo_set_source_u32(cairo, box_colors.border); + cairo_rectangle(cairo, *x, 0, width - 1, height); + cairo_stroke(cairo); + + double text_y = height / 2.0 - text_height / 2.0; + cairo_set_source_u32(cairo, box_colors.text); + cairo_move_to(cairo, (int)*x + ws_horizontal_padding, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, true, "%s", name); + + *x += width + ws_spacing; + return ideal_height; +} + +static void update_heights(uint32_t height, uint32_t *min, uint32_t *max) { + if (*min < height) { + *min = height; + } + if (height > *max) { + *max = height; + } +} + +static uint32_t render_to_cairo(cairo_t *cairo, + struct swaybar *bar, struct swaybar_output *output) { struct swaybar_config *config = bar->config; cairo_save(cairo); @@ -27,8 +98,20 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, } cairo_paint(cairo); - // TODO: use actual height - return 20; + uint32_t min_height = output->height, max_height = output->height; + + double x = 0; + if (config->workspace_buttons) { + struct swaybar_workspace *ws; + wl_list_for_each(ws, &output->workspaces, link) { + uint32_t h = render_workspace_button( + cairo, config, ws, &x, output->height); + update_heights(h, &min_height, &max_height); + } + } + + // TODO: Shrink via min_height if sane + return max_height; } void render_frame(struct swaybar *bar, @@ -41,6 +124,7 @@ void render_frame(struct swaybar *bar, // Reconfigure surface zwlr_layer_surface_v1_set_size( output->layer_surface, 0, height); + zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); // TODO: this could infinite loop if the compositor assigns us a // different height than what we asked for wl_surface_commit(output->surface); From 86ba0fc15d7615b09f0279616d538af5c23bc551 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 10:38:17 -0400 Subject: [PATCH 266/522] Re-render bar on IPC updates --- include/swaybar/ipc.h | 3 ++- swaybar/bar.c | 8 +++++++- swaybar/ipc.c | 46 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index f3881bd0f..278baef0d 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -1,9 +1,10 @@ #ifndef _SWAYBAR_IPC_H #define _SWAYBAR_IPC_H +#include #include "swaybar/bar.h" void ipc_initialize(struct swaybar *bar, const char *bar_id); -void handle_ipc_event(struct swaybar *bar); +bool handle_ipc_event(struct swaybar *bar); void ipc_get_workspaces(struct swaybar *bar); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index 68dea4086..90fd5ad4a 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -143,11 +143,17 @@ static void display_in(int fd, short mask, void *_bar) { static void ipc_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; - handle_ipc_event(bar); + if (handle_ipc_event(bar)) { + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + render_frame(bar, output); + } + } } void bar_run(struct swaybar *bar) { add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); + add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar); while (1) { event_loop_poll(); } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 6b8320705..75f179539 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "swaybar/config.h" #include "swaybar/ipc.h" #include "ipc-client.h" @@ -288,10 +289,51 @@ void ipc_initialize(struct swaybar *bar, const char *bar_id) { ipc_parse_config(bar->config, res); free(res); ipc_get_outputs(bar); - // TODO: subscribe to stuff + + const char *subscribe = "[ \"workspace\", \"mode\" ]"; + len = strlen(subscribe); + free(ipc_single_command(bar->ipc_event_socketfd, + IPC_SUBSCRIBE, subscribe, &len)); } -void handle_ipc_event(struct swaybar *bar) { +bool handle_ipc_event(struct swaybar *bar) { struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); + if (!resp) { + return false; + } + switch (resp->type) { + case IPC_EVENT_WORKSPACE: + ipc_get_workspaces(bar); + break; + case IPC_EVENT_MODE: { + json_object *result = json_tokener_parse(resp->payload); + if (!result) { + free_ipc_response(resp); + wlr_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 { + wlr_log(L_ERROR, "failed to parse response"); + json_object_put(result); + free_ipc_response(resp); + return false; + } + json_object_put(result); + break; + } + default: + free_ipc_response(resp); + return false; + } free_ipc_response(resp); + return true; } From 37b61eff2df3c8b47b1304650d1fb204a62658db Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 10:59:33 -0400 Subject: [PATCH 267/522] Add binding mode indicator --- swaybar/ipc.c | 1 + swaybar/render.c | 77 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 75f179539..3c2d6fbc9 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -306,6 +306,7 @@ bool handle_ipc_event(struct swaybar *bar) { ipc_get_workspaces(bar); break; case IPC_EVENT_MODE: { + // TODO: interpret "pango_markup" field json_object *result = json_tokener_parse(resp->payload); if (!result) { free_ipc_response(resp); diff --git a/swaybar/render.c b/swaybar/render.c index 226e4ce31..beb4de405 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -10,6 +11,38 @@ #include "swaybar/render.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" +static const int ws_horizontal_padding = 5; +static const double ws_vertical_padding = 1.5; +static const int ws_spacing = 1; + +static uint32_t render_binding_mode_indicator(cairo_t *cairo, + struct swaybar_config *config, const char *mode, double x, + uint32_t height) { + int text_width, text_height; + get_text_size(cairo, config->font, &text_width, &text_height, + 1, true, "⚡ %s", mode); + uint32_t ideal_height = text_height + ws_vertical_padding * 2; + if (height < ideal_height) { + height = ideal_height; + } + + cairo_set_source_u32(cairo, config->colors.binding_mode.background); + cairo_rectangle(cairo, x, 0, text_width + ws_horizontal_padding * 2 - 1, + height + ws_vertical_padding * 2); + cairo_fill(cairo); + + cairo_set_source_u32(cairo, config->colors.binding_mode.border); + cairo_rectangle(cairo, x, 0, text_width + ws_horizontal_padding * 2 - 1, + height + ws_vertical_padding * 2); + cairo_stroke(cairo); + + double text_y = height / 2.0 - text_height / 2.0; + cairo_set_source_u32(cairo, config->colors.binding_mode.text); + cairo_move_to(cairo, (int)x + ws_horizontal_padding, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, true, "⚡ %s", mode); + return ideal_height; +} + static const char *strip_workspace_number(const char *ws_name) { size_t len = strlen(ws_name); for (size_t i = 0; i < len; ++i) { @@ -26,10 +59,6 @@ static const char *strip_workspace_number(const char *ws_name) { static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_config *config, struct swaybar_workspace *ws, double *x, uint32_t height) { - static const int ws_horizontal_padding = 5; - static const double ws_vertical_padding = 1.5; - static const int ws_spacing = 1; - const char *name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); @@ -72,24 +101,10 @@ static uint32_t render_workspace_button(cairo_t *cairo, return ideal_height; } -static void update_heights(uint32_t height, uint32_t *min, uint32_t *max) { - if (*min < height) { - *min = height; - } - if (height > *max) { - *max = height; - } -} - static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, struct swaybar_output *output) { struct swaybar_config *config = bar->config; - cairo_save(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); - cairo_paint(cairo); - cairo_restore(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); if (output->focused) { cairo_set_source_u32(cairo, config->colors.focused_background); @@ -98,20 +113,30 @@ static uint32_t render_to_cairo(cairo_t *cairo, } cairo_paint(cairo); - uint32_t min_height = output->height, max_height = output->height; - + uint32_t max_height = 0; + /* + * Each render_* function takes the actual height of the bar, and returns + * the ideal height. If the actual height is too short, the render function + * can do whatever it wants - the buffer won't be committed. If the actual + * height is too tall, the render function should adapt its drawing to + * utilize the available space. + */ double x = 0; if (config->workspace_buttons) { struct swaybar_workspace *ws; wl_list_for_each(ws, &output->workspaces, link) { uint32_t h = render_workspace_button( cairo, config, ws, &x, output->height); - update_heights(h, &min_height, &max_height); + max_height = h > max_height ? h : max_height; } } + if (config->binding_mode_indicator && config->mode) { + uint32_t h = render_binding_mode_indicator( + cairo, config, config->mode, x, output->height); + max_height = h > max_height ? h : max_height; + } - // TODO: Shrink via min_height if sane - return max_height; + return max_height > output->height ? max_height : output->height; } void render_frame(struct swaybar *bar, @@ -134,6 +159,12 @@ void render_frame(struct swaybar *bar, output->current_buffer = get_next_buffer(bar->shm, output->buffers, output->width, output->height); cairo_t *shm = output->current_buffer->cairo; + + cairo_save(shm); + cairo_set_operator(shm, CAIRO_OPERATOR_CLEAR); + cairo_paint(shm); + cairo_restore(shm); + cairo_set_source_surface(shm, recorder, 0.0, 0.0); cairo_paint(shm); wl_surface_attach(output->surface, From 1e8faeec0263a7da311a13c56a0de34e47e66fa6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 11:58:54 -0400 Subject: [PATCH 268/522] Pixel-perfect rendering --- include/swaybar/config.h | 1 + swaybar/config.c | 1 + swaybar/ipc.c | 62 +++++++++++++++++++++++++++------------- swaybar/render.c | 48 ++++++++++++++++++++----------- 4 files changed, 75 insertions(+), 37 deletions(-) diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 6bcefe642..7634cb16e 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -24,6 +24,7 @@ struct swaybar_config { char *font; char *sep_symbol; char *mode; + bool mode_pango_markup; bool strip_workspace_numbers; bool binding_mode_indicator; bool wrap_scroll; diff --git a/swaybar/config.c b/swaybar/config.c index 83cf23095..802d07797 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -41,6 +41,7 @@ struct swaybar_config *init_config() { /* colors */ config->colors.background = 0x000000FF; + config->colors.focused_background = 0x000000FF; config->colors.statusline = 0xFFFFFFFF; config->colors.separator = 0x666666FF; diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 3c2d6fbc9..a260b7988 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -48,58 +48,76 @@ static void ipc_parse_colors( 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)); + config->colors.background = parse_color( + json_object_get_string(background)); } if (statusline) { - config->colors.statusline = parse_color(json_object_get_string(statusline)); + config->colors.statusline = parse_color( + json_object_get_string(statusline)); } if (separator) { - config->colors.separator = parse_color(json_object_get_string(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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + config->colors.binding_mode.text = parse_color( + json_object_get_string(binding_mode_text)); } } @@ -306,14 +324,13 @@ bool handle_ipc_event(struct swaybar *bar) { ipc_get_workspaces(bar); break; case IPC_EVENT_MODE: { - // TODO: interpret "pango_markup" field json_object *result = json_tokener_parse(resp->payload); if (!result) { free_ipc_response(resp); wlr_log(L_ERROR, "failed to parse payload as json"); return false; } - json_object *json_change; + json_object *json_change, *json_pango_markup; if (json_object_object_get_ex(result, "change", &json_change)) { const char *change = json_object_get_string(json_change); free(bar->config->mode); @@ -328,6 +345,11 @@ bool handle_ipc_event(struct swaybar *bar) { free_ipc_response(resp); return false; } + if (json_object_object_get_ex(result, + "pango_markup", &json_pango_markup)) { + bar->config->mode_pango_markup = json_object_get_boolean( + json_pango_markup); + } json_object_put(result); break; } diff --git a/swaybar/render.c b/swaybar/render.c index beb4de405..ba22e9d47 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -13,33 +13,39 @@ static const int ws_horizontal_padding = 5; static const double ws_vertical_padding = 1.5; -static const int ws_spacing = 1; +static const double border_width = 1; static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_config *config, const char *mode, double x, uint32_t height) { int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, true, "⚡ %s", mode); - uint32_t ideal_height = text_height + ws_vertical_padding * 2; + 1, true, "%s", mode); + uint32_t ideal_height = text_height + ws_vertical_padding * 2 + + border_width * 2; if (height < ideal_height) { height = ideal_height; } + uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; cairo_set_source_u32(cairo, config->colors.binding_mode.background); - cairo_rectangle(cairo, x, 0, text_width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); + cairo_rectangle(cairo, x, 0, width, height); cairo_fill(cairo); cairo_set_source_u32(cairo, config->colors.binding_mode.border); - cairo_rectangle(cairo, x, 0, text_width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); - cairo_stroke(cairo); + cairo_rectangle(cairo, x, 0, width, border_width); + cairo_fill(cairo); + cairo_rectangle(cairo, x, 0, border_width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, x + width - border_width, 0, border_width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, x, height - border_width, width, border_width); + cairo_fill(cairo); double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, config->colors.binding_mode.text); - cairo_move_to(cairo, (int)x + ws_horizontal_padding, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, true, "⚡ %s", mode); + cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, true, "%s", mode); return ideal_height; } @@ -78,26 +84,33 @@ static uint32_t render_workspace_button(cairo_t *cairo, int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, 1, true, "%s", name); - uint32_t ideal_height = ws_vertical_padding * 2 + text_height; + uint32_t ideal_height = ws_vertical_padding * 2 + text_height + + border_width * 2; if (height < ideal_height) { height = ideal_height; } - uint32_t width = ws_horizontal_padding * 2 + text_width; + uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; cairo_set_source_u32(cairo, box_colors.background); - cairo_rectangle(cairo, *x, 0, width - 1, height); + cairo_rectangle(cairo, *x, 0, width, height); cairo_fill(cairo); cairo_set_source_u32(cairo, box_colors.border); - cairo_rectangle(cairo, *x, 0, width - 1, height); - cairo_stroke(cairo); + cairo_rectangle(cairo, *x, 0, width, border_width); + cairo_fill(cairo); + cairo_rectangle(cairo, *x, 0, border_width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, *x + width - border_width, 0, border_width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, *x, height - border_width, width, border_width); + cairo_fill(cairo); double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, box_colors.text); - cairo_move_to(cairo, (int)*x + ws_horizontal_padding, (int)floor(text_y)); + cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); pango_printf(cairo, config->font, 1, true, "%s", name); - *x += width + ws_spacing; + *x += width; return ideal_height; } @@ -167,6 +180,7 @@ void render_frame(struct swaybar *bar, 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); From 531c175d3e60bf9dbfd538af1fd5eebb906c6f91 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 12:03:08 -0400 Subject: [PATCH 269/522] Respect user bar height preference This is an i3-gaps feature we support --- swaybar/render.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/swaybar/render.c b/swaybar/render.c index ba22e9d47..317b0f655 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -158,6 +158,9 @@ void render_frame(struct swaybar *bar, CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); uint32_t height = render_to_cairo(cairo, bar, output); + if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) { + height = bar->config->height; + } if (height != output->height) { // Reconfigure surface zwlr_layer_surface_v1_set_size( From a76829f3756d3df22fe46e6688374497de29c2e1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 12:19:20 -0400 Subject: [PATCH 270/522] Some layer shell fixes Based on the corresponding rootston changes --- include/sway/layers.h | 2 -- include/sway/output.h | 1 + sway/desktop/layer_shell.c | 22 ---------------------- sway/desktop/output.c | 8 ++++++++ 4 files changed, 9 insertions(+), 24 deletions(-) diff --git a/include/sway/layers.h b/include/sway/layers.h index 22054be1e..ee47c5ad6 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -14,8 +14,6 @@ struct sway_layer_surface { struct wl_listener unmap; struct wl_listener surface_commit; struct wl_listener output_destroy; - struct wl_listener output_mode; - struct wl_listener output_transform; bool configured; struct wlr_box geo; diff --git a/include/sway/output.h b/include/sway/output.h index f899230f9..6fb79987b 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -21,6 +21,7 @@ struct sway_output { struct wl_listener frame; struct wl_listener destroy; struct wl_listener mode; + struct wl_listener transform; pid_t bg_pid; }; diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index bd62f84a4..31679fb2f 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -193,22 +193,10 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { struct sway_layer_surface *sway_layer = wl_container_of(listener, sway_layer, output_destroy); wl_list_remove(&sway_layer->output_destroy.link); - wl_list_remove(&sway_layer->output_mode.link); - wl_list_remove(&sway_layer->output_transform.link); sway_layer->layer_surface->output = NULL; wlr_layer_surface_close(sway_layer->layer_surface); } -static void handle_output_mode(struct wl_listener *listener, void *data) { - struct wlr_output *output = data; - arrange_layers((struct sway_output *)output->data); -} - -static void handle_output_transform(struct wl_listener *listener, void *data) { - struct wlr_output *output = data; - arrange_layers((struct sway_output *)output->data); -} - static void handle_surface_commit(struct wl_listener *listener, void *data) { struct sway_layer_surface *layer = wl_container_of(listener, layer, surface_commit); @@ -243,8 +231,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&sway_layer->surface_commit.link); if (sway_layer->layer_surface->output != NULL) { wl_list_remove(&sway_layer->output_destroy.link); - wl_list_remove(&sway_layer->output_mode.link); - wl_list_remove(&sway_layer->output_transform.link); } struct sway_output *output = sway_layer->layer_surface->output->data; arrange_layers(output); @@ -289,14 +275,6 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&layer_surface->output->events.destroy, &sway_layer->output_destroy); - sway_layer->output_mode.notify = handle_output_mode; - wl_signal_add(&layer_surface->output->events.mode, - &sway_layer->output_mode); - - sway_layer->output_transform.notify = handle_output_transform; - wl_signal_add(&layer_surface->output->events.transform, - &sway_layer->output_transform); - sway_layer->destroy.notify = handle_destroy; wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); sway_layer->map.notify = handle_map; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index b8253ace2..30b23a185 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -268,6 +268,12 @@ static void handle_output_mode(struct wl_listener *listener, void *data) { arrange_windows(output->swayc, -1, -1); } +static void handle_output_transform(struct wl_listener *listener, void *data) { + struct sway_output *output = wl_container_of(listener, output, transform); + arrange_layers(output); + arrange_windows(output->swayc, -1, -1); +} + void handle_new_output(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; @@ -306,6 +312,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->destroy.notify = handle_output_destroy; wl_signal_add(&wlr_output->events.mode, &output->mode); output->mode.notify = handle_output_mode; + wl_signal_add(&wlr_output->events.transform, &output->transform); + output->transform.notify = handle_output_transform; arrange_layers(output); arrange_windows(&root_container, -1, -1); From 718502c815d0af81b4ab71fb6b86976b5403adf9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 13:49:46 -0400 Subject: [PATCH 271/522] Iterate over workspaces backwards --- swaybar/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaybar/render.c b/swaybar/render.c index 317b0f655..f797873c7 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -137,7 +137,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, double x = 0; if (config->workspace_buttons) { struct swaybar_workspace *ws; - wl_list_for_each(ws, &output->workspaces, link) { + wl_list_for_each_reverse(ws, &output->workspaces, link) { uint32_t h = render_workspace_button( cairo, config, ws, &x, output->height); max_height = h > max_height ? h : max_height; From 0d0ab7c5ce148bce841fa0682d04bc7b6c21b902 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 15:16:12 -0400 Subject: [PATCH 272/522] Implement status line Does not yet support i3bar json protocol --- include/swaybar/bar.h | 1 + include/swaybar/status_line.h | 69 +++++++++---------------------- swaybar/bar.c | 26 ++++++++++-- swaybar/config.c | 1 + swaybar/meson.build | 1 + swaybar/render.c | 56 +++++++++++++++++++++++++ swaybar/status_line.c | 78 +++++++++++++++++++++++++++++++++++ 7 files changed, 178 insertions(+), 54 deletions(-) create mode 100644 swaybar/status_line.c diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index c89aa61c5..1bf2ea2d5 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -16,6 +16,7 @@ struct swaybar { struct swaybar_config *config; struct swaybar_output *focused_output; + struct status_line *status; int ipc_event_socketfd; int ipc_socketfd; diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 0664ddee8..6c595df0f 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -1,61 +1,30 @@ #ifndef _SWAYBAR_STATUS_LINE_H #define _SWAYBAR_STATUS_LINE_H - #include +#include #include - -#include "list.h" #include "bar.h" -typedef enum {UNDEF, TEXT, I3BAR} command_protocol; +enum status_protocol { + PROTOCOL_UNDEF, + PROTOCOL_TEXT, + PROTOCOL_I3BAR, +}; struct status_line { - list_t *block_line; - const char *text_line; - command_protocol protocol; - bool click_events; + pid_t pid; + int read_fd, write_fd; + FILE *read, *write; + + enum status_protocol protocol; + const char *text; + + char *buffer; + size_t buffer_size; }; -struct status_block { - char *full_text, *short_text, *align; - bool urgent; - uint32_t color; - int min_width; - char *name, *instance; - bool separator; - int separator_block_width; - bool markup; - // Airblader features - uint32_t background; - uint32_t border; - int border_top; - int border_bottom; - int border_left; - int border_right; +struct status_line *status_line_init(char *cmd); +void status_line_free(struct status_line *status); +bool handle_status_readable(struct status_line *status); - // Set during rendering - int x; - int width; -}; - -/** - * Initialize status line struct. - */ -struct status_line *init_status_line(); - -/** - * handle status line activity. - */ -bool handle_status_line(struct bar *bar); - -/** - * Handle mouse clicks. - */ -bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button); - -/** - * Free status line struct. - */ -void free_status_line(struct status_line *line); - -#endif /* _SWAYBAR_STATUS_LINE_H */ +#endif diff --git a/swaybar/bar.c b/swaybar/bar.c index 90fd5ad4a..72c4be8f5 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -13,6 +13,7 @@ #include "swaybar/render.h" #include "swaybar/config.h" #include "swaybar/event_loop.h" +#include "swaybar/status_line.h" #include "swaybar/bar.h" #include "swaybar/ipc.h" #include "ipc-client.h" @@ -98,6 +99,9 @@ void bar_setup(struct swaybar *bar, bar->ipc_socketfd = ipc_open_socket(socket_path); bar->ipc_event_socketfd = ipc_open_socket(socket_path); ipc_initialize(bar, bar_id); + if (bar->config->status_command) { + bar->status = status_line_init(bar->config->status_command); + } assert(bar->display = wl_display_connect(NULL)); @@ -134,6 +138,13 @@ void bar_setup(struct swaybar *bar, } } +static void render_all_frames(struct swaybar *bar) { + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + render_frame(bar, output); + } +} + static void display_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; if (wl_display_dispatch(bar->display) == -1) { @@ -144,16 +155,23 @@ static void display_in(int fd, short mask, void *_bar) { static void ipc_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; if (handle_ipc_event(bar)) { - struct swaybar_output *output; - wl_list_for_each(output, &bar->outputs, link) { - render_frame(bar, output); - } + render_all_frames(bar); + } +} + +static void status_in(int fd, short mask, void *_bar) { + struct swaybar *bar = (struct swaybar *)_bar; + if (handle_status_readable(bar->status)) { + render_all_frames(bar); } } void bar_run(struct swaybar *bar) { add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar); + if (bar->status) { + add_event(bar->status->read_fd, POLLIN, status_in, bar); + } while (1) { event_loop_poll(); } diff --git a/swaybar/config.c b/swaybar/config.c index 802d07797..9169ad27f 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -43,6 +43,7 @@ struct swaybar_config *init_config() { config->colors.background = 0x000000FF; config->colors.focused_background = 0x000000FF; config->colors.statusline = 0xFFFFFFFF; + config->colors.focused_statusline = 0xFFFFFFFF; config->colors.separator = 0x666666FF; config->colors.focused_workspace.border = 0x4C7899FF; diff --git a/swaybar/meson.build b/swaybar/meson.build index 6dc7c5642..d15e8b5c1 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -7,6 +7,7 @@ executable( 'ipc.c', 'main.c', 'render.c', + 'status_line.c', ], include_directories: [sway_inc], dependencies: [ diff --git a/swaybar/render.c b/swaybar/render.c index f797873c7..ec1239a11 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -9,12 +9,59 @@ #include "swaybar/bar.h" #include "swaybar/config.h" #include "swaybar/render.h" +#include "swaybar/status_line.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" static const int ws_horizontal_padding = 5; static const double ws_vertical_padding = 1.5; static const double border_width = 1; +static uint32_t render_status_line_text(cairo_t *cairo, + struct swaybar_config *config, struct status_line *status, + bool focused, uint32_t width, uint32_t height) { + if (!status->text) { + return 0; + } + //wlr_log(L_DEBUG, "focused %d", focused); + cairo_set_source_u32(cairo, focused ? + config->colors.focused_statusline : config->colors.statusline); + static const int margin = 3; + int text_width, text_height; + get_text_size(cairo, config->font, &text_width, &text_height, + 1, config->pango_markup, "%s", status->text); + uint32_t ideal_height = text_height + ws_vertical_padding * 2; + if (height < ideal_height) { + height = ideal_height; + } + double text_y = height / 2.0 - text_height / 2.0; + cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, config->pango_markup, + "%s", status->text); + return ideal_height; +} + +static uint32_t render_status_line_i3bar(cairo_t *cairo, + struct swaybar_config *config, struct status_line *status, + bool focused, uint32_t width, uint32_t height) { + // TODO + return 0; +} + +static uint32_t render_status_line(cairo_t *cairo, + struct swaybar_config *config, struct status_line *status, + bool focused, uint32_t width, uint32_t height) { + switch (status->protocol) { + case PROTOCOL_TEXT: + return render_status_line_text(cairo, + config, status, focused, width, height); + case PROTOCOL_I3BAR: + return render_status_line_i3bar(cairo, + config, status, focused, width, height); + default: + return 0; + } +} + static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_config *config, const char *mode, double x, uint32_t height) { @@ -148,6 +195,11 @@ static uint32_t render_to_cairo(cairo_t *cairo, cairo, config, config->mode, x, output->height); max_height = h > max_height ? h : max_height; } + if (bar->status) { + uint32_t h = render_status_line(cairo, config, bar->status, + output->focused, output->width, output->height); + max_height = h > max_height ? h : max_height; + } return max_height > output->height ? max_height : output->height; } @@ -157,6 +209,10 @@ void render_frame(struct swaybar *bar, cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); + cairo_save(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); + cairo_paint(cairo); + cairo_restore(cairo); uint32_t height = render_to_cairo(cairo, bar, output); if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) { height = bar->config->height; diff --git a/swaybar/status_line.c b/swaybar/status_line.c new file mode 100644 index 000000000..ff668c9c4 --- /dev/null +++ b/swaybar/status_line.c @@ -0,0 +1,78 @@ +#define _POSIX_C_SOURCE +#include +#include +#include +#include +#include +#include +#include "swaybar/config.h" +#include "swaybar/status_line.h" +#include "readline.h" + +bool handle_status_readable(struct status_line *status) { + char *line = read_line_buffer(status->read, + status->buffer, status->buffer_size); + switch (status->protocol) { + case PROTOCOL_I3BAR: + // TODO + break; + case PROTOCOL_TEXT: + status->text = line; + return true; + case PROTOCOL_UNDEF: + if (!line) { + return false; + } + if (line[0] == '{') { + // TODO: JSON + } else { + status->text = line; + status->protocol = PROTOCOL_TEXT; + } + return false; + } + return false; +} + +struct status_line *status_line_init(char *cmd) { + struct status_line *status = calloc(1, sizeof(struct status_line)); + status->buffer_size = 4096; + status->buffer = malloc(status->buffer_size); + + int pipe_read_fd[2]; + int pipe_write_fd[2]; + if (pipe(pipe_read_fd) != 0 || pipe(pipe_write_fd) != 0) { + wlr_log(L_ERROR, "Unable to create pipes for status_command fork"); + exit(1); + } + + status->pid = fork(); + if (status->pid == 0) { + dup2(pipe_read_fd[1], STDOUT_FILENO); + close(pipe_read_fd[0]); + 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", cmd, NULL, }; + execvp(_cmd[0], _cmd); + exit(1); + } + + close(pipe_read_fd[1]); + status->read_fd = pipe_read_fd[0]; + fcntl(status->read_fd, F_SETFL, O_NONBLOCK); + close(pipe_write_fd[0]); + status->write_fd = pipe_write_fd[1]; + fcntl(status->write_fd, F_SETFL, O_NONBLOCK); + + status->read = fdopen(status->read_fd, "r"); + status->write = fdopen(status->write_fd, "w"); + return status; +} + +void status_line_free(struct status_line *line) { + free(line); +} From 0464a9910da2b99abea0ab202e179d66260a893b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 15:19:42 -0400 Subject: [PATCH 273/522] Clean up status line on exit --- swaybar/bar.c | 5 +++++ swaybar/status_line.c | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/swaybar/bar.c b/swaybar/bar.c index 72c4be8f5..44f4ee31c 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -191,4 +191,9 @@ void bar_teardown(struct swaybar *bar) { if (bar->config) { free_config(bar->config); } + close(bar->ipc_event_socketfd); + close(bar->ipc_socketfd); + if (bar->status) { + status_line_free(bar->status); + } } diff --git a/swaybar/status_line.c b/swaybar/status_line.c index ff668c9c4..5b131aee5 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -73,6 +73,8 @@ struct status_line *status_line_init(char *cmd) { return status; } -void status_line_free(struct status_line *line) { - free(line); +void status_line_free(struct status_line *status) { + close(status->read_fd); + close(status->write_fd); + free(status); } From da6e48520bad9718a7c4ddf0591474d54736c1c2 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 15:36:52 -0400 Subject: [PATCH 274/522] Tear down bar when display exits --- swaybar/bar.c | 3 ++- swaybar/render.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/swaybar/bar.c b/swaybar/bar.c index 44f4ee31c..afbce7ccf 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -148,7 +148,8 @@ static void render_all_frames(struct swaybar *bar) { 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); + bar_teardown(bar); + exit(0); } } diff --git a/swaybar/render.c b/swaybar/render.c index ec1239a11..a5834f4bb 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -22,7 +22,6 @@ static uint32_t render_status_line_text(cairo_t *cairo, if (!status->text) { return 0; } - //wlr_log(L_DEBUG, "focused %d", focused); cairo_set_source_u32(cairo, focused ? config->colors.focused_statusline : config->colors.statusline); static const int margin = 3; From b72825441b61f56478ef29372a41a6fa72e4c79d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 16:02:59 -0400 Subject: [PATCH 275/522] Fixed laggy focused output boolean --- swaybar/ipc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/swaybar/ipc.c b/swaybar/ipc.c index a260b7988..a82904bda 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -216,9 +216,11 @@ static void free_workspaces(struct wl_list *list) { } void ipc_get_workspaces(struct swaybar *bar) { + bar->focused_output = NULL; struct swaybar_output *output; wl_list_for_each(output, &bar->outputs, link) { free_workspaces(&output->workspaces); + output->focused = false; } uint32_t len = 0; char *res = ipc_single_command(bar->ipc_socketfd, @@ -251,10 +253,6 @@ void ipc_get_workspaces(struct swaybar *bar) { 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); @@ -262,6 +260,7 @@ void ipc_get_workspaces(struct swaybar *bar) { } } } + json_object_put(results); free(res); } From 6836074fed83255438960fdc9597532d8bcae4bd Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 16:51:36 -0400 Subject: [PATCH 276/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 8c9e04dee..f9ab6778b 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 eef5a018c..19c5b5bc6 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 bcf1c4338..6b7404e5e 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 213e7680a..0422fdd9b 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 31679fb2f..187c86643 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 648e79143..81bef7bda 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 977f1ecbc..24e415812 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 156de3807..408ed4321 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; From bf7a4cd0ebd465a0597e9eec0142fad222b396de Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 17:20:03 -0400 Subject: [PATCH 277/522] Add bar configuration commands --- include/sway/commands.h | 3 + include/sway/ipc-server.h | 1 + sway/commands.c | 135 +++++++++++++------- sway/commands/bar.c | 57 +++++++++ sway/commands/bar/activate_button.c | 9 ++ sway/commands/bar/binding_mode_indicator.c | 27 ++++ sway/commands/bar/bindsym.c | 11 ++ sway/commands/bar/colors.c | 129 +++++++++++++++++++ sway/commands/bar/context_button.c | 9 ++ sway/commands/bar/font.c | 26 ++++ sway/commands/bar/height.c | 21 +++ sway/commands/bar/hidden_state.c | 78 +++++++++++ sway/commands/bar/icon_theme.c | 9 ++ sway/commands/bar/id.c | 33 +++++ sway/commands/bar/mode.c | 78 +++++++++++ sway/commands/bar/modifier.c | 35 +++++ sway/commands/bar/output.c | 50 ++++++++ sway/commands/bar/pango_markup.c | 27 ++++ sway/commands/bar/position.c | 29 +++++ sway/commands/bar/secondary_button.c | 9 ++ sway/commands/bar/separator_symbol.c | 21 +++ sway/commands/bar/status_command.c | 21 +++ sway/commands/bar/strip_workspace_numbers.c | 27 ++++ sway/commands/bar/swaybar_command.c | 21 +++ sway/commands/bar/tray_output.c | 9 ++ sway/commands/bar/tray_padding.c | 10 ++ sway/commands/bar/workspace_buttons.c | 27 ++++ sway/commands/bar/wrap_scroll.c | 27 ++++ sway/config.c | 127 ++++++++++++++++++ sway/ipc-server.c | 10 +- sway/meson.build | 25 ++++ 31 files changed, 1051 insertions(+), 50 deletions(-) create mode 100644 sway/commands/bar.c create mode 100644 sway/commands/bar/activate_button.c create mode 100644 sway/commands/bar/binding_mode_indicator.c create mode 100644 sway/commands/bar/bindsym.c create mode 100644 sway/commands/bar/colors.c create mode 100644 sway/commands/bar/context_button.c create mode 100644 sway/commands/bar/font.c create mode 100644 sway/commands/bar/height.c create mode 100644 sway/commands/bar/hidden_state.c create mode 100644 sway/commands/bar/icon_theme.c create mode 100644 sway/commands/bar/id.c create mode 100644 sway/commands/bar/mode.c create mode 100644 sway/commands/bar/modifier.c create mode 100644 sway/commands/bar/output.c create mode 100644 sway/commands/bar/pango_markup.c create mode 100644 sway/commands/bar/position.c create mode 100644 sway/commands/bar/secondary_button.c create mode 100644 sway/commands/bar/separator_symbol.c create mode 100644 sway/commands/bar/status_command.c create mode 100644 sway/commands/bar/strip_workspace_numbers.c create mode 100644 sway/commands/bar/swaybar_command.c create mode 100644 sway/commands/bar/tray_output.c create mode 100644 sway/commands/bar/tray_padding.c create mode 100644 sway/commands/bar/workspace_buttons.c create mode 100644 sway/commands/bar/wrap_scroll.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 9ff18823d..dda286a2c 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -74,6 +74,9 @@ void free_cmd_results(struct cmd_results *results); */ const char *cmd_results_to_json(struct cmd_results *results); +struct cmd_results *add_color(const char *name, + char *buffer, const char *color); + typedef struct cmd_results *sway_cmd(int argc, char **argv); sway_cmd cmd_assign; diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index 6b7404e5e..1f6fffff2 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -12,5 +12,6 @@ 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); +void ipc_event_barconfig_update(struct bar_config *bar); #endif diff --git a/sway/commands.c b/sway/commands.c index b52eb2006..8d8b643b1 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -91,45 +91,9 @@ void apply_seat_config(struct seat_config *seat) { sway_input_manager_apply_seat_config(input_manager, seat); } -/** - * Check and add color to buffer. - * - * return error object, or NULL if color is valid. - */ -struct cmd_results *add_color(const char *name, char *buffer, const char *color) { - int len = strlen(color); - if (len != 7 && len != 9) { - return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); - } - - if (color[0] != '#') { - return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); - } - - int i; - for (i = 1; i < len; ++i) { - if (!isxdigit(color[i])) { - return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); - } - } - - // copy color to buffer - strncpy(buffer, color, len); - // add default alpha channel if color was defined without it - if (len == 7) { - buffer[7] = 'f'; - buffer[8] = 'f'; - } - buffer[9] = '\0'; - - return NULL; -} - -/** - * handlers that can run in either config or command context - * Keep alphabetized - */ +/* Keep alphabetized */ static struct cmd_handler handlers[] = { + { "bar", cmd_bar }, { "bindcode", cmd_bindcode }, { "bindsym", cmd_bindsym }, { "exec", cmd_exec }, @@ -141,18 +105,53 @@ static struct cmd_handler handlers[] = { { "workspace", cmd_workspace }, }; -/** - * Commands that can *only* run in the config loading context - * Keep alphabetized - */ +static struct cmd_handler bar_handlers[] = { + { "activate_button", bar_cmd_activate_button }, + { "binding_mode_indicator", bar_cmd_binding_mode_indicator }, + { "bindsym", bar_cmd_bindsym }, + { "colors", bar_cmd_colors }, + { "context_button", bar_cmd_context_button }, + { "font", bar_cmd_font }, + { "height", bar_cmd_height }, + { "hidden_state", bar_cmd_hidden_state }, + { "icon_theme", bar_cmd_icon_theme }, + { "id", bar_cmd_id }, + { "mode", bar_cmd_mode }, + { "modifier", bar_cmd_modifier }, + { "output", bar_cmd_output }, + { "pango_markup", bar_cmd_pango_markup }, + { "position", bar_cmd_position }, + { "secondary_button", bar_cmd_secondary_button }, + { "separator_symbol", bar_cmd_separator_symbol }, + { "status_command", bar_cmd_status_command }, + { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, + { "swaybar_command", bar_cmd_swaybar_command }, + { "tray_output", bar_cmd_tray_output }, + { "tray_padding", bar_cmd_tray_padding }, + { "workspace_buttons", bar_cmd_workspace_buttons }, + { "wrap_scroll", bar_cmd_wrap_scroll }, +}; + +static struct cmd_handler bar_colors_handlers[] = { + { "active_workspace", bar_colors_cmd_active_workspace }, + { "background", bar_colors_cmd_background }, + { "binding_mode", bar_colors_cmd_binding_mode }, + { "focused_background", bar_colors_cmd_focused_background }, + { "focused_separator", bar_colors_cmd_focused_separator }, + { "focused_statusline", bar_colors_cmd_focused_statusline }, + { "focused_workspace", bar_colors_cmd_focused_workspace }, + { "inactive_workspace", bar_colors_cmd_inactive_workspace }, + { "separator", bar_colors_cmd_separator }, + { "statusline", bar_colors_cmd_statusline }, + { "urgent_workspace", bar_colors_cmd_urgent_workspace }, +}; + +/* Config-time only commands. Keep alphabetized */ static struct cmd_handler config_handlers[] = { { "set", cmd_set }, }; -/** - * Commands that can *not* run in the config loading context - * Keep alphabetized - */ +/* Runtime-only commands. Keep alphabetized */ static struct cmd_handler command_handlers[] = { { "exit", cmd_exit }, { "focus", cmd_focus }, @@ -200,13 +199,19 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { bool config_loading = config->reading || !config->active; - if (block == CMD_BLOCK_INPUT) { - // input commands can run in either context + if (block == CMD_BLOCK_BAR) { + return bsearch(&d, bar_handlers, + sizeof(bar_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + } else if (block == CMD_BLOCK_BAR_COLORS) { + return bsearch(&d, bar_colors_handlers, + sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + } else if (block == CMD_BLOCK_INPUT) { return bsearch(&d, input_handlers, sizeof(input_handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); } else if (block == CMD_BLOCK_SEAT) { - // seat commands can run in either context return bsearch(&d, seat_handlers, sizeof(seat_handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); @@ -558,3 +563,35 @@ const char *cmd_results_to_json(struct cmd_results *results) { free(root); return json; } + +/** + * Check and add color to buffer. + * + * return error object, or NULL if color is valid. + */ +struct cmd_results *add_color(const char *name, + char *buffer, const char *color) { + int len = strlen(color); + if (len != 7 && len != 9) { + return cmd_results_new(CMD_INVALID, name, + "Invalid color definition %s", color); + } + if (color[0] != '#') { + return cmd_results_new(CMD_INVALID, name, + "Invalid color definition %s", color); + } + for (int i = 1; i < len; ++i) { + if (!isxdigit(color[i])) { + return cmd_results_new(CMD_INVALID, name, + "Invalid color definition %s", color); + } + } + strncpy(buffer, color, len); + // add default alpha channel if color was defined without it + if (len == 7) { + buffer[7] = 'f'; + buffer[8] = 'f'; + } + buffer[9] = '\0'; + return NULL; +} diff --git a/sway/commands/bar.c b/sway/commands/bar.c new file mode 100644 index 000000000..548106b3b --- /dev/null +++ b/sway/commands/bar.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "util.h" + +struct cmd_results *cmd_bar(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "bar", EXPECTED_AT_LEAST, 1))) { + return error; + } + + if (config->reading && strcmp("{", argv[0]) != 0) { + return cmd_results_new(CMD_INVALID, "bar", + "Expected '{' at start of bar config definition."); + } + + if (!config->reading) { + if (argc > 1) { + if (strcasecmp("mode", argv[0]) == 0) { + return bar_cmd_mode(argc-1, argv + 1); + } + + if (strcasecmp("hidden_state", argv[0]) == 0) { + return bar_cmd_hidden_state(argc-1, argv + 1); + } + } + return cmd_results_new(CMD_FAILURE, "bar", "Can only be used in config file."); + } + + // Create new bar with default values + struct bar_config *bar = default_bar_config(); + if (!bar) { + return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar state"); + } + + // set bar id + int i; + for (i = 0; i < config->bars->length; ++i) { + if (bar == config->bars->items[i]) { + const int len = 5 + numlen(i); // "bar-" + i + \0 + bar->id = malloc(len * sizeof(char)); + if (bar->id) { + snprintf(bar->id, len, "bar-%d", i); + } else { + return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar ID"); + } + break; + } + } + + // Set current bar + config->current_bar = bar; + wlr_log(L_DEBUG, "Configuring bar %s", bar->id); + return cmd_results_new(CMD_BLOCK_BAR, NULL, NULL); +} diff --git a/sway/commands/bar/activate_button.c b/sway/commands/bar/activate_button.c new file mode 100644 index 000000000..0665d2a69 --- /dev/null +++ b/sway/commands/bar/activate_button.c @@ -0,0 +1,9 @@ +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_activate_button(int argc, char **argv) { + const char *cmd_name = "activate_button"; + // TODO TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); +} diff --git a/sway/commands/bar/binding_mode_indicator.c b/sway/commands/bar/binding_mode_indicator.c new file mode 100644 index 000000000..e11e1033b --- /dev/null +++ b/sway/commands/bar/binding_mode_indicator.c @@ -0,0 +1,27 @@ +#include +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "binding_mode_indicator", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "binding_mode_indicator", "No bar defined."); + } + + if (strcasecmp("yes", argv[0]) == 0) { + config->current_bar->binding_mode_indicator = true; + wlr_log(L_DEBUG, "Enabling binding mode indicator on bar: %s", config->current_bar->id); + } else if (strcasecmp("no", argv[0]) == 0) { + config->current_bar->binding_mode_indicator = false; + wlr_log(L_DEBUG, "Disabling binding mode indicator on bar: %s", config->current_bar->id); + } else { + error = cmd_results_new(CMD_INVALID, "binding_mode_indicator", "Invalid value %s", argv[0]); + return error; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/bindsym.c b/sway/commands/bar/bindsym.c new file mode 100644 index 000000000..ac09a03ff --- /dev/null +++ b/sway/commands/bar/bindsym.c @@ -0,0 +1,11 @@ +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "list.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { + return cmd_results_new(CMD_FAILURE, "bindsym", "TODO"); // TODO +} diff --git a/sway/commands/bar/colors.c b/sway/commands/bar/colors.c new file mode 100644 index 000000000..8b3b0aacb --- /dev/null +++ b/sway/commands/bar/colors.c @@ -0,0 +1,129 @@ +#include +#include "sway/commands.h" + +static struct cmd_results *parse_single_color(char **color, const char *cmd_name, int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!*color) { + *color = malloc(10); + if (!*color) { + return cmd_results_new(CMD_FAILURE, cmd_name, "Unable to allocate color"); + } + } + + error = add_color(cmd_name, *color, argv[0]); + if (error) { + return error; + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +static struct cmd_results *parse_three_colors(char ***colors, const char *cmd_name, int argc, char **argv) { + struct cmd_results *error = NULL; + if (argc != 3) { + return cmd_results_new(CMD_INVALID, cmd_name, "Requires exactly three color values"); + } + + int i; + for (i = 0; i < 3; i++) { + if (!*colors[i]) { + *(colors[i]) = malloc(10); + if (!*(colors[i])) { + return cmd_results_new(CMD_FAILURE, cmd_name, "Unable to allocate color"); + } + } + error = add_color(cmd_name, *(colors[i]), argv[i]); + if (error) { + return error; + } + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *bar_cmd_colors(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "colors", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (strcmp("{", argv[0]) != 0) { + return cmd_results_new(CMD_INVALID, "colors", + "Expected '{' at the start of colors config definition."); + } + + return cmd_results_new(CMD_BLOCK_BAR_COLORS, NULL, NULL); +} + +struct cmd_results *bar_colors_cmd_active_workspace(int argc, char **argv) { + char **colors[3] = { + &(config->current_bar->colors.active_workspace_border), + &(config->current_bar->colors.active_workspace_bg), + &(config->current_bar->colors.active_workspace_text) + }; + return parse_three_colors(colors, "active_workspace", argc, argv); +} + +struct cmd_results *bar_colors_cmd_background(int argc, char **argv) { + return parse_single_color(&(config->current_bar->colors.background), "background", argc, argv); +} + +struct cmd_results *bar_colors_cmd_focused_background(int argc, char **argv) { + return parse_single_color(&(config->current_bar->colors.focused_background), "focused_background", argc, argv); +} + +struct cmd_results *bar_colors_cmd_binding_mode(int argc, char **argv) { + char **colors[3] = { + &(config->current_bar->colors.binding_mode_border), + &(config->current_bar->colors.binding_mode_bg), + &(config->current_bar->colors.binding_mode_text) + }; + return parse_three_colors(colors, "binding_mode", argc, argv); +} + +struct cmd_results *bar_colors_cmd_focused_workspace(int argc, char **argv) { + char **colors[3] = { + &(config->current_bar->colors.focused_workspace_border), + &(config->current_bar->colors.focused_workspace_bg), + &(config->current_bar->colors.focused_workspace_text) + }; + return parse_three_colors(colors, "focused_workspace", argc, argv); +} + +struct cmd_results *bar_colors_cmd_inactive_workspace(int argc, char **argv) { + char **colors[3] = { + &(config->current_bar->colors.inactive_workspace_border), + &(config->current_bar->colors.inactive_workspace_bg), + &(config->current_bar->colors.inactive_workspace_text) + }; + return parse_three_colors(colors, "inactive_workspace", argc, argv); +} + +struct cmd_results *bar_colors_cmd_separator(int argc, char **argv) { + return parse_single_color(&(config->current_bar->colors.separator), "separator", argc, argv); +} + +struct cmd_results *bar_colors_cmd_focused_separator(int argc, char **argv) { + return parse_single_color(&(config->current_bar->colors.focused_separator), "focused_separator", argc, argv); +} + +struct cmd_results *bar_colors_cmd_statusline(int argc, char **argv) { + return parse_single_color(&(config->current_bar->colors.statusline), "statusline", argc, argv); +} + +struct cmd_results *bar_colors_cmd_focused_statusline(int argc, char **argv) { + return parse_single_color(&(config->current_bar->colors.focused_separator), "focused_separator", argc, argv); +} + +struct cmd_results *bar_colors_cmd_urgent_workspace(int argc, char **argv) { + char **colors[3] = { + &(config->current_bar->colors.urgent_workspace_border), + &(config->current_bar->colors.urgent_workspace_bg), + &(config->current_bar->colors.urgent_workspace_text) + }; + return parse_three_colors(colors, "urgent_workspace", argc, argv); +} diff --git a/sway/commands/bar/context_button.c b/sway/commands/bar/context_button.c new file mode 100644 index 000000000..e6d17f10b --- /dev/null +++ b/sway/commands/bar/context_button.c @@ -0,0 +1,9 @@ +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_context_button(int argc, char **argv) { + const char *cmd_name = "context_button"; + // TODO TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); +} diff --git a/sway/commands/bar/font.c b/sway/commands/bar/font.c new file mode 100644 index 000000000..6d7c533ad --- /dev/null +++ b/sway/commands/bar/font.c @@ -0,0 +1,26 @@ +#include +#include "sway/commands.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *bar_cmd_font(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "font", EXPECTED_AT_LEAST, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "font", "No bar defined."); + } + + char *font = join_args(argv, argc); + free(config->current_bar->font); + if (strlen(font) > 6 && strncmp("pango:", font, 6) == 0) { + config->current_bar->font = font; + } else { + config->current_bar->font = font; + } + + wlr_log(L_DEBUG, "Settings font '%s' for bar: %s", config->current_bar->font, config->current_bar->id); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/height.c b/sway/commands/bar/height.c new file mode 100644 index 000000000..ae0c7834f --- /dev/null +++ b/sway/commands/bar/height.c @@ -0,0 +1,21 @@ +#include +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_height(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "height", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + int height = atoi(argv[0]); + if (height < 0) { + return cmd_results_new(CMD_INVALID, "height", + "Invalid height value: %s", argv[0]); + } + + config->current_bar->height = height; + wlr_log(L_DEBUG, "Setting bar height to %d on bar: %s", height, config->current_bar->id); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c new file mode 100644 index 000000000..245d0858d --- /dev/null +++ b/sway/commands/bar/hidden_state.c @@ -0,0 +1,78 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/ipc-server.h" +#include "log.h" + +static struct cmd_results *bar_set_hidden_state(struct bar_config *bar, + const char *hidden_state) { + char *old_state = bar->hidden_state; + if (strcasecmp("toggle", hidden_state) == 0 && !config->reading) { + if (strcasecmp("hide", bar->hidden_state) == 0) { + bar->hidden_state = strdup("show"); + } else if (strcasecmp("show", bar->hidden_state) == 0) { + bar->hidden_state = strdup("hide"); + } + } else if (strcasecmp("hide", hidden_state) == 0) { + bar->hidden_state = strdup("hide"); + } else if (strcasecmp("show", hidden_state) == 0) { + bar->hidden_state = strdup("show"); + } else { + return cmd_results_new(CMD_INVALID, "hidden_state", + "Invalid value %s", hidden_state); + } + + if (strcmp(old_state, bar->hidden_state) != 0) { + if (!config->reading) { + ipc_event_barconfig_update(bar); + } + wlr_log(L_DEBUG, "Setting hidden_state: '%s' for bar: %s", + bar->hidden_state, bar->id); + } + + // free old mode + free(old_state); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "hidden_state", EXPECTED_AT_LEAST, 1))) { + return error; + } + if ((error = checkarg(argc, "hidden_state", EXPECTED_LESS_THAN, 3))) { + return error; + } + + if (config->reading && argc > 1) { + return cmd_results_new(CMD_INVALID, "hidden_state", + "Unexpected value %s in config mode", argv[1]); + } + + const char *state = argv[0]; + + if (config->reading) { + return bar_set_hidden_state(config->current_bar, state); + } + + const char *id = NULL; + if (argc == 2) { + id = argv[1]; + } + + struct bar_config *bar; + for (int i = 0; i < config->bars->length; ++i) { + bar = config->bars->items[i]; + if (id && strcmp(id, bar->id) == 0) { + return bar_set_hidden_state(bar, state); + } + + error = bar_set_hidden_state(bar, state); + if (error) { + return error; + } + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/icon_theme.c b/sway/commands/bar/icon_theme.c new file mode 100644 index 000000000..c6090b81c --- /dev/null +++ b/sway/commands/bar/icon_theme.c @@ -0,0 +1,9 @@ +#define _XOPEN_SOURCE 500 +#include +#include "sway/commands.h" + +struct cmd_results *bar_cmd_icon_theme(int argc, char **argv) { + const char *cmd_name = "tray_output"; + // TODO TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); +} diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c new file mode 100644 index 000000000..d9e7f8df1 --- /dev/null +++ b/sway/commands/bar/id.c @@ -0,0 +1,33 @@ +#define _XOPEN_SOURCE 500 +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_id(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "id", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + const char *name = argv[0]; + const char *oldname = config->current_bar->id; + + // check if id is used by a previously defined bar + int i; + for (i = 0; i < config->bars->length; ++i) { + struct bar_config *find = config->bars->items[i]; + if (strcmp(name, find->id) == 0 && config->current_bar != find) { + return cmd_results_new(CMD_FAILURE, "id", + "Id '%s' already defined for another bar. Id unchanged (%s).", + name, oldname); + } + } + + wlr_log(L_DEBUG, "Renaming bar: '%s' to '%s'", oldname, name); + + // free old bar id + free(config->current_bar->id); + + config->current_bar->id = strdup(name); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c new file mode 100644 index 000000000..7d346956b --- /dev/null +++ b/sway/commands/bar/mode.c @@ -0,0 +1,78 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/ipc-server.h" +#include "log.h" + +static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode) { + char *old_mode = bar->mode; + if (strcasecmp("toggle", mode) == 0 && !config->reading) { + if (strcasecmp("dock", bar->mode) == 0) { + bar->mode = strdup("hide"); + } else if (strcasecmp("hide", bar->mode) == 0) { + bar->mode = strdup("dock"); + } + } else if (strcasecmp("dock", mode) == 0) { + bar->mode = strdup("dock"); + } else if (strcasecmp("hide", mode) == 0) { + bar->mode = strdup("hide"); + } else if (strcasecmp("invisible", mode) == 0) { + bar->mode = strdup("invisible"); + } else { + return cmd_results_new(CMD_INVALID, "mode", "Invalid value %s", mode); + } + + if (strcmp(old_mode, bar->mode) != 0) { + if (!config->reading) { + ipc_event_barconfig_update(bar); + } + wlr_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id); + } + + // free old mode + free(old_mode); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *bar_cmd_mode(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "mode", EXPECTED_AT_LEAST, 1))) { + return error; + } + if ((error = checkarg(argc, "mode", EXPECTED_LESS_THAN, 3))) { + return error; + } + + if (config->reading && argc > 1) { + return cmd_results_new(CMD_INVALID, "mode", "Unexpected value %s in config mode", argv[1]); + } + + const char *mode = argv[0]; + + if (config->reading) { + return bar_set_mode(config->current_bar, mode); + } + + const char *id = NULL; + if (argc == 2) { + id = argv[1]; + } + + int i; + struct bar_config *bar; + for (i = 0; i < config->bars->length; ++i) { + bar = config->bars->items[i]; + if (id && strcmp(id, bar->id) == 0) { + return bar_set_mode(bar, mode); + } + + error = bar_set_mode(bar, mode); + if (error) { + return error; + } + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/modifier.c b/sway/commands/bar/modifier.c new file mode 100644 index 000000000..9a1f8b01b --- /dev/null +++ b/sway/commands/bar/modifier.c @@ -0,0 +1,35 @@ +#include +#include "sway/commands.h" +#include "log.h" +#include "stringop.h" +#include "util.h" + +struct cmd_results *bar_cmd_modifier(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "modifier", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "modifier", "No bar defined."); + } + + uint32_t mod = 0; + + list_t *split = split_string(argv[0], "+"); + for (int i = 0; i < split->length; ++i) { + uint32_t tmp_mod; + if ((tmp_mod = get_modifier_mask_by_name(split->items[i])) > 0) { + mod |= tmp_mod; + continue; + } else { + free_flat_list(split); + return cmd_results_new(CMD_INVALID, "modifier", "Unknown modifier '%s'", split->items[i]); + } + } + free_flat_list(split); + + config->current_bar->modifier = mod; + wlr_log(L_DEBUG, "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/output.c b/sway/commands/bar/output.c new file mode 100644 index 000000000..034d9ca4c --- /dev/null +++ b/sway/commands/bar/output.c @@ -0,0 +1,50 @@ +#define _XOPEN_SOURCE 500 +#include +#include "sway/commands.h" +#include "list.h" +#include "log.h" + +struct cmd_results *bar_cmd_output(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "output", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "output", "No bar defined."); + } + + const char *output = argv[0]; + list_t *outputs = config->current_bar->outputs; + if (!outputs) { + outputs = create_list(); + config->current_bar->outputs = outputs; + } + + int i; + int add_output = 1; + if (strcmp("*", output) == 0) { + // remove all previous defined outputs and replace with '*' + for (i = 0; i < outputs->length; ++i) { + free(outputs->items[i]); + list_del(outputs, i); + } + } else { + // only add output if not already defined with either the same + // name or as '*' + for (i = 0; i < outputs->length; ++i) { + const char *find = outputs->items[i]; + if (strcmp("*", find) == 0 || strcmp(output, find) == 0) { + add_output = 0; + break; + } + } + } + + if (add_output) { + list_add(outputs, strdup(output)); + wlr_log(L_DEBUG, "Adding bar: '%s' to output '%s'", config->current_bar->id, output); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/pango_markup.c b/sway/commands/bar/pango_markup.c new file mode 100644 index 000000000..34b85e984 --- /dev/null +++ b/sway/commands/bar/pango_markup.c @@ -0,0 +1,27 @@ +#include +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "pango_markup", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "pango_markup", "No bar defined."); + } + + if (strcasecmp("enabled", argv[0]) == 0) { + config->current_bar->pango_markup = true; + wlr_log(L_DEBUG, "Enabling pango markup for bar: %s", config->current_bar->id); + } else if (strcasecmp("disabled", argv[0]) == 0) { + config->current_bar->pango_markup = false; + wlr_log(L_DEBUG, "Disabling pango markup for bar: %s", config->current_bar->id); + } else { + error = cmd_results_new(CMD_INVALID, "pango_markup", "Invalid value %s", argv[0]); + return error; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/position.c b/sway/commands/bar/position.c new file mode 100644 index 000000000..efa8c0bc8 --- /dev/null +++ b/sway/commands/bar/position.c @@ -0,0 +1,29 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_position(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "position", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "position", "No bar defined."); + } + + char *valid[] = { "top", "bottom", "left", "right" }; + for (size_t i = 0; i < sizeof(valid) / sizeof(valid[0]); ++i) { + if (strcasecmp(valid[i], argv[0]) == 0) { + wlr_log(L_DEBUG, "Setting bar position '%s' for bar: %s", + argv[0], config->current_bar->id); + config->current_bar->position = strdup(argv[0]); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + } + + error = cmd_results_new(CMD_INVALID, "position", "Invalid value %s", argv[0]); + return error; +} diff --git a/sway/commands/bar/secondary_button.c b/sway/commands/bar/secondary_button.c new file mode 100644 index 000000000..46d53e3ff --- /dev/null +++ b/sway/commands/bar/secondary_button.c @@ -0,0 +1,9 @@ +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_secondary_button(int argc, char **argv) { + const char *cmd_name = "secondary_button"; + // TODO TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); +} diff --git a/sway/commands/bar/separator_symbol.c b/sway/commands/bar/separator_symbol.c new file mode 100644 index 000000000..7dc0956b9 --- /dev/null +++ b/sway/commands/bar/separator_symbol.c @@ -0,0 +1,21 @@ +#define _XOPEN_SOURCE 500 +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_separator_symbol(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "separator_symbol", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "separator_symbol", "No bar defined."); + } + + free(config->current_bar->separator_symbol); + config->current_bar->separator_symbol = strdup(argv[0]); + wlr_log(L_DEBUG, "Settings separator_symbol '%s' for bar: %s", config->current_bar->separator_symbol, config->current_bar->id); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/status_command.c b/sway/commands/bar/status_command.c new file mode 100644 index 000000000..05377fcca --- /dev/null +++ b/sway/commands/bar/status_command.c @@ -0,0 +1,21 @@ +#include +#include "sway/commands.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *bar_cmd_status_command(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "status_command", EXPECTED_AT_LEAST, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "status_command", "No bar defined."); + } + + free(config->current_bar->status_command); + config->current_bar->status_command = join_args(argv, argc); + wlr_log(L_DEBUG, "Feeding bar with status command: %s", config->current_bar->status_command); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/strip_workspace_numbers.c b/sway/commands/bar/strip_workspace_numbers.c new file mode 100644 index 000000000..0558db8fd --- /dev/null +++ b/sway/commands/bar/strip_workspace_numbers.c @@ -0,0 +1,27 @@ +#include +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "strip_workspace_numbers", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "strip_workspace_numbers", "No bar defined."); + } + + if (strcasecmp("yes", argv[0]) == 0) { + config->current_bar->strip_workspace_numbers = true; + wlr_log(L_DEBUG, "Stripping workspace numbers on bar: %s", config->current_bar->id); + } else if (strcasecmp("no", argv[0]) == 0) { + config->current_bar->strip_workspace_numbers = false; + wlr_log(L_DEBUG, "Enabling workspace numbers on bar: %s", config->current_bar->id); + } else { + error = cmd_results_new(CMD_INVALID, "strip_workspace_numbers", "Invalid value %s", argv[0]); + return error; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/swaybar_command.c b/sway/commands/bar/swaybar_command.c new file mode 100644 index 000000000..63d4f29a2 --- /dev/null +++ b/sway/commands/bar/swaybar_command.c @@ -0,0 +1,21 @@ +#include +#include "sway/commands.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *bar_cmd_swaybar_command(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "swaybar_command", EXPECTED_AT_LEAST, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "swaybar_command", "No bar defined."); + } + + free(config->current_bar->swaybar_command); + config->current_bar->swaybar_command = join_args(argv, argc); + wlr_log(L_DEBUG, "Using custom swaybar command: %s", config->current_bar->swaybar_command); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/tray_output.c b/sway/commands/bar/tray_output.c new file mode 100644 index 000000000..2d8221461 --- /dev/null +++ b/sway/commands/bar/tray_output.c @@ -0,0 +1,9 @@ +#define _XOPEN_SOURCE 500 +#include +#include "sway/commands.h" + +struct cmd_results *bar_cmd_tray_output(int argc, char **argv) { + const char *cmd_name = "tray_output"; + // TODO TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); +} diff --git a/sway/commands/bar/tray_padding.c b/sway/commands/bar/tray_padding.c new file mode 100644 index 000000000..95b8ad3b3 --- /dev/null +++ b/sway/commands/bar/tray_padding.c @@ -0,0 +1,10 @@ +#include +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_tray_padding(int argc, char **argv) { + const char *cmd_name = "tray_padding"; + // TODO TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); +} diff --git a/sway/commands/bar/workspace_buttons.c b/sway/commands/bar/workspace_buttons.c new file mode 100644 index 000000000..1a617eb8f --- /dev/null +++ b/sway/commands/bar/workspace_buttons.c @@ -0,0 +1,27 @@ +#include +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "workspace_buttons", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "workspace_buttons", "No bar defined."); + } + + if (strcasecmp("yes", argv[0]) == 0) { + config->current_bar->workspace_buttons = true; + wlr_log(L_DEBUG, "Enabling workspace buttons on bar: %s", config->current_bar->id); + } else if (strcasecmp("no", argv[0]) == 0) { + config->current_bar->workspace_buttons = false; + wlr_log(L_DEBUG, "Disabling workspace buttons on bar: %s", config->current_bar->id); + } else { + error = cmd_results_new(CMD_INVALID, "workspace_buttons", "Invalid value %s", argv[0]); + return error; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/wrap_scroll.c b/sway/commands/bar/wrap_scroll.c new file mode 100644 index 000000000..c89dff5f8 --- /dev/null +++ b/sway/commands/bar/wrap_scroll.c @@ -0,0 +1,27 @@ +#include +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "wrap_scroll", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "wrap_scroll", "No bar defined."); + } + + if (strcasecmp("yes", argv[0]) == 0) { + config->current_bar->wrap_scroll = true; + wlr_log(L_DEBUG, "Enabling wrap scroll on bar: %s", config->current_bar->id); + } else if (strcasecmp("no", argv[0]) == 0) { + config->current_bar->wrap_scroll = false; + wlr_log(L_DEBUG, "Disabling wrap scroll on bar: %s", config->current_bar->id); + } else { + error = cmd_results_new(CMD_INVALID, "wrap_scroll", "Invalid value %s", argv[0]); + return error; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 0422fdd9b..a0e408de1 100644 --- a/sway/config.c +++ b/sway/config.c @@ -110,6 +110,48 @@ 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; @@ -239,6 +281,91 @@ 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/ipc-server.c b/sway/ipc-server.c index 408ed4321..59fc05f94 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -313,10 +313,18 @@ void ipc_event_window(swayc_t *window, const char *change) { const char *json_string = json_object_to_json_string(obj); ipc_send_event(json_string, IPC_EVENT_WINDOW); - json_object_put(obj); // free } +void ipc_event_barconfig_update(struct bar_config *bar) { + wlr_log(L_DEBUG, "Sending barconfig_update event"); + json_object *json = ipc_json_describe_bar_config(bar); + + const char *json_string = json_object_to_json_string(json); + ipc_send_event(json_string, IPC_EVENT_BARCONFIG_UPDATE); + json_object_put(json); // free +} + int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; diff --git a/sway/meson.build b/sway/meson.build index 8bddb11ba..8fcb0dbf5 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/bar.c', 'commands/bind.c', 'commands/exit.c', 'commands/exec.c', @@ -19,6 +20,30 @@ sway_sources = files( 'commands/seat/attach.c', 'commands/seat/fallback.c', 'commands/set.c', + 'commands/bar/activate_button.c', + 'commands/bar/binding_mode_indicator.c', + 'commands/bar/bindsym.c', + 'commands/bar/colors.c', + 'commands/bar/context_button.c', + 'commands/bar/font.c', + 'commands/bar/height.c', + 'commands/bar/hidden_state.c', + 'commands/bar/icon_theme.c', + 'commands/bar/id.c', + 'commands/bar/mode.c', + 'commands/bar/modifier.c', + 'commands/bar/output.c', + 'commands/bar/pango_markup.c', + 'commands/bar/position.c', + 'commands/bar/secondary_button.c', + 'commands/bar/separator_symbol.c', + 'commands/bar/status_command.c', + 'commands/bar/strip_workspace_numbers.c', + 'commands/bar/swaybar_command.c', + 'commands/bar/tray_output.c', + 'commands/bar/tray_padding.c', + 'commands/bar/workspace_buttons.c', + 'commands/bar/wrap_scroll.c', 'commands/input/accel_profile.c', 'commands/input/click_method.c', 'commands/input/drag_lock.c', From 569b2bfd5daae5b3be49772bdca4a3f224e20629 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 17:41:02 -0400 Subject: [PATCH 278/522] 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 diff --git a/include/sway/config.h b/include/sway/config.h index f9ab6778b..dbcfc91e1 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 a0e408de1..0422fdd9b 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 000000000..ecc357d03 --- /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 9e2118614..24b4a18e2 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 8fcb0dbf5..ac65d05eb 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', From 5c9cdbcdd2a07e2ced7b60d629a3e20bd7c8bf68 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 17:49:44 -0400 Subject: [PATCH 279/522] 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 diff --git a/include/sway/commands.h b/include/sway/commands.h index dda286a2c..1291d5fb6 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 dbcfc91e1..4a7fee0fb 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 8d8b643b1..38e2f764d 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 000000000..770d48214 --- /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 24b4a18e2..c3ec61b71 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 ac65d05eb..54c03061a 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 6c9bce7ad..900e499aa 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). From 2719ddfe5e171881f3997f9f853bfca97fe01529 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 18:07:03 -0400 Subject: [PATCH 280/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 4a7fee0fb..b7820128d 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 ecc357d03..5e02c01ce 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 92f72f13f..75202df2c 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 bbafe9ec1..64e2bdee1 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); From 2e84f21ab786a5e31de836fda4e8bbd6de08d0ec Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 18:08:23 -0400 Subject: [PATCH 281/522] Terminate swaybar when freeing bar config --- sway/config/bar.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sway/config/bar.c b/sway/config/bar.c index 5e02c01ce..10abdef7e 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -15,6 +15,16 @@ #include "list.h" #include "log.h" +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); + } +} + void free_bar_config(struct bar_config *bar) { if (!bar) { return; @@ -31,7 +41,7 @@ void free_bar_config(struct bar_config *bar) { free_flat_list(bar->outputs); } if (bar->pid != 0) { - // TODO terminate_swaybar(bar->pid); + terminate_swaybar(bar->pid); } free(bar->colors.background); free(bar->colors.statusline); @@ -191,16 +201,6 @@ void invoke_swaybar(struct bar_config *bar) { 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) { From 8b5b72c576b59c875fc10f8ae88d9643c9797c39 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 18:09:42 -0400 Subject: [PATCH 282/522] Restart swaybar on config reload --- sway/commands/reload.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/commands/reload.c b/sway/commands/reload.c index d54d40db6..a06a9aa05 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -11,8 +11,7 @@ struct cmd_results *cmd_reload(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); } - /* load_swaybars(); -- for when it's implemented */ - + load_swaybars(); arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From 5f5076baffa34a9e0d3e33c8fd5ce7c8e8bdeb2d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 18:24:29 -0400 Subject: [PATCH 283/522] Call arrange_windows on layer destroy --- sway/desktop/layer_shell.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 187c86643..d8ce0db18 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -81,6 +81,7 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, &full_area.width, &full_area.height); wl_list_for_each(sway_layer, list, link) { struct wlr_layer_surface *layer = sway_layer->layer_surface; + wlr_log(L_DEBUG, "arranging layer %p %s", sway_layer, layer->namespace); struct wlr_layer_surface_state *state = &layer->current; if (exclusive != (state->exclusive_zone > 0)) { continue; @@ -168,7 +169,10 @@ void arrange_layers(struct sway_output *output) { &usable_area, true); memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); - arrange_windows(output->swayc, -1, -1); + if (memcmp(&usable_area, &output->usable_area, + sizeof(struct wlr_box)) != 0) { + arrange_windows(output->swayc, -1, -1); + } // Arrange non-exlusive surfaces from top->bottom usable_area.x = usable_area.y = 0; @@ -216,7 +220,8 @@ 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"); + wlr_log(L_DEBUG, "Layer surface destroyed (%s)", + sway_layer->layer_surface->namespace); if (sway_layer->layer_surface->mapped) { unmap(sway_layer->layer_surface); } @@ -231,6 +236,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = sway_layer->layer_surface->output->data; free(sway_layer); arrange_layers(output); + arrange_windows(output->swayc, -1, -1); } static void handle_map(struct wl_listener *listener, void *data) { From f3fbf193127507e5ec5d23587c3e521ac2eb5891 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 21:09:34 -0400 Subject: [PATCH 284/522] Do some small cleanup - Fix workspace events (security config isn't in use so it wasn't being sent) - Kill status bar process when swaybar exits - Don't rearrange windows on every layer surface commit --- sway/desktop/layer_shell.c | 2 +- sway/ipc-server.c | 23 ----------------------- swaybar/status_line.c | 1 + 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index d8ce0db18..a5cd79baf 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -204,8 +204,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { if (wlr_output != NULL) { struct sway_output *output = wlr_output->data; struct wlr_box old_geo = layer->geo; - arrange_layers(output); if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { + arrange_layers(output); // TODO DAMAGE apply whole surface from previous and new geos } else { // TODO DAMAGE from surface damage diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 59fc05f94..8250b3a03 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -242,33 +242,10 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { } static void ipc_send_event(const char *json_string, enum ipc_command_type event) { - static struct { - enum ipc_command_type event; - enum ipc_feature feature; - } security_mappings[] = { - { IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE }, - { IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT }, - { IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE }, - { IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW }, - { IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING }, - { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT } - }; - - uint32_t security_mask = 0; - for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) { - if (security_mappings[i].event == event) { - security_mask = security_mappings[i].feature; - break; - } - } - int i; struct ipc_client *client; for (i = 0; i < ipc_client_list->length; i++) { client = ipc_client_list->items[i]; - if (!(client->security_policy & security_mask)) { - continue; - } if ((client->subscribed_events & event_mask(event)) == 0) { continue; } diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 5b131aee5..3454f2072 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -76,5 +76,6 @@ struct status_line *status_line_init(char *cmd) { void status_line_free(struct status_line *status) { close(status->read_fd); close(status->write_fd); + kill(status->pid, SIGTERM); free(status); } From c91adbd188414c12f5c30d94790e3495532653a1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 21:28:31 -0400 Subject: [PATCH 285/522] Fix failure to rearrange output in some cases --- sway/desktop/layer_shell.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index a5cd79baf..bf76b0753 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -81,7 +81,6 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, &full_area.width, &full_area.height); wl_list_for_each(sway_layer, list, link) { struct wlr_layer_surface *layer = sway_layer->layer_surface; - wlr_log(L_DEBUG, "arranging layer %p %s", sway_layer, layer->namespace); struct wlr_layer_surface_state *state = &layer->current; if (exclusive != (state->exclusive_zone > 0)) { continue; @@ -167,10 +166,11 @@ void arrange_layers(struct sway_output *output) { &usable_area, true); arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &usable_area, true); - memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); if (memcmp(&usable_area, &output->usable_area, sizeof(struct wlr_box)) != 0) { + wlr_log(L_DEBUG, "Usable area changed, rearranging output"); + memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); arrange_windows(output->swayc, -1, -1); } @@ -204,8 +204,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { if (wlr_output != NULL) { struct sway_output *output = wlr_output->data; struct wlr_box old_geo = layer->geo; + arrange_layers(output); if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { - arrange_layers(output); // TODO DAMAGE apply whole surface from previous and new geos } else { // TODO DAMAGE from surface damage @@ -236,7 +236,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = sway_layer->layer_surface->output->data; free(sway_layer); arrange_layers(output); - arrange_windows(output->swayc, -1, -1); } static void handle_map(struct wl_listener *listener, void *data) { From 849c3515abff7033dbd4723fd7328cb07af74222 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 21:54:08 -0400 Subject: [PATCH 286/522] Use statically allocated text buffer --- common/pango.c | 6 ++---- sway/commands/bar.c | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/common/pango.c b/common/pango.c index 212d96cfa..2ae7883c0 100644 --- a/common/pango.c +++ b/common/pango.c @@ -32,7 +32,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, 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); + static char buf[2048]; va_list args; va_start(args, fmt); @@ -45,12 +45,11 @@ void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, 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); + static char buf[2048]; va_list args; va_start(args, fmt); @@ -63,5 +62,4 @@ void pango_printf(cairo_t *cairo, const char *font, pango_cairo_update_layout(cairo, layout); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); - free(buf); } diff --git a/sway/commands/bar.c b/sway/commands/bar.c index 548106b3b..ff111163e 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -36,15 +36,15 @@ struct cmd_results *cmd_bar(int argc, char **argv) { } // set bar id - int i; - for (i = 0; i < config->bars->length; ++i) { + for (int i = 0; i < config->bars->length; ++i) { if (bar == config->bars->items[i]) { const int len = 5 + numlen(i); // "bar-" + i + \0 bar->id = malloc(len * sizeof(char)); if (bar->id) { snprintf(bar->id, len, "bar-%d", i); } else { - return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar ID"); + return cmd_results_new(CMD_FAILURE, + "bar", "Unable to allocate bar ID"); } break; } From 741424c4e7811c12d8cca28466f89bd61eaf3a75 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 22:05:16 -0400 Subject: [PATCH 287/522] Clean up imported bar commands --- sway/commands/bar/activate_button.c | 3 +- sway/commands/bar/binding_mode_indicator.c | 20 ++++---- sway/commands/bar/colors.c | 51 ++++++++++----------- sway/commands/bar/context_button.c | 3 +- sway/commands/bar/font.c | 13 ++---- sway/commands/bar/height.c | 5 +- sway/commands/bar/hidden_state.c | 5 -- sway/commands/bar/icon_theme.c | 3 +- sway/commands/bar/id.c | 5 +- sway/commands/bar/mode.c | 10 ++-- sway/commands/bar/modifier.c | 8 ++-- sway/commands/bar/output.c | 15 +++--- sway/commands/bar/pango_markup.c | 11 +++-- sway/commands/bar/position.c | 7 +-- sway/commands/bar/secondary_button.c | 3 +- sway/commands/bar/separator_symbol.c | 9 ++-- sway/commands/bar/status_command.c | 9 ++-- sway/commands/bar/strip_workspace_numbers.c | 18 ++++---- sway/commands/bar/swaybar_command.c | 9 ++-- sway/commands/bar/tray_output.c | 3 +- sway/commands/bar/tray_padding.c | 3 +- sway/commands/bar/workspace_buttons.c | 15 +++--- sway/commands/bar/wrap_scroll.c | 12 ++--- 23 files changed, 104 insertions(+), 136 deletions(-) diff --git a/sway/commands/bar/activate_button.c b/sway/commands/bar/activate_button.c index 0665d2a69..7310e7eca 100644 --- a/sway/commands/bar/activate_button.c +++ b/sway/commands/bar/activate_button.c @@ -3,7 +3,6 @@ #include "log.h" struct cmd_results *bar_cmd_activate_button(int argc, char **argv) { - const char *cmd_name = "activate_button"; // TODO TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); + return cmd_results_new(CMD_INVALID, "activate_button", "TODO TRAY"); } diff --git a/sway/commands/bar/binding_mode_indicator.c b/sway/commands/bar/binding_mode_indicator.c index e11e1033b..3ba5f33f8 100644 --- a/sway/commands/bar/binding_mode_indicator.c +++ b/sway/commands/bar/binding_mode_indicator.c @@ -5,23 +5,23 @@ struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { struct cmd_results *error = NULL; - if ((error = checkarg(argc, "binding_mode_indicator", EXPECTED_EQUAL_TO, 1))) { + if ((error = checkarg(argc, + "binding_mode_indicator", EXPECTED_EQUAL_TO, 1))) { return error; } - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "binding_mode_indicator", "No bar defined."); + return cmd_results_new(CMD_FAILURE, + "binding_mode_indicator", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { config->current_bar->binding_mode_indicator = true; - wlr_log(L_DEBUG, "Enabling binding mode indicator on bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Enabling binding mode indicator on bar: %s", + config->current_bar->id); } else if (strcasecmp("no", argv[0]) == 0) { config->current_bar->binding_mode_indicator = false; - wlr_log(L_DEBUG, "Disabling binding mode indicator on bar: %s", config->current_bar->id); - } else { - error = cmd_results_new(CMD_INVALID, "binding_mode_indicator", "Invalid value %s", argv[0]); - return error; + wlr_log(L_DEBUG, "Disabling binding mode indicator on bar: %s", + config->current_bar->id); } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); + return cmd_results_new(CMD_INVALID, "binding_mode_indicator", + "Invalid value %s", argv[0]); } diff --git a/sway/commands/bar/colors.c b/sway/commands/bar/colors.c index 8b3b0aacb..17ba9b7cf 100644 --- a/sway/commands/bar/colors.c +++ b/sway/commands/bar/colors.c @@ -1,47 +1,38 @@ #include #include "sway/commands.h" -static struct cmd_results *parse_single_color(char **color, const char *cmd_name, int argc, char **argv) { +static struct cmd_results *parse_single_color(char **color, + const char *cmd_name, int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { return error; } - - if (!*color) { - *color = malloc(10); - if (!*color) { - return cmd_results_new(CMD_FAILURE, cmd_name, "Unable to allocate color"); - } + if (!*color && !(*color = malloc(10))) { + return NULL; } - error = add_color(cmd_name, *color, argv[0]); if (error) { return error; } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -static struct cmd_results *parse_three_colors(char ***colors, const char *cmd_name, int argc, char **argv) { +static struct cmd_results *parse_three_colors(char ***colors, + const char *cmd_name, int argc, char **argv) { struct cmd_results *error = NULL; if (argc != 3) { - return cmd_results_new(CMD_INVALID, cmd_name, "Requires exactly three color values"); + return cmd_results_new(CMD_INVALID, + cmd_name, "Requires exactly three color values"); } - - int i; - for (i = 0; i < 3; i++) { - if (!*colors[i]) { - *(colors[i]) = malloc(10); - if (!*(colors[i])) { - return cmd_results_new(CMD_FAILURE, cmd_name, "Unable to allocate color"); - } + for (size_t i = 0; i < 3; i++) { + if (!*colors[i] && !(*(colors[i]) = malloc(10))) { + return NULL; } error = add_color(cmd_name, *(colors[i]), argv[i]); if (error) { return error; } } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -50,12 +41,10 @@ struct cmd_results *bar_cmd_colors(int argc, char **argv) { if ((error = checkarg(argc, "colors", EXPECTED_EQUAL_TO, 1))) { return error; } - if (strcmp("{", argv[0]) != 0) { return cmd_results_new(CMD_INVALID, "colors", "Expected '{' at the start of colors config definition."); } - return cmd_results_new(CMD_BLOCK_BAR_COLORS, NULL, NULL); } @@ -69,11 +58,13 @@ struct cmd_results *bar_colors_cmd_active_workspace(int argc, char **argv) { } struct cmd_results *bar_colors_cmd_background(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.background), "background", argc, argv); + return parse_single_color(&(config->current_bar->colors.background), + "background", argc, argv); } struct cmd_results *bar_colors_cmd_focused_background(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.focused_background), "focused_background", argc, argv); + return parse_single_color(&(config->current_bar->colors.focused_background), + "focused_background", argc, argv); } struct cmd_results *bar_colors_cmd_binding_mode(int argc, char **argv) { @@ -104,19 +95,23 @@ struct cmd_results *bar_colors_cmd_inactive_workspace(int argc, char **argv) { } struct cmd_results *bar_colors_cmd_separator(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.separator), "separator", argc, argv); + return parse_single_color(&(config->current_bar->colors.separator), + "separator", argc, argv); } struct cmd_results *bar_colors_cmd_focused_separator(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.focused_separator), "focused_separator", argc, argv); + return parse_single_color(&(config->current_bar->colors.focused_separator), + "focused_separator", argc, argv); } struct cmd_results *bar_colors_cmd_statusline(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.statusline), "statusline", argc, argv); + return parse_single_color(&(config->current_bar->colors.statusline), + "statusline", argc, argv); } struct cmd_results *bar_colors_cmd_focused_statusline(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.focused_separator), "focused_separator", argc, argv); + return parse_single_color(&(config->current_bar->colors.focused_separator), + "focused_separator", argc, argv); } struct cmd_results *bar_colors_cmd_urgent_workspace(int argc, char **argv) { diff --git a/sway/commands/bar/context_button.c b/sway/commands/bar/context_button.c index e6d17f10b..3b76885ad 100644 --- a/sway/commands/bar/context_button.c +++ b/sway/commands/bar/context_button.c @@ -3,7 +3,6 @@ #include "log.h" struct cmd_results *bar_cmd_context_button(int argc, char **argv) { - const char *cmd_name = "context_button"; // TODO TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); + return cmd_results_new(CMD_INVALID, "context_button", "TODO TRAY"); } diff --git a/sway/commands/bar/font.c b/sway/commands/bar/font.c index 6d7c533ad..80b7a5931 100644 --- a/sway/commands/bar/font.c +++ b/sway/commands/bar/font.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include #include "sway/commands.h" #include "log.h" @@ -8,19 +9,13 @@ struct cmd_results *bar_cmd_font(int argc, char **argv) { if ((error = checkarg(argc, "font", EXPECTED_AT_LEAST, 1))) { return error; } - if (!config->current_bar) { return cmd_results_new(CMD_FAILURE, "font", "No bar defined."); } - char *font = join_args(argv, argc); free(config->current_bar->font); - if (strlen(font) > 6 && strncmp("pango:", font, 6) == 0) { - config->current_bar->font = font; - } else { - config->current_bar->font = font; - } - - wlr_log(L_DEBUG, "Settings font '%s' for bar: %s", config->current_bar->font, config->current_bar->id); + config->current_bar->font = strdup(font); + wlr_log(L_DEBUG, "Settings font '%s' for bar: %s", + config->current_bar->font, config->current_bar->id); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/height.c b/sway/commands/bar/height.c index ae0c7834f..3160caed8 100644 --- a/sway/commands/bar/height.c +++ b/sway/commands/bar/height.c @@ -8,14 +8,13 @@ struct cmd_results *bar_cmd_height(int argc, char **argv) { if ((error = checkarg(argc, "height", EXPECTED_EQUAL_TO, 1))) { return error; } - int height = atoi(argv[0]); if (height < 0) { return cmd_results_new(CMD_INVALID, "height", "Invalid height value: %s", argv[0]); } - config->current_bar->height = height; - wlr_log(L_DEBUG, "Setting bar height to %d on bar: %s", height, config->current_bar->id); + wlr_log(L_DEBUG, "Setting bar height to %d on bar: %s", + height, config->current_bar->id); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c index 245d0858d..6641f1848 100644 --- a/sway/commands/bar/hidden_state.c +++ b/sway/commands/bar/hidden_state.c @@ -23,7 +23,6 @@ static struct cmd_results *bar_set_hidden_state(struct bar_config *bar, return cmd_results_new(CMD_INVALID, "hidden_state", "Invalid value %s", hidden_state); } - if (strcmp(old_state, bar->hidden_state) != 0) { if (!config->reading) { ipc_event_barconfig_update(bar); @@ -31,7 +30,6 @@ static struct cmd_results *bar_set_hidden_state(struct bar_config *bar, wlr_log(L_DEBUG, "Setting hidden_state: '%s' for bar: %s", bar->hidden_state, bar->id); } - // free old mode free(old_state); return cmd_results_new(CMD_SUCCESS, NULL, NULL); @@ -45,14 +43,12 @@ struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { if ((error = checkarg(argc, "hidden_state", EXPECTED_LESS_THAN, 3))) { return error; } - if (config->reading && argc > 1) { return cmd_results_new(CMD_INVALID, "hidden_state", "Unexpected value %s in config mode", argv[1]); } const char *state = argv[0]; - if (config->reading) { return bar_set_hidden_state(config->current_bar, state); } @@ -61,7 +57,6 @@ struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { if (argc == 2) { id = argv[1]; } - struct bar_config *bar; for (int i = 0; i < config->bars->length; ++i) { bar = config->bars->items[i]; diff --git a/sway/commands/bar/icon_theme.c b/sway/commands/bar/icon_theme.c index c6090b81c..44cd3076c 100644 --- a/sway/commands/bar/icon_theme.c +++ b/sway/commands/bar/icon_theme.c @@ -3,7 +3,6 @@ #include "sway/commands.h" struct cmd_results *bar_cmd_icon_theme(int argc, char **argv) { - const char *cmd_name = "tray_output"; // TODO TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); + return cmd_results_new(CMD_INVALID, "icon_theme", "TODO TRAY"); } diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c index d9e7f8df1..c1e56f039 100644 --- a/sway/commands/bar/id.c +++ b/sway/commands/bar/id.c @@ -11,10 +11,8 @@ struct cmd_results *bar_cmd_id(int argc, char **argv) { const char *name = argv[0]; const char *oldname = config->current_bar->id; - // check if id is used by a previously defined bar - int i; - for (i = 0; i < config->bars->length; ++i) { + for (int i = 0; i < config->bars->length; ++i) { struct bar_config *find = config->bars->items[i]; if (strcmp(name, find->id) == 0 && config->current_bar != find) { return cmd_results_new(CMD_FAILURE, "id", @@ -27,7 +25,6 @@ struct cmd_results *bar_cmd_id(int argc, char **argv) { // free old bar id free(config->current_bar->id); - config->current_bar->id = strdup(name); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c index 7d346956b..34bb0a4ff 100644 --- a/sway/commands/bar/mode.c +++ b/sway/commands/bar/mode.c @@ -44,13 +44,12 @@ struct cmd_results *bar_cmd_mode(int argc, char **argv) { if ((error = checkarg(argc, "mode", EXPECTED_LESS_THAN, 3))) { return error; } - if (config->reading && argc > 1) { - return cmd_results_new(CMD_INVALID, "mode", "Unexpected value %s in config mode", argv[1]); + return cmd_results_new(CMD_INVALID, + "mode", "Unexpected value %s in config mode", argv[1]); } const char *mode = argv[0]; - if (config->reading) { return bar_set_mode(config->current_bar, mode); } @@ -60,19 +59,16 @@ struct cmd_results *bar_cmd_mode(int argc, char **argv) { id = argv[1]; } - int i; struct bar_config *bar; - for (i = 0; i < config->bars->length; ++i) { + for (int i = 0; i < config->bars->length; ++i) { bar = config->bars->items[i]; if (id && strcmp(id, bar->id) == 0) { return bar_set_mode(bar, mode); } - error = bar_set_mode(bar, mode); if (error) { return error; } } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/modifier.c b/sway/commands/bar/modifier.c index 9a1f8b01b..7ba4b125d 100644 --- a/sway/commands/bar/modifier.c +++ b/sway/commands/bar/modifier.c @@ -15,7 +15,6 @@ struct cmd_results *bar_cmd_modifier(int argc, char **argv) { } uint32_t mod = 0; - list_t *split = split_string(argv[0], "+"); for (int i = 0; i < split->length; ++i) { uint32_t tmp_mod; @@ -24,12 +23,13 @@ struct cmd_results *bar_cmd_modifier(int argc, char **argv) { continue; } else { free_flat_list(split); - return cmd_results_new(CMD_INVALID, "modifier", "Unknown modifier '%s'", split->items[i]); + return cmd_results_new(CMD_INVALID, "modifier", + "Unknown modifier '%s'", split->items[i]); } } free_flat_list(split); - config->current_bar->modifier = mod; - wlr_log(L_DEBUG, "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]); + wlr_log(L_DEBUG, + "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/output.c b/sway/commands/bar/output.c index 034d9ca4c..f7ca0aa41 100644 --- a/sway/commands/bar/output.c +++ b/sway/commands/bar/output.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 500 +#include #include #include "sway/commands.h" #include "list.h" @@ -9,7 +10,6 @@ struct cmd_results *bar_cmd_output(int argc, char **argv) { if ((error = checkarg(argc, "output", EXPECTED_EQUAL_TO, 1))) { return error; } - if (!config->current_bar) { return cmd_results_new(CMD_FAILURE, "output", "No bar defined."); } @@ -21,21 +21,20 @@ struct cmd_results *bar_cmd_output(int argc, char **argv) { config->current_bar->outputs = outputs; } - int i; - int add_output = 1; + bool add_output = true; if (strcmp("*", output) == 0) { // remove all previous defined outputs and replace with '*' - for (i = 0; i < outputs->length; ++i) { + for (int i = 0; i < outputs->length; ++i) { free(outputs->items[i]); list_del(outputs, i); } } else { // only add output if not already defined with either the same // name or as '*' - for (i = 0; i < outputs->length; ++i) { + for (int i = 0; i < outputs->length; ++i) { const char *find = outputs->items[i]; if (strcmp("*", find) == 0 || strcmp(output, find) == 0) { - add_output = 0; + add_output = false; break; } } @@ -43,8 +42,8 @@ struct cmd_results *bar_cmd_output(int argc, char **argv) { if (add_output) { list_add(outputs, strdup(output)); - wlr_log(L_DEBUG, "Adding bar: '%s' to output '%s'", config->current_bar->id, output); + wlr_log(L_DEBUG, "Adding bar: '%s' to output '%s'", + config->current_bar->id, output); } - return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/pango_markup.c b/sway/commands/bar/pango_markup.c index 34b85e984..480af724b 100644 --- a/sway/commands/bar/pango_markup.c +++ b/sway/commands/bar/pango_markup.c @@ -8,19 +8,20 @@ struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { if ((error = checkarg(argc, "pango_markup", EXPECTED_EQUAL_TO, 1))) { return error; } - if (!config->current_bar) { return cmd_results_new(CMD_FAILURE, "pango_markup", "No bar defined."); } - if (strcasecmp("enabled", argv[0]) == 0) { config->current_bar->pango_markup = true; - wlr_log(L_DEBUG, "Enabling pango markup for bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Enabling pango markup for bar: %s", + config->current_bar->id); } else if (strcasecmp("disabled", argv[0]) == 0) { config->current_bar->pango_markup = false; - wlr_log(L_DEBUG, "Disabling pango markup for bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Disabling pango markup for bar: %s", + config->current_bar->id); } else { - error = cmd_results_new(CMD_INVALID, "pango_markup", "Invalid value %s", argv[0]); + error = cmd_results_new(CMD_INVALID, "pango_markup", + "Invalid value %s", argv[0]); return error; } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/bar/position.c b/sway/commands/bar/position.c index efa8c0bc8..9c5804839 100644 --- a/sway/commands/bar/position.c +++ b/sway/commands/bar/position.c @@ -9,11 +9,9 @@ struct cmd_results *bar_cmd_position(int argc, char **argv) { if ((error = checkarg(argc, "position", EXPECTED_EQUAL_TO, 1))) { return error; } - if (!config->current_bar) { return cmd_results_new(CMD_FAILURE, "position", "No bar defined."); } - char *valid[] = { "top", "bottom", "left", "right" }; for (size_t i = 0; i < sizeof(valid) / sizeof(valid[0]); ++i) { if (strcasecmp(valid[i], argv[0]) == 0) { @@ -23,7 +21,6 @@ struct cmd_results *bar_cmd_position(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL, NULL); } } - - error = cmd_results_new(CMD_INVALID, "position", "Invalid value %s", argv[0]); - return error; + return cmd_results_new(CMD_INVALID, + "position", "Invalid value %s", argv[0]); } diff --git a/sway/commands/bar/secondary_button.c b/sway/commands/bar/secondary_button.c index 46d53e3ff..449124cb9 100644 --- a/sway/commands/bar/secondary_button.c +++ b/sway/commands/bar/secondary_button.c @@ -3,7 +3,6 @@ #include "log.h" struct cmd_results *bar_cmd_secondary_button(int argc, char **argv) { - const char *cmd_name = "secondary_button"; // TODO TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); + return cmd_results_new(CMD_INVALID, "secondary_button", "TODO TRAY"); } diff --git a/sway/commands/bar/separator_symbol.c b/sway/commands/bar/separator_symbol.c index 7dc0956b9..1e08df6d2 100644 --- a/sway/commands/bar/separator_symbol.c +++ b/sway/commands/bar/separator_symbol.c @@ -8,14 +8,13 @@ struct cmd_results *bar_cmd_separator_symbol(int argc, char **argv) { if ((error = checkarg(argc, "separator_symbol", EXPECTED_EQUAL_TO, 1))) { return error; } - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "separator_symbol", "No bar defined."); + return cmd_results_new(CMD_FAILURE, + "separator_symbol", "No bar defined."); } - free(config->current_bar->separator_symbol); config->current_bar->separator_symbol = strdup(argv[0]); - wlr_log(L_DEBUG, "Settings separator_symbol '%s' for bar: %s", config->current_bar->separator_symbol, config->current_bar->id); - + wlr_log(L_DEBUG, "Settings separator_symbol '%s' for bar: %s", + config->current_bar->separator_symbol, config->current_bar->id); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/status_command.c b/sway/commands/bar/status_command.c index 05377fcca..5e199cde6 100644 --- a/sway/commands/bar/status_command.c +++ b/sway/commands/bar/status_command.c @@ -8,14 +8,13 @@ struct cmd_results *bar_cmd_status_command(int argc, char **argv) { if ((error = checkarg(argc, "status_command", EXPECTED_AT_LEAST, 1))) { return error; } - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "status_command", "No bar defined."); + return cmd_results_new(CMD_FAILURE, + "status_command", "No bar defined."); } - free(config->current_bar->status_command); config->current_bar->status_command = join_args(argv, argc); - wlr_log(L_DEBUG, "Feeding bar with status command: %s", config->current_bar->status_command); - + wlr_log(L_DEBUG, "Feeding bar with status command: %s", + config->current_bar->status_command); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/strip_workspace_numbers.c b/sway/commands/bar/strip_workspace_numbers.c index 0558db8fd..4f24a3563 100644 --- a/sway/commands/bar/strip_workspace_numbers.c +++ b/sway/commands/bar/strip_workspace_numbers.c @@ -5,23 +5,25 @@ struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) { struct cmd_results *error = NULL; - if ((error = checkarg(argc, "strip_workspace_numbers", EXPECTED_EQUAL_TO, 1))) { + if ((error = checkarg(argc, + "strip_workspace_numbers", EXPECTED_EQUAL_TO, 1))) { return error; } - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "strip_workspace_numbers", "No bar defined."); + return cmd_results_new(CMD_FAILURE, + "strip_workspace_numbers", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { config->current_bar->strip_workspace_numbers = true; - wlr_log(L_DEBUG, "Stripping workspace numbers on bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Stripping workspace numbers on bar: %s", + config->current_bar->id); } else if (strcasecmp("no", argv[0]) == 0) { config->current_bar->strip_workspace_numbers = false; - wlr_log(L_DEBUG, "Enabling workspace numbers on bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Enabling workspace numbers on bar: %s", + config->current_bar->id); } else { - error = cmd_results_new(CMD_INVALID, "strip_workspace_numbers", "Invalid value %s", argv[0]); - return error; + return cmd_results_new(CMD_INVALID, + "strip_workspace_numbers", "Invalid value %s", argv[0]); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/swaybar_command.c b/sway/commands/bar/swaybar_command.c index 63d4f29a2..520cdd118 100644 --- a/sway/commands/bar/swaybar_command.c +++ b/sway/commands/bar/swaybar_command.c @@ -8,14 +8,13 @@ struct cmd_results *bar_cmd_swaybar_command(int argc, char **argv) { if ((error = checkarg(argc, "swaybar_command", EXPECTED_AT_LEAST, 1))) { return error; } - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "swaybar_command", "No bar defined."); + return cmd_results_new(CMD_FAILURE, + "swaybar_command", "No bar defined."); } - free(config->current_bar->swaybar_command); config->current_bar->swaybar_command = join_args(argv, argc); - wlr_log(L_DEBUG, "Using custom swaybar command: %s", config->current_bar->swaybar_command); - + wlr_log(L_DEBUG, "Using custom swaybar command: %s", + config->current_bar->swaybar_command); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/tray_output.c b/sway/commands/bar/tray_output.c index 2d8221461..6ab167313 100644 --- a/sway/commands/bar/tray_output.c +++ b/sway/commands/bar/tray_output.c @@ -3,7 +3,6 @@ #include "sway/commands.h" struct cmd_results *bar_cmd_tray_output(int argc, char **argv) { - const char *cmd_name = "tray_output"; // TODO TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); + return cmd_results_new(CMD_INVALID, "tray_output", "TODO TRAY"); } diff --git a/sway/commands/bar/tray_padding.c b/sway/commands/bar/tray_padding.c index 95b8ad3b3..91c56f19e 100644 --- a/sway/commands/bar/tray_padding.c +++ b/sway/commands/bar/tray_padding.c @@ -4,7 +4,6 @@ #include "log.h" struct cmd_results *bar_cmd_tray_padding(int argc, char **argv) { - const char *cmd_name = "tray_padding"; // TODO TRAY - return cmd_results_new(CMD_INVALID, cmd_name, "TODO TRAY"); + return cmd_results_new(CMD_INVALID, "tray_padding", "TODO TRAY"); } diff --git a/sway/commands/bar/workspace_buttons.c b/sway/commands/bar/workspace_buttons.c index 1a617eb8f..6edc3a0de 100644 --- a/sway/commands/bar/workspace_buttons.c +++ b/sway/commands/bar/workspace_buttons.c @@ -8,20 +8,21 @@ struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { if ((error = checkarg(argc, "workspace_buttons", EXPECTED_EQUAL_TO, 1))) { return error; } - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "workspace_buttons", "No bar defined."); + return cmd_results_new(CMD_FAILURE, + "workspace_buttons", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { config->current_bar->workspace_buttons = true; - wlr_log(L_DEBUG, "Enabling workspace buttons on bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Enabling workspace buttons on bar: %s", + config->current_bar->id); } else if (strcasecmp("no", argv[0]) == 0) { config->current_bar->workspace_buttons = false; - wlr_log(L_DEBUG, "Disabling workspace buttons on bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Disabling workspace buttons on bar: %s", + config->current_bar->id); } else { - error = cmd_results_new(CMD_INVALID, "workspace_buttons", "Invalid value %s", argv[0]); - return error; + return cmd_results_new(CMD_INVALID, "workspace_buttons", + "Invalid value %s", argv[0]); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/wrap_scroll.c b/sway/commands/bar/wrap_scroll.c index c89dff5f8..7386f82ce 100644 --- a/sway/commands/bar/wrap_scroll.c +++ b/sway/commands/bar/wrap_scroll.c @@ -8,20 +8,20 @@ struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { if ((error = checkarg(argc, "wrap_scroll", EXPECTED_EQUAL_TO, 1))) { return error; } - if (!config->current_bar) { return cmd_results_new(CMD_FAILURE, "wrap_scroll", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { config->current_bar->wrap_scroll = true; - wlr_log(L_DEBUG, "Enabling wrap scroll on bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Enabling wrap scroll on bar: %s", + config->current_bar->id); } else if (strcasecmp("no", argv[0]) == 0) { config->current_bar->wrap_scroll = false; - wlr_log(L_DEBUG, "Disabling wrap scroll on bar: %s", config->current_bar->id); + wlr_log(L_DEBUG, "Disabling wrap scroll on bar: %s", + config->current_bar->id); } else { - error = cmd_results_new(CMD_INVALID, "wrap_scroll", "Invalid value %s", argv[0]); - return error; + return cmd_results_new(CMD_INVALID, + "wrap_scroll", "Invalid value %s", argv[0]); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From 8efee109ad2ab4861f25e54e9f6d1ceb06203791 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 22:10:33 -0400 Subject: [PATCH 288/522] Implement modes --- include/sway/ipc-server.h | 1 + sway/commands.c | 1 + sway/commands/mode.c | 59 +++++++++++++++++++++++++++++++++++++++ sway/ipc-server.c | 14 ++++++++-- sway/meson.build | 1 + 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 sway/commands/mode.c diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index 1f6fffff2..b4db75c34 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -13,5 +13,6 @@ 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); void ipc_event_barconfig_update(struct bar_config *bar); +void ipc_event_mode(const char *mode); #endif diff --git a/sway/commands.c b/sway/commands.c index 38e2f764d..bcc777ed3 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -100,6 +100,7 @@ static struct cmd_handler handlers[] = { { "exec_always", cmd_exec_always }, { "include", cmd_include }, { "input", cmd_input }, + { "mode", cmd_mode }, { "output", cmd_output }, { "seat", cmd_seat }, { "workspace", cmd_workspace }, diff --git a/sway/commands/mode.c b/sway/commands/mode.c new file mode 100644 index 000000000..c30a8bac2 --- /dev/null +++ b/sway/commands/mode.c @@ -0,0 +1,59 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/ipc-server.h" +#include "list.h" +#include "log.h" + +struct cmd_results *cmd_mode(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "mode", EXPECTED_AT_LEAST, 1))) { + return error; + } + + const char *mode_name = argv[0]; + bool new_mode = (argc == 2 && strcmp(argv[1], "{") == 0); + if (new_mode && !config->reading) { + return cmd_results_new(CMD_FAILURE, + "mode", "Can only be used in config file."); + } + struct sway_mode *mode = NULL; + // Find mode + for (int i = 0; i < config->modes->length; ++i) { + struct sway_mode *test = config->modes->items[i]; + if (strcasecmp(test->name, mode_name) == 0) { + mode = test; + break; + } + } + // Create mode if it doesn't exist + if (!mode && new_mode) { + mode = calloc(1, sizeof(struct sway_mode)); + if (!mode) { + return cmd_results_new(CMD_FAILURE, + "mode", "Unable to allocate mode"); + } + mode->name = strdup(mode_name); + mode->keysym_bindings = create_list(); + mode->keycode_bindings = create_list(); + list_add(config->modes, mode); + } + if (!mode) { + error = cmd_results_new(CMD_INVALID, + "mode", "Unknown mode `%s'", mode_name); + return error; + } + if ((config->reading && new_mode) || (!config->reading && !new_mode)) { + wlr_log(L_DEBUG, "Switching to mode `%s'",mode->name); + } + // Set current mode + config->current_mode = mode; + if (!new_mode) { + // trigger IPC mode event + ipc_event_mode(config->current_mode->name); + } + return cmd_results_new(new_mode ? CMD_BLOCK_MODE : CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 8250b3a03..c3b589a6f 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -290,7 +290,7 @@ void ipc_event_window(swayc_t *window, const char *change) { const char *json_string = json_object_to_json_string(obj); ipc_send_event(json_string, IPC_EVENT_WINDOW); - json_object_put(obj); // free + json_object_put(obj); } void ipc_event_barconfig_update(struct bar_config *bar) { @@ -299,7 +299,17 @@ void ipc_event_barconfig_update(struct bar_config *bar) { const char *json_string = json_object_to_json_string(json); ipc_send_event(json_string, IPC_EVENT_BARCONFIG_UPDATE); - json_object_put(json); // free + json_object_put(json); +} + +void ipc_event_mode(const char *mode) { + wlr_log(L_DEBUG, "Sending mode::%s event", mode); + json_object *obj = json_object_new_object(); + json_object_object_add(obj, "change", json_object_new_string(mode)); + + const char *json_string = json_object_to_json_string(obj); + ipc_send_event(json_string, IPC_EVENT_MODE); + json_object_put(obj); } int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { diff --git a/sway/meson.build b/sway/meson.build index 54c03061a..1e7ee7ae4 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -16,6 +16,7 @@ sway_sources = files( 'commands/include.c', 'commands/input.c', 'commands/layout.c', + 'commands/mode.c', 'commands/seat.c', 'commands/seat/attach.c', 'commands/seat/fallback.c', From ddc09940b161ac2e2d21d70d8ef4d89d33e2eb20 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 22:16:43 -0400 Subject: [PATCH 289/522] Exit ipc_get_workspace_callback early --- sway/ipc-server.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/sway/ipc-server.c b/sway/ipc-server.c index c3b589a6f..872c57047 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -379,22 +379,23 @@ void ipc_client_disconnect(struct ipc_client *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); + if (workspace->type != C_WORKSPACE) { + return; } + 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) { From dbda7bfbed7d4ac67f7c2932dd0b82fb5531f89a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 22:23:41 -0400 Subject: [PATCH 290/522] Move declaration into loop --- sway/ipc-server.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 872c57047..9d23607bf 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -538,8 +538,7 @@ void ipc_client_handle_command(struct ipc_client *client) { 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) { + for (int 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)); } @@ -549,8 +548,7 @@ void ipc_client_handle_command(struct ipc_client *client) { } else { // Send particular bar's details struct bar_config *bar = NULL; - int i; - for (i = 0; i < config->bars->length; ++i) { + for (int i = 0; i < config->bars->length; ++i) { bar = config->bars->items[i]; if (strcmp(buf, bar->id) == 0) { break; From 6fe66d0e6c9a20a9dbe2d464671ff19ea5b0387c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 22:25:25 -0400 Subject: [PATCH 291/522] Fix layer_surface_closed --- swaybar/bar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaybar/bar.c b/swaybar/bar.c index afbce7ccf..82404d335 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -46,7 +46,7 @@ static void layer_surface_configure(void *data, static void layer_surface_closed(void *_output, struct zwlr_layer_surface_v1 *surface) { // TODO: Deal with hotplugging - struct swaybar_output *output = output; + struct swaybar_output *output = _output; zwlr_layer_surface_v1_destroy(output->layer_surface); wl_surface_destroy(output->surface); } From 095ac319214d6e51df223950292bfca5ddaf591a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 22:32:17 -0400 Subject: [PATCH 292/522] Use render_all_frames from bar_setup --- swaybar/bar.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/swaybar/bar.c b/swaybar/bar.c index 82404d335..0fc415178 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -91,6 +91,13 @@ static const struct wl_registry_listener registry_listener = { .global_remove = handle_global_remove, }; +static void render_all_frames(struct swaybar *bar) { + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + render_frame(bar, output); + } +} + void bar_setup(struct swaybar *bar, const char *socket_path, const char *bar_id) { bar_init(bar); @@ -133,16 +140,7 @@ void bar_setup(struct swaybar *bar, } } ipc_get_workspaces(bar); - wl_list_for_each(output, &bar->outputs, link) { - render_frame(bar, output); - } -} - -static void render_all_frames(struct swaybar *bar) { - struct swaybar_output *output; - wl_list_for_each(output, &bar->outputs, link) { - render_frame(bar, output); - } + render_all_frames(bar); } static void display_in(int fd, short mask, void *_bar) { From 92c58b1e63d41d48cfb487b04a2cb105c990bc4c Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 23:08:59 -0400 Subject: [PATCH 293/522] rename container_for_each_descendent --- include/sway/tree/container.h | 2 +- sway/criteria.c | 2 +- sway/input/seat.c | 2 +- sway/tree/container.c | 6 +++--- sway/tree/layout.c | 2 +- sway/tree/view.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 92ff2b670..16df3ee75 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -131,7 +131,7 @@ struct sway_container *container_at(struct sway_container *parent, /** * Apply the function for each child of the container breadth first. */ -void container_for_each(struct sway_container *container, +void container_for_each_descendent(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data); #endif diff --git a/sway/criteria.c b/sway/criteria.c index 46961a604..247f6b754 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -435,7 +435,7 @@ list_t *container_for_crit_tokens(list_t *tokens) { struct list_tokens list_tokens = (struct list_tokens){create_list(), tokens}; - container_for_each(&root_container, + container_for_each_descendent(&root_container, (void (*)(struct sway_container *, void *))container_match_add, &list_tokens); diff --git a/sway/input/seat.c b/sway/input/seat.c index be0e15deb..76d29b520 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -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(&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); diff --git a/sway/tree/container.c b/sway/tree/container.c index dade8f541..fe97d6453 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -154,7 +154,7 @@ struct sway_container *container_output_create( struct sway_container *container_workspace_create( struct sway_container *output, const char *name) { if (!sway_assert(output, - "container_workspace_create called with null output")) { + "container_workspace_create called with null output")) { return NULL; } wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); @@ -178,7 +178,7 @@ struct sway_container *container_workspace_create( 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")) { + "container_view_create called with NULL sibling/parent")) { return NULL; } const char *title = view_get_title(sway_view); @@ -400,7 +400,7 @@ struct sway_container *container_at(struct sway_container *parent, return NULL; } -void container_for_each(struct sway_container *con, +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) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 53ff9ffa9..614d05058 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -592,7 +592,7 @@ static struct sway_container *get_swayc_in_direction_under( } } else { wlr_log(L_DEBUG, - "%s cont %d-%p dir %i sibling %d: %p", __func__, idx, + "cont %d-%p dir %i sibling %d: %p", idx, container, dir, desired, parent->children->items[desired]); return parent->children->items[desired]; } diff --git a/sway/tree/view.c b/sway/tree/view.c index 20e657a26..d5325c314 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -45,7 +45,7 @@ void view_set_size(struct sway_view *view, int width, int height) { } } -// TODO make view coordinates +// 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 = { From 2778edef976a669dd0019ebb5327bcfeb4de13c5 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 23:15:39 -0400 Subject: [PATCH 294/522] arrange windows --- include/sway/tree/layout.h | 2 +- sway/commands/layout.c | 2 +- sway/commands/reload.c | 2 +- sway/desktop/layer_shell.c | 2 +- sway/desktop/output.c | 4 ++-- sway/desktop/wl_shell.c | 4 ++-- sway/desktop/xdg_shell_v6.c | 4 ++-- sway/desktop/xwayland.c | 8 ++++---- sway/tree/container.c | 2 +- sway/tree/layout.c | 16 ++++++++-------- sway/tree/workspace.c | 2 +- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 6980ec9ee..ad52bdb08 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -43,7 +43,7 @@ enum sway_container_layout container_get_default_layout(struct sway_container *o void container_sort_workspaces(struct sway_container *output); -void container_arrange_windows(struct sway_container *container, +void arrange_windows(struct sway_container *container, double width, double height); struct sway_container *container_get_in_direction(struct sway_container diff --git a/sway/commands/layout.c b/sway/commands/layout.c index e9cfeb8f1..ebab2a48a 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -50,7 +50,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } } - container_arrange_windows(parent, parent->width, parent->height); + arrange_windows(parent, parent->width, parent->height); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 83ecd75bb..8cef789ba 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -13,6 +13,6 @@ struct cmd_results *cmd_reload(int argc, char **argv) { /* load_swaybars(); -- for when it's implemented */ - container_arrange_windows(&root_container, -1, -1); + arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 4bfd1c45b..137b3260d 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -172,7 +172,7 @@ void arrange_layers(struct sway_output *output) { if (memcmp(&usable_area_before, &usable_area, sizeof(struct wlr_box)) != 0) { wlr_log(L_DEBUG, "arrange"); - container_arrange_windows(output->swayc, -1, -1); + arrange_windows(output->swayc, -1, -1); } // Arrange non-exlusive surfaces from top->bottom diff --git a/sway/desktop/output.c b/sway/desktop/output.c index fa1b0680e..b463dfdc3 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -264,7 +264,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { static void handle_output_mode(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, mode); arrange_layers(output); - container_arrange_windows(output->swayc, -1, -1); + arrange_windows(output->swayc, -1, -1); } void handle_new_output(struct wl_listener *listener, void *data) { @@ -307,5 +307,5 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->mode.notify = handle_output_mode; arrange_layers(output); - container_arrange_windows(&root_container, -1, -1); + arrange_windows(&root_container, -1, -1); } diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index ac1c7f262..4d4d1ed79 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -77,7 +77,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); free(sway_surface->view); free(sway_surface); - container_arrange_windows(parent, -1, -1); + arrange_windows(parent, -1, -1); } void handle_wl_shell_surface(struct wl_listener *listener, void *data) { @@ -136,6 +136,6 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; - container_arrange_windows(cont->parent, -1, -1); + arrange_windows(cont->parent, -1, -1); 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 616cb88f1..09894f0e0 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -86,7 +86,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_container *parent = container_view_destroy(sway_xdg_surface->view->swayc); free(sway_xdg_surface->view); free(sway_xdg_surface); - container_arrange_windows(parent, -1, -1); + arrange_windows(parent, -1, -1); } void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { @@ -140,7 +140,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; - container_arrange_windows(cont->parent, -1, -1); + arrange_windows(cont->parent, -1, -1); sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index fa1054f20..fd0bcaca9 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -116,7 +116,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); if (parent) { - container_arrange_windows(parent, -1, -1); + arrange_windows(parent, -1, -1); } free(sway_surface->view); @@ -134,7 +134,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); if (parent) { - container_arrange_windows(parent, -1, -1); + arrange_windows(parent, -1, -1); } sway_surface->view->swayc = NULL; @@ -163,7 +163,7 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { struct sway_container *cont = container_view_create(parent, view); view->swayc = cont; - container_arrange_windows(cont->parent, -1, -1); + arrange_windows(cont->parent, -1, -1); sway_input_manager_set_focus(input_manager, cont); } } @@ -242,6 +242,6 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; - container_arrange_windows(cont->parent, -1, -1); + arrange_windows(cont->parent, -1, -1); sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/tree/container.c b/sway/tree/container.c index fe97d6453..40047dcfd 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -221,7 +221,7 @@ struct sway_container *container_output_destroy(struct sway_container *output) { container_add_child(root_container.children->items[p], child); } container_sort_workspaces(root_container.children->items[p]); - container_arrange_windows(root_container.children->items[p], + arrange_windows(root_container.children->items[p], -1, -1); } } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 614d05058..dc0ee5b40 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -42,7 +42,7 @@ static void output_layout_change_notify(struct wl_listener *listener, output_container->height = output_box->height; } - container_arrange_windows(&root_container, -1, -1); + arrange_windows(&root_container, -1, -1); } void layout_init(void) { @@ -167,7 +167,7 @@ static void apply_vert_layout(struct sway_container *container, const double x, const double height, const int start, const int end); -void container_arrange_windows(struct sway_container *container, +void arrange_windows(struct sway_container *container, double width, double height) { int i; if (width == -1 || height == -1) { @@ -192,7 +192,7 @@ void container_arrange_windows(struct sway_container *container, struct sway_container *output = container->children->items[i]; wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); - container_arrange_windows(output, -1, -1); + arrange_windows(output, -1, -1); } return; case C_OUTPUT: @@ -206,7 +206,7 @@ void container_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]; - container_arrange_windows(child, -1, -1); + arrange_windows(child, -1, -1); } return; case C_WORKSPACE: @@ -294,9 +294,9 @@ static void apply_horiz_layout(struct sway_container *container, if (i == end - 1) { double remaining_width = x + width - child_x; - container_arrange_windows(child, remaining_width, height); + arrange_windows(child, remaining_width, height); } else { - container_arrange_windows(child, child->width * scale, height); + arrange_windows(child, child->width * scale, height); } child_x += child->width; } @@ -345,9 +345,9 @@ void apply_vert_layout(struct sway_container *container, if (i == end - 1) { double remaining_height = y + height - child_y; - container_arrange_windows(child, width, remaining_height); + arrange_windows(child, width, remaining_height); } else { - container_arrange_windows(child, width, child->height * scale); + arrange_windows(child, width, child->height * scale); } child_y += child->height; } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 369cf14c9..ba04c55c2 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -247,6 +247,6 @@ bool workspace_switch(struct sway_container *workspace) { } sway_seat_set_focus(seat, next); struct sway_container *output = container_parent(workspace, C_OUTPUT); - container_arrange_windows(output, -1, -1); + arrange_windows(output, -1, -1); return true; } From d0c7f66e950689b70196a890b62b82ff3c66e103 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 23:29:29 -0400 Subject: [PATCH 295/522] 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/workspace.h | 26 ---- include/sway/{tree => }/view.h | 4 + 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 +- 39 files changed, 588 insertions(+), 593 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/workspace.h rename include/sway/{tree => }/view.h (96%) create mode 100644 include/sway/workspace.h diff --git a/include/sway/config.h b/include/sway/config.h index 7fdd0be09..48a8b0abb 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 000000000..f200a1a2e --- /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 ec256ddbd..9b4b4befa 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 c6c73dbab..eab7dc90f 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 496bfd5d0..1d55bec7a 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 3d2fdc4fb..eef5a018c 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 d73006dc6..bcf1c4338 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 000000000..e82c4442a --- /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 16df3ee75..000000000 --- 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 ad52bdb08..000000000 --- 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/workspace.h b/include/sway/tree/workspace.h deleted file mode 100644 index d73b29c1c..000000000 --- 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/tree/view.h b/include/sway/view.h similarity index 96% rename from include/sway/tree/view.h rename to include/sway/view.h index e5f53f4e6..b28862113 100644 --- a/include/sway/tree/view.h +++ b/include/sway/view.h @@ -62,6 +62,10 @@ enum sway_view_prop { 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; diff --git a/include/sway/workspace.h b/include/sway/workspace.h new file mode 100644 index 000000000..fee54255c --- /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 954950e76..61870c513 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 64f079f4e..f1a8078f7 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 f67747679..f408ce2a9 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 ebab2a48a..b0fc5d664 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 f7e3372ce..35bc80995 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 8cef789ba..d54d40db6 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 8f39e5fc8..fa8913984 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 0b29735a6..213e7680a 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 7fc797393..9e2118614 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 247f6b754..2eee331c1 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 137b3260d..bd62f84a4 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 ba778f4c5..b8253ace2 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 4d4d1ed79..0356aa811 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 25c0cbca6..18e7d3993 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 fd0bcaca9..f9b5242b6 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 d57ac3e3e..8a0d1df59 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 d421a03f1..27c2c72eb 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 76d29b520..648e79143 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 7caa2457a..977f1ecbc 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 50d0bcf30..156de3807 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 ded922ee7..f2f24be35 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 40047dcfd..bbafe9ec1 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 dc0ee5b40..de9e7b586 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 d5325c314..9499adca7 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 ba04c55c2..861fda4dd 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 2d2b3b694..93d1219c4 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); } From d8104db8f1820bd3d4db8bf4f1ee51ae334ee6e7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 23:35:49 -0400 Subject: [PATCH 296/522] Early return from render functions if necessary --- swaybar/render.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index a5834f4bb..3d9ef66bb 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -30,7 +30,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, 1, config->pango_markup, "%s", status->text); uint32_t ideal_height = text_height + ws_vertical_padding * 2; if (height < ideal_height) { - height = ideal_height; + return ideal_height; } double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y)); @@ -70,7 +70,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; if (height < ideal_height) { - height = ideal_height; + return ideal_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; @@ -133,7 +133,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; if (height < ideal_height) { - height = ideal_height; + return ideal_height; } uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; From dc8c9fbeb664518c76066cc28ee29452c6c30128 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 23:41:33 -0400 Subject: [PATCH 297/522] 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 | 4 - include/sway/tree/workspace.h | 26 ++++ 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 +- 39 files changed, 593 insertions(+), 588 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 rename include/sway/{ => tree}/view.h (96%) create mode 100644 include/sway/tree/workspace.h delete mode 100644 include/sway/workspace.h diff --git a/include/sway/config.h b/include/sway/config.h index 48a8b0abb..7fdd0be09 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 f200a1a2e..000000000 --- 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 9b4b4befa..ec256ddbd 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 eab7dc90f..c6c73dbab 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 1d55bec7a..496bfd5d0 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 eef5a018c..3d2fdc4fb 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 bcf1c4338..d73006dc6 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 e82c4442a..000000000 --- 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 000000000..16df3ee75 --- /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 000000000..ad52bdb08 --- /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/view.h b/include/sway/tree/view.h similarity index 96% rename from include/sway/view.h rename to include/sway/tree/view.h index b28862113..e5f53f4e6 100644 --- a/include/sway/view.h +++ b/include/sway/tree/view.h @@ -62,10 +62,6 @@ enum sway_view_prop { 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; diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h new file mode 100644 index 000000000..d73b29c1c --- /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/workspace.h b/include/sway/workspace.h deleted file mode 100644 index fee54255c..000000000 --- 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 61870c513..954950e76 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 f1a8078f7..64f079f4e 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 f408ce2a9..f67747679 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 b0fc5d664..ebab2a48a 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 35bc80995..f7e3372ce 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 d54d40db6..8cef789ba 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 fa8913984..8f39e5fc8 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 213e7680a..0b29735a6 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 9e2118614..7fc797393 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 2eee331c1..247f6b754 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 bd62f84a4..137b3260d 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 b8253ace2..ba778f4c5 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 0356aa811..4d4d1ed79 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 18e7d3993..25c0cbca6 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 f9b5242b6..fd0bcaca9 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 8a0d1df59..d57ac3e3e 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 27c2c72eb..d421a03f1 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 648e79143..76d29b520 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 977f1ecbc..7caa2457a 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 156de3807..50d0bcf30 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 f2f24be35..ded922ee7 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 bbafe9ec1..40047dcfd 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 de9e7b586..dc0ee5b40 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 9499adca7..d5325c314 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 861fda4dd..ba04c55c2 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 93d1219c4..2d2b3b694 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); } From 8f490d7d2dbadfe85dcf3dcd972471e86671442a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 29 Mar 2018 23:53:38 -0400 Subject: [PATCH 298/522] Fix oversights from previous pull request --- include/sway/tree/container.h | 10 ++++++++-- sway/criteria.c | 2 +- sway/desktop/output.c | 2 +- sway/input/seat.c | 2 +- sway/tree/container.c | 21 ++++++++++++++++++--- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 16df3ee75..3bb497db4 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -104,7 +104,7 @@ 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, +void container_descendants(struct sway_container *root, enum sway_container_type type, void (*func)(struct sway_container *item, void *data), void *data); @@ -131,7 +131,13 @@ struct sway_container *container_at(struct sway_container *parent, /** * Apply the function for each child of the container breadth first. */ -void container_for_each_descendent(struct sway_container *container, +void container_for_each_descendant_bfs(struct sway_container *container, + void (*f)(struct sway_container *container, void *data), void *data); + +/** + * Apply the function for each child of the container depth first. + */ +void container_for_each_descendant_dfs(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data); #endif diff --git a/sway/criteria.c b/sway/criteria.c index 247f6b754..5fee18881 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -435,7 +435,7 @@ 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, + container_for_each_descendant_dfs(&root_container, (void (*)(struct sway_container *, void *))container_match_add, &list_tokens); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index ba778f4c5..1273df599 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -228,7 +228,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { .output = soutput, .now = &now, }; - container_descendents(workspace, C_VIEW, output_frame_view, &rdata); + container_descendants(workspace, C_VIEW, output_frame_view, &rdata); // render unmanaged views on top struct sway_view *view; diff --git a/sway/input/seat.c b/sway/input/seat.c index 76d29b520..aa0b1d504 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -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_descendant_dfs(&root_container, collect_focus_iter, seat); wl_signal_add(&root_container.sway_root->events.new_container, &seat->new_container); diff --git a/sway/tree/container.c b/sway/tree/container.c index 40047dcfd..6a6861f37 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -266,7 +266,7 @@ struct sway_container *container_set_layout(struct sway_container *container, return container; } -void container_descendents(struct sway_container *root, +void container_descendants(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) { @@ -275,7 +275,7 @@ void container_descendents(struct sway_container *root, func(item, data); } if (item->children && item->children->length) { - container_descendents(item, type, func, data); + container_descendants(item, type, func, data); } } } @@ -400,7 +400,22 @@ struct sway_container *container_at(struct sway_container *parent, return NULL; } -void container_for_each_descendent(struct sway_container *con, +void container_for_each_descendant_dfs(struct sway_container *container, + void (*f)(struct sway_container *container, void *data), + void *data) { + if (container) { + if (container->children) { + for (int i = 0; i < container->children->length; ++i) { + struct sway_container *child = + container->children->items[i]; + container_for_each_descendant_dfs(child, f, data); + } + } + f(container, data); + } +} + +void container_for_each_descendant_bfs(struct sway_container *con, void (*f)(struct sway_container *con, void *data), void *data) { list_t *queue = get_bfs_queue(); if (!queue) { From d6acb3d86cf0842bff81da1ec2bc990ae84ed85b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 00:13:54 -0400 Subject: [PATCH 299/522] Set WAYLAND_DISPLAY earlier in startup --- sway/server.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/server.c b/sway/server.c index 75202df2c..3fba019df 100644 --- a/sway/server.c +++ b/sway/server.c @@ -102,12 +102,11 @@ void server_fini(struct sway_server *server) { void server_run(struct sway_server *server) { wlr_log(L_INFO, "Running compositor on wayland display '%s'", server->socket); - setenv("_WAYLAND_DISPLAY", server->socket, true); + setenv("WAYLAND_DISPLAY", server->socket, true); if (!wlr_backend_start(server->backend)) { wlr_log(L_ERROR, "Failed to start backend"); wlr_backend_destroy(server->backend); return; } - setenv("WAYLAND_DISPLAY", server->socket, true); wl_display_run(server->wl_display); } From 00d450e5540deedd5071b4c4b467dcf0ae82f299 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 00:16:18 -0400 Subject: [PATCH 300/522] Use output coords for layer surfaces This will need to be more carefully thought out when we get the output_layout working entirely. --- sway/desktop/output.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a9c59684d..87eb80fe6 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -187,8 +187,7 @@ static void render_layer(struct sway_output *output, wl_list_for_each(sway_layer, layer, link) { struct wlr_layer_surface *layer = sway_layer->layer_surface; render_surface(layer->surface, output->wlr_output, when, - sway_layer->geo.x + output_layout_box->x, - sway_layer->geo.y + output_layout_box->y, 0); + sway_layer->geo.x, sway_layer->geo.y, 0); wlr_surface_send_frame_done(layer->surface, when); } } From 2a90d26ebe2af75a19f1850a6a2105170b825e9a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 00:30:38 -0400 Subject: [PATCH 301/522] Fix issues with swaybar on DRM --- include/swaybar/config.h | 1 + swaybar/ipc.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 7634cb16e..7f321df89 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -30,6 +30,7 @@ struct swaybar_config { bool wrap_scroll; bool workspace_buttons; struct wl_list outputs; + bool all_outputs; int height; struct { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index a82904bda..326f25cc2 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -188,7 +188,7 @@ static void ipc_parse_config( json_object *output = json_object_array_get_idx(outputs, i); const char *name = json_object_get_string(output); if (strcmp("*", name) == 0) { - // TODO: do we need to clear out the list here or something + config->all_outputs = true; break; } struct config_output *coutput = calloc( @@ -197,6 +197,8 @@ static void ipc_parse_config( coutput->index = SIZE_MAX; wl_list_insert(&config->outputs, &coutput->link); } + } else { + config->all_outputs = true; } if (colors) { @@ -279,7 +281,7 @@ static void ipc_get_outputs(struct swaybar *bar) { if (!active) { continue; } - if (wl_list_empty(&bar->config->outputs)) { + if (bar->config->all_outputs) { struct config_output *coutput = calloc( 1, sizeof(struct config_output)); coutput->name = strdup(name); From e62cc0ac26b20af92ae082b110a3ab77cf0c4e60 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 00:34:24 -0400 Subject: [PATCH 302/522] Finish porting over workspace_next_name --- sway/tree/workspace.c | 107 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 7 deletions(-) diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index ba04c55c2..5800ea096 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -1,8 +1,11 @@ #define _XOPEN_SOURCE 500 +#include +#include #include #include #include #include +#include "stringop.h" #include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -22,18 +25,108 @@ void next_name_map(struct sway_container *ws, void *data) { ++count; } +static bool workspace_valid_on_output(const char *output_name, + const char *ws_name) { + int i; + for (i = 0; i < config->workspace_outputs->length; ++i) { + struct workspace_output *wso = config->workspace_outputs->items[i]; + if (strcasecmp(wso->workspace, ws_name) == 0) { + if (strcasecmp(wso->output, output_name) != 0) { + return false; + } + } + } + + return true; +} + char *workspace_next_name(const char *output_name) { wlr_log(L_DEBUG, "Workspace: Generating new workspace name for output %s", output_name); - int count = 0; - next_name_map(&root_container, &count); - ++count; - int len = snprintf(NULL, 0, "%d", count); - char *name = malloc(len + 1); - if (!sway_assert(name, "Failed to allocate workspace name")) { + int l = 1; + // Scan all workspace bindings to find the next available workspace name, + // if none are found/available then default to a number + struct sway_mode *mode = config->current_mode; + + // TODO: iterate over keycode bindings too + int order = INT_MAX; + char *target = NULL; + for (int i = 0; i < mode->keysym_bindings->length; ++i) { + struct sway_binding *binding = mode->keysym_bindings->items[i]; + char *cmdlist = strdup(binding->command); + char *dup = cmdlist; + char *name = NULL; + + // workspace n + char *cmd = argsep(&cmdlist, " "); + if (cmdlist) { + name = argsep(&cmdlist, ",;"); + } + + if (strcmp("workspace", cmd) == 0 && name) { + wlr_log(L_DEBUG, "Got valid workspace command for target: '%s'", name); + char *_target = strdup(name); + strip_quotes(_target); + while (isspace(*_target)) { + memmove(_target, _target+1, strlen(_target+1)); + } + + // Make sure that the command references an actual workspace + // not a command about workspaces + if (strcmp(_target, "next") == 0 || + strcmp(_target, "prev") == 0 || + strcmp(_target, "next_on_output") == 0 || + strcmp(_target, "prev_on_output") == 0 || + strcmp(_target, "number") == 0 || + strcmp(_target, "back_and_forth") == 0 || + strcmp(_target, "current") == 0) + { + free(_target); + free(dup); + continue; + } + + // Make sure that the workspace doesn't already exist + if (workspace_by_name(_target)) { + free(_target); + free(dup); + continue; + } + + // make sure that the workspace can appear on the given + // output + if (!workspace_valid_on_output(output_name, _target)) { + free(_target); + free(dup); + continue; + } + + if (binding->order < order) { + order = binding->order; + free(target); + target = _target; + wlr_log(L_DEBUG, "Workspace: Found free name %s", _target); + } + } + free(dup); + } + if (target != NULL) { + return target; + } + // As a fall back, get the current number of active workspaces + // and return that + 1 for the next workspace's name + int ws_num = root_container.children->length; + if (ws_num >= 10) { + l = 2; + } else if (ws_num >= 100) { + l = 3; + } + char *name = malloc(l + 1); + if (!name) { + wlr_log(L_ERROR, "Could not allocate workspace name"); return NULL; } - snprintf(name, len + 1, "%d", count); + sprintf(name, "%d", ws_num++); return name; } From 2d460502812093b47f43295cf21636198e44edbb Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 00:46:40 -0400 Subject: [PATCH 303/522] Fix crash when override redirect views close --- sway/desktop/xwayland.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index fd0bcaca9..38ee46563 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -108,10 +108,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&sway_surface->commit.link); wl_list_remove(&sway_surface->destroy.link); wl_list_remove(&sway_surface->request_configure.link); - if (xsurface->override_redirect) { - if (xsurface->mapped) { - wl_list_remove(&sway_surface->view->unmanaged_view_link); - } + if (xsurface->override_redirect && xsurface->mapped) { + wl_list_remove(&sway_surface->view->unmanaged_view_link); + wl_list_init(&sway_surface->view->unmanaged_view_link); } struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); @@ -127,8 +126,9 @@ static void handle_unmap_notify(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, unmap_notify); struct wlr_xwayland_surface *xsurface = data; - if (xsurface->override_redirect) { + if (xsurface->override_redirect && xsurface->mapped) { wl_list_remove(&sway_surface->view->unmanaged_view_link); + wl_list_init(&sway_surface->view->unmanaged_view_link); } // take it out of the tree From 981827ca423838a0fa422b4dd65acb1b8f81349d Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 00:47:57 -0400 Subject: [PATCH 304/522] Cleanup and remove global renderer reference --- include/sway/server.h | 1 - sway/desktop/output.c | 25 ++++++++++++++----------- sway/server.c | 18 +++++++++--------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index 25eb64fe8..db81932f1 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -18,7 +18,6 @@ struct sway_server { const char *socket; struct wlr_backend *backend; - struct wlr_renderer *renderer; struct wlr_compositor *compositor; struct wlr_data_device_manager *data_device_manager; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 87eb80fe6..f3416c03c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -41,6 +41,9 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, static void render_surface(struct wlr_surface *surface, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation) { + struct wlr_renderer *renderer = + wlr_backend_get_renderer(wlr_output->backend); + if (!wlr_surface_has_buffer(surface)) { return; } @@ -65,8 +68,8 @@ static void render_surface(struct wlr_surface *surface, float matrix[9]; wlr_matrix_project_box(matrix, &render_box, surface->current->transform, 0, wlr_output->transform_matrix); - wlr_render_texture_with_matrix(server.renderer, surface->texture, - matrix, 1.0f); // TODO: configurable alpha + wlr_render_texture_with_matrix(renderer, surface->texture, matrix, + 1.0f); // TODO: configurable alpha wlr_surface_send_frame_done(surface, when); } @@ -192,15 +195,14 @@ static void render_layer(struct sway_output *output, } } -static void output_frame_notify(struct wl_listener *listener, void *data) { +static void handle_output_frame(struct wl_listener *listener, void *data) { struct sway_output *soutput = wl_container_of(listener, soutput, frame); struct wlr_output *wlr_output = data; - struct sway_server *server = soutput->server; - struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); + struct wlr_renderer *renderer = + wlr_backend_get_renderer(wlr_output->backend); - int buffer_age = -1; - wlr_output_make_current(wlr_output, &buffer_age); - wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); + wlr_output_make_current(wlr_output, NULL); + wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; wlr_renderer_clear(renderer, clear_color); @@ -218,7 +220,8 @@ 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 *focus = + sway_seat_get_focus_inactive(seat, soutput->swayc); struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : container_parent(focus, C_WORKSPACE)); @@ -248,7 +251,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { render_layer(soutput, output_box, &now, &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); - wlr_renderer_end(server->renderer); + wlr_renderer_end(renderer); wlr_output_swap_buffers(wlr_output, &now, NULL); soutput->last_frame = now; } @@ -306,7 +309,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { sway_input_manager_configure_xcursor(input_manager); wl_signal_add(&wlr_output->events.frame, &output->frame); - output->frame.notify = output_frame_notify; + output->frame.notify = handle_output_frame; wl_signal_add(&wlr_output->events.destroy, &output->destroy); output->destroy.notify = handle_output_destroy; wl_signal_add(&wlr_output->events.mode, &output->mode); diff --git a/sway/server.c b/sway/server.c index 3fba019df..728e624e5 100644 --- a/sway/server.c +++ b/sway/server.c @@ -1,19 +1,19 @@ #define _POSIX_C_SOURCE 200112L -#include +#include #include +#include #include #include #include #include -#include #include +#include #include #include -#include #include +#include // TODO WLR: make Xwayland optional #include -#include #include "sway/commands.h" #include "sway/config.h" #include "sway/server.h" @@ -42,11 +42,12 @@ bool server_init(struct sway_server *server) { server->wl_event_loop = wl_display_get_event_loop(server->wl_display); server->backend = wlr_backend_autocreate(server->wl_display); - server->renderer = wlr_gles2_renderer_create(server->backend); + struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); + assert(renderer); + wl_display_init_shm(server->wl_display); - server->compositor = wlr_compositor_create( - server->wl_display, server->renderer); + server->compositor = wlr_compositor_create(server->wl_display, renderer); server->data_device_manager = wlr_data_device_manager_create(server->wl_display); @@ -95,8 +96,7 @@ bool server_init(struct sway_server *server) { } void server_fini(struct sway_server *server) { - // TODO WLR: tear down more stuff - wlr_backend_destroy(server->backend); + // TODO } void server_run(struct sway_server *server) { From 28cb412b0d083355507875459e6c5f412e81ce43 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 10:09:56 -0400 Subject: [PATCH 305/522] Unify initial xwayland view mapping with map handler --- sway/desktop/xwayland.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 38ee46563..c3697b4cb 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -150,7 +150,8 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { sway_surface->view->surface = xsurface->surface; // put it back into the tree - if (xsurface->override_redirect) { + if (wlr_xwayland_surface_is_unmanaged(xsurface) || + xsurface->override_redirect) { wl_list_insert(&root_container.sway_root->unmanaged_views, &sway_surface->view->unmanaged_view_link); } else { @@ -230,18 +231,5 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify); sway_surface->map_notify.notify = handle_map_notify; - if (wlr_xwayland_surface_is_unmanaged(xsurface)) { - // these don't get a container in the tree - wl_list_insert(&root_container.sway_root->unmanaged_views, - &sway_view->unmanaged_view_link); - return; - } - - 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); - sway_view->swayc = cont; - - arrange_windows(cont->parent, -1, -1); - sway_input_manager_set_focus(input_manager, cont); + handle_map_notify(&sway_surface->map_notify, xsurface); } From 69eb021767d8cf57b08699c7e330fe8c52ca2764 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 10:43:55 -0400 Subject: [PATCH 306/522] Add default_orientation command --- include/sway/commands.h | 2 +- sway/commands.c | 1 + sway/commands/default_orientation.c | 21 +++++++++++++++++++++ sway/meson.build | 1 + sway/tree/layout.c | 5 ++--- 5 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 sway/commands/default_orientation.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 1291d5fb6..66f097ea0 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -95,6 +95,7 @@ sway_cmd cmd_commands; sway_cmd cmd_debuglog; sway_cmd cmd_default_border; sway_cmd cmd_default_floating_border; +sway_cmd cmd_default_orientation; sway_cmd cmd_exec; sway_cmd cmd_exec_always; sway_cmd cmd_exit; @@ -125,7 +126,6 @@ sway_cmd cmd_move; sway_cmd cmd_new_float; sway_cmd cmd_new_window; sway_cmd cmd_no_focus; -sway_cmd cmd_orientation; sway_cmd cmd_output; sway_cmd cmd_permit; sway_cmd cmd_reject; diff --git a/sway/commands.c b/sway/commands.c index bcc777ed3..eee7f254e 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[] = { + { "default_orientation", cmd_default_orientation }, { "set", cmd_set }, { "swaybg_command", cmd_swaybg_command }, }; diff --git a/sway/commands/default_orientation.c b/sway/commands/default_orientation.c new file mode 100644 index 000000000..a5347ce21 --- /dev/null +++ b/sway/commands/default_orientation.c @@ -0,0 +1,21 @@ +#include +#include +#include "sway/commands.h" + +struct cmd_results *cmd_default_orientation(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "default_orientation", EXPECTED_EQUAL_TO, 1))) { + return error; + } + if (strcasecmp(argv[0], "horizontal") == 0) { + config->default_orientation = L_HORIZ; + } else if (strcasecmp(argv[0], "vertical") == 0) { + config->default_orientation = L_VERT; + } else if (strcasecmp(argv[0], "auto") == 0) { + // Do nothing + } else { + return cmd_results_new(CMD_INVALID, "default_orientation", + "Expected 'orientation '"); + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index 1e7ee7ae4..9c5e4a00e 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -8,6 +8,7 @@ sway_sources = files( 'input/keyboard.c', 'commands/bar.c', 'commands/bind.c', + 'commands/default_orientation.c', 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', diff --git a/sway/tree/layout.c b/sway/tree/layout.c index dc0ee5b40..c7cf16e66 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -123,12 +123,11 @@ struct sway_container *container_remove_child(struct sway_container *child) { enum sway_container_layout container_get_default_layout( struct sway_container *output) { - /* TODO WLR if (config->default_layout != L_NONE) { - //return config->default_layout; + return config->default_layout; } else if (config->default_orientation != L_NONE) { return config->default_orientation; - } else */if (output->width >= output->height) { + } else if (output->width >= output->height) { return L_HORIZ; } else { return L_VERT; From 01af34391267e91461a4ab7a1234dd58f45d2c93 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 10:31:21 -0400 Subject: [PATCH 307/522] Destroy empty workspaces when moving away --- include/sway/tree/container.h | 8 +++++ include/sway/tree/layout.h | 3 ++ sway/input/seat.c | 4 +++ sway/tree/container.c | 55 +++++++++++++++++++++++++++++++++-- sway/tree/layout.c | 37 +++++++++++++++++++++++ 5 files changed, 104 insertions(+), 3 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 3bb497db4..24e8468ec 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -99,8 +99,13 @@ struct sway_container *container_view_create( struct sway_container *container_output_destroy(struct sway_container *output); +struct sway_container *container_workspace_destroy( + struct sway_container *workspace); + struct sway_container *container_view_destroy(struct sway_container *view); +void container_destroy(struct sway_container *cont); + struct sway_container *container_set_layout(struct sway_container *container, enum sway_container_layout layout); @@ -140,4 +145,7 @@ void container_for_each_descendant_bfs(struct sway_container *container, void container_for_each_descendant_dfs(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data); +bool container_has_anscestor(struct sway_container *descendant, + struct sway_container *anscestor); + #endif diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index ad52bdb08..8239366b8 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -39,6 +39,9 @@ struct sway_container *container_add_sibling(struct sway_container *parent, struct sway_container *container_remove_child(struct sway_container *child); +void container_move_to(struct sway_container* container, + struct sway_container* destination); + enum sway_container_layout container_get_default_layout(struct sway_container *output); void container_sort_workspaces(struct sway_container *output); diff --git a/sway/input/seat.c b/sway/input/seat.c index 7cf0dd089..ae5362640 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -8,6 +8,7 @@ #include "sway/input/keyboard.h" #include "sway/ipc-server.h" #include "sway/output.h" +#include "sway/tree/container.h" #include "sway/tree/view.h" #include "log.h" @@ -331,6 +332,9 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe if (last_ws) { wlr_log(L_DEBUG, "sending workspace event"); ipc_event_workspace(last_ws, container, "focus"); + if (last_ws->children->length == 0) { + container_workspace_destroy(last_ws); + } } } diff --git a/sway/tree/container.c b/sway/tree/container.c index 2eac812e4..ed39a1541 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -58,7 +58,7 @@ static struct sway_container *container_create(enum sway_container_type type) { return c; } -static void container_destroy(struct sway_container *cont) { +void container_destroy(struct sway_container *cont) { if (cont == NULL) { return; } @@ -203,8 +203,7 @@ struct sway_container *container_view_create(struct sway_container *sibling, } struct sway_container *container_output_destroy(struct sway_container *output) { - if (!sway_assert(output, - "null output passed to container_output_destroy")) { + if (!sway_assert(output, "cannot destroy null output")) { return NULL; } @@ -236,6 +235,45 @@ struct sway_container *container_output_destroy(struct sway_container *output) { return &root_container; } +struct sway_container *container_workspace_destroy( + struct sway_container *workspace) { + if (!sway_assert(workspace, "cannot destroy null workspace")) { + return NULL; + } + + // Do not destroy this if it's the last workspace on this output + struct sway_container *output = container_parent(workspace, C_OUTPUT); + if (output && output->children->length == 1) { + return NULL; + } + + struct sway_container *parent = workspace->parent; + if (workspace->children->length == 0) { + // destroy the WS if there are no children (TODO check for floating) + wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); + ipc_event_workspace(workspace, NULL, "empty"); + } else { + // Move children to a different workspace on this output + struct sway_container *new_workspace = NULL; + // TODO move floating + for (int i = 0; i < output->children->length; i++) { + if (output->children->items[i] != workspace) { + new_workspace = output->children->items[i]; + break; + } + } + + wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", + workspace->name, new_workspace->name); + for (int i = 0; i < workspace->children->length; i++) { + container_move_to(workspace->children->items[i], new_workspace); + } + } + + container_destroy(workspace); + return parent; +} + struct sway_container *container_view_destroy(struct sway_container *view) { if (!view) { return NULL; @@ -438,3 +476,14 @@ void container_for_each_descendant_bfs(struct sway_container *con, list_cat(queue, current->children); } } + +bool container_has_anscestor(struct sway_container *descendant, + struct sway_container *anscestor) { + while (descendant->type != C_ROOT) { + descendant = descendant->parent; + if (descendant == anscestor) { + return true; + } + } + return false; +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index dc0ee5b40..970078886 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -11,6 +11,7 @@ #include "sway/output.h" #include "sway/tree/view.h" #include "sway/input/seat.h" +#include "sway/ipc-server.h" #include "list.h" #include "log.h" @@ -121,6 +122,42 @@ struct sway_container *container_remove_child(struct sway_container *child) { return parent; } +struct sway_container *container_reap_empty(struct sway_container *container) { + if (!sway_assert(container, "reaping null container")) { + return NULL; + } + while (container->children->length == 0 && container->type == C_CONTAINER) { + wlr_log(L_DEBUG, "Container: Destroying container '%p'", container); + struct sway_container *parent = container->parent; + container_destroy(container); + container = parent; + } + return container; +} + +void container_move_to(struct sway_container* container, + struct sway_container* destination) { + if (container == destination + || container_has_anscestor(container, destination)) { + return; + } + struct sway_container *old_parent = container_remove_child(container); + container->width = container->height = 0; + struct sway_container *new_parent = + container_add_sibling(destination, container); + if (destination->type == C_WORKSPACE) { + // If the workspace only has one child after adding one, it + // means that the workspace was just initialized. + // TODO: Consider floating views in this test + if (destination->children->length == 1) { + ipc_event_workspace(NULL, destination, "init"); + } + } + old_parent = container_reap_empty(old_parent); + arrange_windows(old_parent, -1, -1); + arrange_windows(new_parent, -1, -1); +} + enum sway_container_layout container_get_default_layout( struct sway_container *output) { /* TODO WLR From 6c9d67b1059409750de683aec3b8b9be2da987cc Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 10:53:18 -0400 Subject: [PATCH 308/522] Handle set_cursor requests from clients Allow clients to set a custom cursor if they have the seat's pointer focus. --- include/sway/input/cursor.h | 1 + sway/input/cursor.c | 50 +++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index a16b793b5..64917ce5b 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -9,6 +9,7 @@ struct sway_cursor { struct wlr_xcursor_manager *xcursor_manager; double x, y; + struct wl_client *image_client; struct wl_listener motion; struct wl_listener motion_absolute; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d57ac3e3e..cded0005d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -25,10 +25,12 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, struct wlr_surface *surface = NULL; double sx, sy; + struct sway_container *focus = NULL; + // check for unmanaged views first struct sway_view *view; wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views, - unmanaged_view_link) { + unmanaged_view_link) { if (view->type == SWAY_XWAYLAND_VIEW) { struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_box box = { @@ -39,19 +41,34 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, }; if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { + focus = view->swayc; surface = xsurface->surface; sx = cursor->x - box.x; sy = cursor->y - box.y; - wlr_seat_pointer_notify_enter(seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(seat, time, sx, sy); - return; + break; } } } - struct sway_container *swayc = - container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); - if (swayc) { + // then check for managed views + if (focus == NULL) { + focus = container_at(&root_container, cursor->x, cursor->y, &surface, + &sx, &sy); + } + + // reset cursor if switching between clients + struct wl_client *client = NULL; + if (focus) { + client = wl_resource_get_client(surface->resource); + } + if (client != cursor->image_client) { + wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, + "left_ptr", cursor->cursor); + cursor->image_client = client; + } + + // send pointer enter/leave + if (focus) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); } else { @@ -145,7 +162,24 @@ static void handle_request_set_cursor(struct wl_listener *listener, struct sway_cursor *cursor = wl_container_of(listener, cursor, request_set_cursor); struct wlr_seat_pointer_request_set_cursor_event *event = data; - wlr_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); + + struct wl_client *focused_client = NULL; + struct wlr_surface *focused_surface = + cursor->seat->wlr_seat->pointer_state.focused_surface; + if (focused_surface != NULL) { + focused_client = wl_resource_get_client(focused_surface->resource); + } + + // TODO: check cursor mode + if (focused_client == NULL || + event->seat_client->client != focused_client) { + wlr_log(L_DEBUG, "denying request to set cursor from unfocused client"); + return; + } + + wlr_cursor_set_surface(cursor->cursor, event->surface, event->hotspot_x, + event->hotspot_y); + cursor->image_client = focused_client; } void sway_cursor_destroy(struct sway_cursor *cursor) { From 681f38c8783c14723a8cf88114e5af824d4952b8 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 11:22:12 -0400 Subject: [PATCH 309/522] Fix segfault on xwayland unmanaged view unmap --- sway/desktop/xwayland.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index c3697b4cb..d608c8b61 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -104,14 +104,11 @@ static void handle_commit(struct wl_listener *listener, void *data) { static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, destroy); - struct wlr_xwayland_surface *xsurface = data; + wl_list_remove(&sway_surface->commit.link); wl_list_remove(&sway_surface->destroy.link); wl_list_remove(&sway_surface->request_configure.link); - if (xsurface->override_redirect && xsurface->mapped) { - wl_list_remove(&sway_surface->view->unmanaged_view_link); - wl_list_init(&sway_surface->view->unmanaged_view_link); - } + wl_list_remove(&sway_surface->view->unmanaged_view_link); struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); if (parent) { @@ -125,11 +122,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { static void handle_unmap_notify(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, unmap_notify); - struct wlr_xwayland_surface *xsurface = data; - if (xsurface->override_redirect && xsurface->mapped) { - wl_list_remove(&sway_surface->view->unmanaged_view_link); - wl_list_init(&sway_surface->view->unmanaged_view_link); - } + + wl_list_remove(&sway_surface->view->unmanaged_view_link); + wl_list_init(&sway_surface->view->unmanaged_view_link); // take it out of the tree struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); @@ -152,6 +147,7 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { // put it back into the tree if (wlr_xwayland_surface_is_unmanaged(xsurface) || xsurface->override_redirect) { + wl_list_remove(&sway_surface->view->unmanaged_view_link); wl_list_insert(&root_container.sway_root->unmanaged_views, &sway_surface->view->unmanaged_view_link); } else { @@ -210,6 +206,8 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { sway_view->surface = xsurface->surface; sway_surface->view = sway_view; + wl_list_init(&sway_view->unmanaged_view_link); + // TODO: // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely From a5e457d59aaa4add10ddddaba81b7c64f2f1c689 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 12:06:45 -0400 Subject: [PATCH 310/522] Add xwayland views to focused container --- sway/desktop/xwayland.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index d608c8b61..3e08b20e5 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -154,12 +154,10 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { struct sway_view *view = sway_surface->view; container_view_destroy(view->swayc); - struct sway_container *parent = root_container.children->items[0]; - parent = parent->children->items[0]; // workspace - - struct sway_container *cont = container_view_create(parent, view); + 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, view); view->swayc = cont; - arrange_windows(cont->parent, -1, -1); sway_input_manager_set_focus(input_manager, cont); } From cf09ea184b891594331240eb860f28975dcb8b8c Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 13:34:25 -0400 Subject: [PATCH 311/522] Use the new map/unmap events for xwayland views --- include/sway/tree/view.h | 4 ++-- sway/desktop/xwayland.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index e5f53f4e6..54f6d90e8 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -28,8 +28,8 @@ struct sway_xwayland_surface { 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 unmap; + struct wl_listener map; struct wl_listener destroy; int pending_width, pending_height; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 3e08b20e5..13eaf79a0 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -119,9 +119,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { free(sway_surface); } -static void handle_unmap_notify(struct wl_listener *listener, void *data) { +static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, unmap_notify); + wl_container_of(listener, sway_surface, unmap); wl_list_remove(&sway_surface->view->unmanaged_view_link); wl_list_init(&sway_surface->view->unmanaged_view_link); @@ -136,10 +136,10 @@ static void handle_unmap_notify(struct wl_listener *listener, void *data) { sway_surface->view->surface = NULL; } -static void handle_map_notify(struct wl_listener *listener, void *data) { +static void handle_map(struct wl_listener *listener, void *data) { // TODO put the view back into the tree struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, map_notify); + wl_container_of(listener, sway_surface, map); struct wlr_xwayland_surface *xsurface = data; sway_surface->view->surface = xsurface->surface; @@ -221,11 +221,11 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { &sway_surface->request_configure); sway_surface->request_configure.notify = handle_configure_request; - wl_signal_add(&xsurface->events.unmap_notify, &sway_surface->unmap_notify); - sway_surface->unmap_notify.notify = handle_unmap_notify; + wl_signal_add(&xsurface->events.unmap, &sway_surface->unmap); + sway_surface->unmap.notify = handle_unmap; - wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify); - sway_surface->map_notify.notify = handle_map_notify; + wl_signal_add(&xsurface->events.map, &sway_surface->map); + sway_surface->map.notify = handle_map; - handle_map_notify(&sway_surface->map_notify, xsurface); + handle_map(&sway_surface->map, xsurface); } From 49379dd0fc0758f89d7f4fa4fb5b08c7f4c26ae6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 11:58:17 -0400 Subject: [PATCH 312/522] Fix workspace deletion edge cases --- include/sway/tree/container.h | 2 +- include/sway/tree/layout.h | 2 + include/sway/tree/workspace.h | 2 + sway/desktop/xdg_shell_v6.c | 3 +- sway/desktop/xwayland.c | 20 ++----- sway/meson.build | 1 + sway/tree/container.c | 101 +++------------------------------- sway/tree/layout.c | 64 ++++++++++----------- sway/tree/output.c | 36 ++++++++++++ sway/tree/view.c | 11 ++++ sway/tree/workspace.c | 56 ++++++++++++++++++- 11 files changed, 148 insertions(+), 150 deletions(-) create mode 100644 sway/tree/output.c diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 24e8468ec..6aa66da02 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -104,7 +104,7 @@ struct sway_container *container_workspace_destroy( struct sway_container *container_view_destroy(struct sway_container *view); -void container_destroy(struct sway_container *cont); +struct sway_container *container_destroy(struct sway_container *cont); struct sway_container *container_set_layout(struct sway_container *container, enum sway_container_layout layout); diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 8239366b8..0a904c4b5 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -39,6 +39,8 @@ struct sway_container *container_add_sibling(struct sway_container *parent, struct sway_container *container_remove_child(struct sway_container *child); +struct sway_container *container_reap_empty(struct sway_container *container); + void container_move_to(struct sway_container* container, struct sway_container* destination); diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index d73b29c1c..4e4c34505 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -23,4 +23,6 @@ struct sway_container *workspace_output_prev(struct sway_container *current); struct sway_container *workspace_prev(struct sway_container *current); +bool workspace_is_visible(struct sway_container *ws); + #endif diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 25c0cbca6..01f38d16a 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -83,10 +83,9 @@ 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); + container_view_destroy(sway_xdg_surface->view->swayc); free(sway_xdg_surface->view); free(sway_xdg_surface); - arrange_windows(parent, -1, -1); } void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 3e08b20e5..357c8883c 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -109,29 +109,17 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&sway_surface->destroy.link); wl_list_remove(&sway_surface->request_configure.link); wl_list_remove(&sway_surface->view->unmanaged_view_link); - - struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); - if (parent) { - arrange_windows(parent, -1, -1); - } - - free(sway_surface->view); - free(sway_surface); + container_view_destroy(sway_surface->view->swayc); + sway_surface->view->swayc = NULL; + sway_surface->view->surface = NULL; } static void handle_unmap_notify(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, unmap_notify); - wl_list_remove(&sway_surface->view->unmanaged_view_link); wl_list_init(&sway_surface->view->unmanaged_view_link); - - // take it out of the tree - struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); - if (parent) { - arrange_windows(parent, -1, -1); - } - + container_view_destroy(sway_surface->view->swayc); sway_surface->view->swayc = NULL; sway_surface->view->surface = NULL; } diff --git a/sway/meson.build b/sway/meson.build index 9c5e4a00e..e8a192f03 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -82,6 +82,7 @@ sway_sources = files( 'security.c', 'tree/container.c', 'tree/layout.c', + 'tree/output.c', 'tree/view.c', 'tree/workspace.c', ) diff --git a/sway/tree/container.c b/sway/tree/container.c index ed39a1541..778108b4b 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -10,12 +10,12 @@ #include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/tree/layout.h" +#include "sway/ipc-server.h" #include "sway/output.h" #include "sway/server.h" +#include "sway/tree/layout.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" -#include "sway/ipc-server.h" #include "log.h" static list_t *bfs_queue; @@ -58,13 +58,14 @@ static struct sway_container *container_create(enum sway_container_type type) { return c; } -void container_destroy(struct sway_container *cont) { +struct sway_container *container_destroy(struct sway_container *cont) { if (cont == NULL) { - return; + return NULL; } wl_signal_emit(&cont->events.destroy, cont); + struct sway_container *parent = cont->parent; if (cont->children) { // remove children until there are no more, container_destroy calls // container_remove_child, which removes child from this container @@ -77,13 +78,14 @@ void container_destroy(struct sway_container *cont) { list_foreach(cont->marks, free); list_free(cont->marks); } - if (cont->parent) { + if (parent) { container_remove_child(cont); } if (cont->name) { free(cont->name); } free(cont); + return parent; } struct sway_container *container_output_create( @@ -202,95 +204,6 @@ struct sway_container *container_view_create(struct sway_container *sibling, return swayc; } -struct sway_container *container_output_destroy(struct sway_container *output) { - if (!sway_assert(output, "cannot destroy null 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) { - struct sway_container *child = output->children->items[0]; - container_remove_child(child); - container_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); - } - } - - wl_list_remove(&output->sway_output->frame.link); - wl_list_remove(&output->sway_output->destroy.link); - wl_list_remove(&output->sway_output->mode.link); - - wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); - container_destroy(output); - - return &root_container; -} - -struct sway_container *container_workspace_destroy( - struct sway_container *workspace) { - if (!sway_assert(workspace, "cannot destroy null workspace")) { - return NULL; - } - - // Do not destroy this if it's the last workspace on this output - struct sway_container *output = container_parent(workspace, C_OUTPUT); - if (output && output->children->length == 1) { - return NULL; - } - - struct sway_container *parent = workspace->parent; - if (workspace->children->length == 0) { - // destroy the WS if there are no children (TODO check for floating) - wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); - ipc_event_workspace(workspace, NULL, "empty"); - } else { - // Move children to a different workspace on this output - struct sway_container *new_workspace = NULL; - // TODO move floating - for (int i = 0; i < output->children->length; i++) { - if (output->children->items[i] != workspace) { - new_workspace = output->children->items[i]; - break; - } - } - - wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", - workspace->name, new_workspace->name); - for (int i = 0; i < workspace->children->length; i++) { - container_move_to(workspace->children->items[i], new_workspace); - } - } - - container_destroy(workspace); - return parent; -} - -struct sway_container *container_view_destroy(struct sway_container *view) { - if (!view) { - return NULL; - } - wlr_log(L_DEBUG, "Destroying view '%s'", view->name); - struct sway_container *parent = view->parent; - container_destroy(view); - - // TODO WLR: Destroy empty containers - /* - if (parent && parent->type == C_CONTAINER) { - return destroy_container(parent); - } - */ - return parent; -} - struct sway_container *container_set_layout(struct sway_container *container, enum sway_container_layout layout) { if (container->type == C_WORKSPACE) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 73c4849bf..32e6a77c5 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -9,6 +9,7 @@ #include "sway/tree/container.h" #include "sway/tree/layout.h" #include "sway/output.h" +#include "sway/tree/workspace.h" #include "sway/tree/view.h" #include "sway/input/seat.h" #include "sway/ipc-server.h" @@ -99,42 +100,42 @@ void container_add_child(struct sway_container *parent, parent, parent->type, parent->width, parent->height); list_add(parent->children, 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)) { - child = new_container(child, parent->workspace_layout); - } - */ -} - -struct sway_container *container_remove_child(struct sway_container *child) { - int i; - 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); - break; - } - } - child->parent = NULL; - return parent; } struct sway_container *container_reap_empty(struct sway_container *container) { if (!sway_assert(container, "reaping null container")) { return NULL; } - while (container->children->length == 0 && container->type == C_CONTAINER) { - wlr_log(L_DEBUG, "Container: Destroying container '%p'", container); - struct sway_container *parent = container->parent; - container_destroy(container); - container = parent; + wlr_log(L_DEBUG, "reaping %p %s", container, container->name); + while (container->children->length == 0) { + if (container->type == C_WORKSPACE) { + if (!workspace_is_visible(container)) { + container_workspace_destroy(container); + } + break; + } else if (container->type == C_CONTAINER) { + struct sway_container *parent = container->parent; + container_destroy(container); + container = parent; + } else { + container = container->parent; + } } return container; } +struct sway_container *container_remove_child(struct sway_container *child) { + struct sway_container *parent = child->parent; + for (int i = 0; i < parent->children->length; ++i) { + if (parent->children->items[i] == child) { + list_del(parent->children, i); + break; + } + } + child->parent = NULL; + return container_reap_empty(parent); +} + void container_move_to(struct sway_container* container, struct sway_container* destination) { if (container == destination @@ -145,16 +146,9 @@ void container_move_to(struct sway_container* container, container->width = container->height = 0; struct sway_container *new_parent = container_add_sibling(destination, container); - if (destination->type == C_WORKSPACE) { - // If the workspace only has one child after adding one, it - // means that the workspace was just initialized. - // TODO: Consider floating views in this test - if (destination->children->length == 1) { - ipc_event_workspace(NULL, destination, "init"); - } + if (old_parent) { + arrange_windows(old_parent, -1, -1); } - old_parent = container_reap_empty(old_parent); - arrange_windows(old_parent, -1, -1); arrange_windows(new_parent, -1, -1); } diff --git a/sway/tree/output.c b/sway/tree/output.c new file mode 100644 index 000000000..2246cb11c --- /dev/null +++ b/sway/tree/output.c @@ -0,0 +1,36 @@ +#include "sway/tree/container.h" +#include "sway/tree/layout.h" +#include "sway/output.h" +#include "log.h" + +struct sway_container *container_output_destroy(struct sway_container *output) { + if (!sway_assert(output, "cannot destroy null 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) { + struct sway_container *child = output->children->items[0]; + container_remove_child(child); + container_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); + } + } + + wl_list_remove(&output->sway_output->frame.link); + wl_list_remove(&output->sway_output->destroy.link); + wl_list_remove(&output->sway_output->mode.link); + + wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); + container_destroy(output); + return &root_container; +} diff --git a/sway/tree/view.c b/sway/tree/view.c index d5325c314..480ff693f 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,6 +3,7 @@ #include "sway/tree/container.h" #include "sway/tree/layout.h" #include "sway/tree/view.h" +#include "log.h" const char *view_get_title(struct sway_view *view) { if (view->iface.get_prop) { @@ -94,3 +95,13 @@ void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { } } } + +struct sway_container *container_view_destroy(struct sway_container *view) { + if (!view) { + return NULL; + } + wlr_log(L_DEBUG, "Destroying view '%s'", view->name); + struct sway_container *parent = container_destroy(view); + arrange_windows(parent, -1, -1); + return parent; +} diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 5800ea096..c629f1f17 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -6,9 +6,10 @@ #include #include #include "stringop.h" -#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" +#include "sway/ipc-server.h" +#include "sway/tree/container.h" #include "sway/tree/workspace.h" #include "log.h" #include "util.h" @@ -202,7 +203,48 @@ struct sway_container *workspace_create(const char *name) { sway_seat_get_focus_inactive(seat, &root_container); parent = focus; parent = container_parent(parent, C_OUTPUT); - return container_workspace_create(parent, name); + struct sway_container *new_ws = container_workspace_create(parent, name); + ipc_event_workspace(NULL, new_ws, "init"); + return new_ws; +} + +struct sway_container *container_workspace_destroy( + struct sway_container *workspace) { + if (!sway_assert(workspace, "cannot destroy null workspace")) { + return NULL; + } + + // Do not destroy this if it's the last workspace on this output + struct sway_container *output = container_parent(workspace, C_OUTPUT); + if (output && output->children->length == 1) { + return NULL; + } + + struct sway_container *parent = workspace->parent; + if (workspace->children->length == 0) { + // destroy the WS if there are no children (TODO check for floating) + wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); + ipc_event_workspace(workspace, NULL, "empty"); + } else { + // Move children to a different workspace on this output + struct sway_container *new_workspace = NULL; + // TODO move floating + for (int i = 0; i < output->children->length; i++) { + if (output->children->items[i] != workspace) { + new_workspace = output->children->items[i]; + break; + } + } + + wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", + workspace->name, new_workspace->name); + for (int i = 0; i < workspace->children->length; i++) { + container_move_to(workspace->children->items[i], new_workspace); + } + } + + container_destroy(workspace); + return parent; } /** @@ -343,3 +385,13 @@ bool workspace_switch(struct sway_container *workspace) { arrange_windows(output, -1, -1); return true; } + +bool workspace_is_visible(struct sway_container *ws) { + struct sway_container *output = container_parent(ws, C_OUTPUT); + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); + if (focus->type != C_WORKSPACE) { + focus = container_parent(focus, C_WORKSPACE); + } + return focus == ws; +} From b28e6d23698c98d616710c44a211a8121943b3ca Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 13:56:31 -0400 Subject: [PATCH 313/522] IPC fixes --- sway/ipc-json.c | 69 ++++++++++++++++++++++++++++++++--------------- sway/ipc-server.c | 8 ++++++ 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index eab6399f0..7c5f73047 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -66,19 +66,42 @@ static const char *ipc_json_get_output_transform(enum wl_output_transform transf 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)); - json_object_object_add(object, "primary", json_object_new_boolean(false)); - json_object_object_add(object, "layout", json_object_new_string("output")); - json_object_object_add(object, "make", json_object_new_string(wlr_output->make)); - json_object_object_add(object, "model", json_object_new_string(wlr_output->model)); - json_object_object_add(object, "serial", json_object_new_string(wlr_output->serial)); - json_object_object_add(object, "scale", json_object_new_double(wlr_output->scale)); - json_object_object_add(object, "refresh", json_object_new_int(wlr_output->refresh)); + json_object_object_add(object, "type", + json_object_new_string("output")); + json_object_object_add(object, "active", + json_object_new_boolean(true)); + json_object_object_add(object, "primary", + json_object_new_boolean(false)); + json_object_object_add(object, "layout", + json_object_new_string("output")); + json_object_object_add(object, "make", + json_object_new_string(wlr_output->make)); + json_object_object_add(object, "model", + json_object_new_string(wlr_output->model)); + json_object_object_add(object, "serial", + json_object_new_string(wlr_output->serial)); + json_object_object_add(object, "scale", + json_object_new_double(wlr_output->scale)); + json_object_object_add(object, "refresh", + json_object_new_int(wlr_output->refresh)); json_object_object_add(object, "transform", - json_object_new_string(ipc_json_get_output_transform(wlr_output->transform))); - // TODO WLR need to set "current_workspace" to the currently focused - // workspace in a way that makes sense with multiseat + json_object_new_string( + ipc_json_get_output_transform(wlr_output->transform))); + + struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); + const char *ws = NULL; + if (seat) { + struct sway_container *focus = + sway_seat_get_focus_inactive(seat, container); + if (focus && focus->type != C_WORKSPACE) { + focus = container_parent(focus, C_WORKSPACE); + } + if (focus) { + ws = focus->name; + } + } + json_object_object_add(object, "current_workspace", + json_object_new_string(ws)); json_object *modes_array = json_object_new_array(); struct wlr_output_mode *mode; @@ -95,16 +118,20 @@ 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) { - int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; +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)); - json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL); + json_object_object_add(object, "output", workspace->parent ? + json_object_new_string(workspace->parent->name) : NULL); json_object_object_add(object, "type", json_object_new_string("workspace")); + json_object_object_add(object, "urgent", json_object_new_boolean(false)); } 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_object_add(object, "name", + c->name ? json_object_new_string(c->name) : NULL); } json_object *ipc_json_describe_container(struct sway_container *c) { @@ -118,28 +145,26 @@ json_object *ipc_json_describe_container(struct sway_container *c) { json_object *object = json_object_new_object(); json_object_object_add(object, "id", json_object_new_int((int)c->id)); - json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); + json_object_object_add(object, "name", + c->name ? json_object_new_string(c->name) : NULL); json_object_object_add(object, "rect", ipc_json_create_rect(c)); - json_object_object_add(object, "focused", json_object_new_boolean(focused)); + json_object_object_add(object, "focused", + json_object_new_boolean(focused)); switch (c->type) { case C_ROOT: ipc_json_describe_root(c, object); break; - case C_OUTPUT: ipc_json_describe_output(c, object); break; - case C_CONTAINER: case C_VIEW: ipc_json_describe_view(c, object); break; - case C_WORKSPACE: ipc_json_describe_workspace(c, object); break; - case C_TYPES: default: break; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 394161af3..f1854bcc7 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -398,6 +398,14 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace, json_object_object_add(workspace_json, "focused", json_object_new_boolean(focused)); json_object_array_add((json_object *)data, workspace_json); + + focused_ws = sway_seat_get_focus_inactive(seat, workspace->parent); + if (focused_ws->type != C_WORKSPACE) { + focused_ws = container_parent(focused_ws, C_WORKSPACE); + } + bool visible = workspace == focused_ws; + json_object_object_add(workspace_json, "visible", + json_object_new_boolean(visible)); } void ipc_client_handle_command(struct ipc_client *client) { From 88f08a42f30c6d79adbc9c1d5d897113fcd3a6f4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 14:31:17 -0400 Subject: [PATCH 314/522] Fix segfault when reaping invisible workspaces --- sway/tree/container.c | 2 +- sway/tree/layout.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 778108b4b..c3cf6c641 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -79,7 +79,7 @@ struct sway_container *container_destroy(struct sway_container *cont) { list_free(cont->marks); } if (parent) { - container_remove_child(cont); + parent = container_remove_child(cont); } if (cont->name) { free(cont->name); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 32e6a77c5..588ceb2db 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -110,9 +110,11 @@ struct sway_container *container_reap_empty(struct sway_container *container) { while (container->children->length == 0) { if (container->type == C_WORKSPACE) { if (!workspace_is_visible(container)) { + struct sway_container *parent = container->parent; container_workspace_destroy(container); + return parent; } - break; + return container; } else if (container->type == C_CONTAINER) { struct sway_container *parent = container->parent; container_destroy(container); From 03255fd20209bc26ca54ae6c1562feb0a157c5e3 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 15:33:16 -0400 Subject: [PATCH 315/522] Fix pointer events for hidden workspaces --- sway/input/cursor.c | 83 +++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d57ac3e3e..4abc61ea1 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -6,10 +6,11 @@ #endif #include #include -#include "sway/input/cursor.h" -#include "sway/tree/view.h" #include "list.h" #include "log.h" +#include "sway/input/cursor.h" +#include "sway/output.h" +#include "sway/tree/view.h" static void cursor_update_position(struct sway_cursor *cursor) { double x = cursor->cursor->x; @@ -19,16 +20,12 @@ static void cursor_update_position(struct sway_cursor *cursor) { cursor->y = y; } -static void cursor_send_pointer_motion(struct sway_cursor *cursor, - uint32_t time) { - struct wlr_seat *seat = cursor->seat->wlr_seat; - struct wlr_surface *surface = NULL; - double sx, sy; - +static struct sway_container *cursor_at(struct sway_cursor *cursor, + struct wlr_surface **surface, double *sx, double *sy) { // check for unmanaged views first + struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; struct sway_view *view; - wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views, - unmanaged_view_link) { + wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) { if (view->type == SWAY_XWAYLAND_VIEW) { struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_box box = { @@ -39,19 +36,42 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, }; if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { - surface = xsurface->surface; - sx = cursor->x - box.x; - sy = cursor->y - box.y; - wlr_seat_pointer_notify_enter(seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(seat, time, sx, sy); - return; + *surface = xsurface->surface; + *sx = cursor->x - box.x; + *sy = cursor->y - box.y; + return view->swayc; } } } - struct sway_container *swayc = - container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); - if (swayc) { + // find the output the cursor is on + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; + struct wlr_output *wlr_output = + wlr_output_layout_output_at(output_layout, cursor->x, cursor->y); + if (wlr_output == NULL) { + return NULL; + } + struct sway_output *output = wlr_output->data; + + // find the focused workspace on the output for this seat + struct sway_container *workspace = + sway_seat_get_focus_inactive(cursor->seat, output->swayc); + if (workspace->type != C_WORKSPACE) { + workspace = container_parent(workspace, C_WORKSPACE); + } + + return container_at(workspace, cursor->x, cursor->y, surface, sx, sy); +} + +static void cursor_send_pointer_motion(struct sway_cursor *cursor, + uint32_t time) { + struct wlr_seat *seat = cursor->seat->wlr_seat; + struct wlr_surface *surface = NULL; + double sx, sy; + struct sway_container *cont = cursor_at(cursor, &surface, &sx, &sy); + + if (cont) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); } else { @@ -60,8 +80,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, } static void handle_cursor_motion(struct wl_listener *listener, void *data) { - struct sway_cursor *cursor = - wl_container_of(listener, cursor, motion); + struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); struct wlr_event_pointer_motion *event = data; wlr_cursor_move(cursor->cursor, event->device, event->delta_x, event->delta_y); @@ -80,16 +99,13 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, } static void handle_cursor_button(struct wl_listener *listener, void *data) { - struct sway_cursor *cursor = - wl_container_of(listener, cursor, button); + 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 *swayc = - container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); - + struct sway_container *swayc = cursor_at(cursor, &surface, &sx, &sy); sway_seat_set_focus(cursor->seat, swayc); } @@ -98,23 +114,20 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { } static void handle_cursor_axis(struct wl_listener *listener, void *data) { - struct sway_cursor *cursor = - wl_container_of(listener, cursor, axis); + struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); struct wlr_event_pointer_axis *event = data; wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, event->orientation, event->delta); } static void handle_touch_down(struct wl_listener *listener, void *data) { - struct sway_cursor *cursor = - wl_container_of(listener, cursor, touch_down); + struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); struct wlr_event_touch_down *event = data; wlr_log(L_DEBUG, "TODO: handle touch down event: %p", event); } static void handle_touch_up(struct wl_listener *listener, void *data) { - struct sway_cursor *cursor = - wl_container_of(listener, cursor, touch_up); + struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); struct wlr_event_touch_up *event = data; wlr_log(L_DEBUG, "TODO: handle touch up event: %p", event); } @@ -127,15 +140,13 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { } static void handle_tool_axis(struct wl_listener *listener, void *data) { - struct sway_cursor *cursor = - wl_container_of(listener, cursor, tool_axis); + struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); struct wlr_event_tablet_tool_axis *event = data; wlr_log(L_DEBUG, "TODO: handle tool axis event: %p", event); } static void handle_tool_tip(struct wl_listener *listener, void *data) { - struct sway_cursor *cursor = - wl_container_of(listener, cursor, tool_tip); + struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); struct wlr_event_tablet_tool_tip *event = data; wlr_log(L_DEBUG, "TODO: handle tool tip event: %p", event); } From eb716c6c43ab3c9f265c2629538e232c4b3de625 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 16:12:02 -0400 Subject: [PATCH 316/522] Fix segfaults when focusing a workspace --- sway/input/cursor.c | 29 ++++++++++++++++++++--------- sway/ipc-server.c | 2 +- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 4abc61ea1..717d864b5 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -20,7 +20,11 @@ static void cursor_update_position(struct sway_cursor *cursor) { cursor->y = y; } -static struct sway_container *cursor_at(struct sway_cursor *cursor, +/** + * Returns the container at the cursor's position. If the container is a view, + * stores the surface at the cursor's position in `*surface`. + */ +static struct sway_container *container_at_cursor(struct sway_cursor *cursor, struct wlr_surface **surface, double *sx, double *sy) { // check for unmanaged views first struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; @@ -55,13 +59,18 @@ static struct sway_container *cursor_at(struct sway_cursor *cursor, struct sway_output *output = wlr_output->data; // find the focused workspace on the output for this seat - struct sway_container *workspace = + struct sway_container *workspace_cont = sway_seat_get_focus_inactive(cursor->seat, output->swayc); - if (workspace->type != C_WORKSPACE) { - workspace = container_parent(workspace, C_WORKSPACE); + if (workspace_cont != NULL && workspace_cont->type != C_WORKSPACE) { + workspace_cont = container_parent(workspace_cont, C_WORKSPACE); + } + if (workspace_cont == NULL) { + return output->swayc; } - return container_at(workspace, cursor->x, cursor->y, surface, sx, sy); + struct sway_container *view_cont = container_at(workspace_cont, + cursor->x, cursor->y, surface, sx, sy); + return view_cont != NULL ? view_cont : workspace_cont; } static void cursor_send_pointer_motion(struct sway_cursor *cursor, @@ -69,9 +78,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; - struct sway_container *cont = cursor_at(cursor, &surface, &sx, &sy); + struct sway_container *cont = + container_at_cursor(cursor, &surface, &sx, &sy); - if (cont) { + if (cont != NULL && surface != NULL) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); } else { @@ -105,8 +115,9 @@ 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 = cursor_at(cursor, &surface, &sx, &sy); - sway_seat_set_focus(cursor->seat, swayc); + struct sway_container *cont = + container_at_cursor(cursor, &surface, &sx, &sy); + sway_seat_set_focus(cursor->seat, cont); } wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 394161af3..6f7a0670d 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -390,7 +390,7 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace, struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); struct sway_container *focused_ws = sway_seat_get_focus(seat); - if (focused_ws->type != C_WORKSPACE) { + if (focused_ws != NULL && focused_ws->type != C_WORKSPACE) { focused_ws = container_parent(focused_ws, C_WORKSPACE); } bool focused = workspace == focused_ws; From a776ecbb860608e0f75430a53ea75a6ed19ac746 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 13:18:50 -0400 Subject: [PATCH 317/522] Add lite damage tracking This skips the renderer if nothing has changed, and renders everything otherwise. --- include/sway/output.h | 14 +++- include/sway/server.h | 1 - include/sway/tree/view.h | 4 + sway/desktop/layer_shell.c | 26 +++++-- sway/desktop/output.c | 148 +++++++++++++++++++++++++----------- sway/desktop/wl_shell.c | 1 + sway/desktop/xdg_shell_v6.c | 5 +- sway/desktop/xwayland.c | 13 ++-- sway/tree/container.c | 2 +- sway/tree/output.c | 5 +- sway/tree/view.c | 18 ++++- 11 files changed, 171 insertions(+), 66 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 6fb79987b..b4980cd8d 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -5,6 +5,7 @@ #include #include #include +#include "sway/tree/view.h" struct sway_server; struct sway_container; @@ -13,17 +14,26 @@ struct sway_output { struct wlr_output *wlr_output; struct sway_container *swayc; struct sway_server *server; - struct timespec last_frame; struct wl_list layers[4]; // sway_layer_surface::link struct wlr_box usable_area; - struct wl_listener frame; + struct timespec last_frame; + struct wlr_output_damage *damage; + struct wl_listener destroy; struct wl_listener mode; struct wl_listener transform; + struct wl_listener damage_destroy; + struct wl_listener damage_frame; + pid_t bg_pid; }; +void output_damage_whole(struct sway_output *output); + +void output_damage_whole_view(struct sway_output *output, + struct sway_view *view); + #endif diff --git a/include/sway/server.h b/include/sway/server.h index db81932f1..61f21cdbd 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -25,7 +25,6 @@ struct sway_server { struct sway_input_manager *input; struct wl_listener new_output; - struct wl_listener output_frame; struct wlr_layer_shell *layer_shell; struct wl_listener layer_shell_surface; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 54f6d90e8..526a84856 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -113,4 +113,8 @@ void view_close(struct sway_view *view); void view_update_outputs(struct sway_view *view, const struct wlr_box *before); +void view_damage_whole(struct sway_view *view); + +void view_damage_from(struct sway_view *view); + #endif diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index f7e5d19cb..5c96659a1 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -4,12 +4,13 @@ #include #include #include +#include #include #include #include "sway/layers.h" -#include "sway/tree/layout.h" #include "sway/output.h" #include "sway/server.h" +#include "sway/tree/layout.h" static void apply_exclusive(struct wlr_box *usable_area, uint32_t anchor, int32_t exclusive, @@ -210,20 +211,26 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { } else { // TODO DAMAGE from surface damage } + wlr_output_damage_add_box(output->damage, &old_geo); + wlr_output_damage_add_box(output->damage, &layer->geo); } } -static void unmap(struct wlr_layer_surface *layer_surface) { - // TODO DAMAGE +static void unmap(struct sway_layer_surface *sway_layer) { + struct wlr_output *wlr_output = sway_layer->layer_surface->output; + if (wlr_output != NULL) { + struct sway_output *output = wlr_output->data; + wlr_output_damage_add_box(output->damage, &sway_layer->geo); + } } static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_layer_surface *sway_layer = wl_container_of( - listener, sway_layer, destroy); + struct sway_layer_surface *sway_layer = wl_container_of(listener, + sway_layer, destroy); wlr_log(L_DEBUG, "Layer surface destroyed (%s)", sway_layer->layer_surface->namespace); if (sway_layer->layer_surface->mapped) { - unmap(sway_layer->layer_surface); + unmap(sway_layer); } wl_list_remove(&sway_layer->link); wl_list_remove(&sway_layer->destroy.link); @@ -239,13 +246,16 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } static void handle_map(struct wl_listener *listener, void *data) { - // TODO DAMAGE + struct sway_layer_surface *sway_layer = wl_container_of(listener, + sway_layer, map); + struct sway_output *output = sway_layer->layer_surface->output->data; + wlr_output_damage_add_box(output->damage, &sway_layer->geo); } static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_layer_surface *sway_layer = wl_container_of( listener, sway_layer, unmap); - unmap(sway_layer->layer_surface); + unmap(sway_layer); } void handle_layer_shell_surface(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/output.c b/sway/desktop/output.c index f3416c03c..ea457996d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -6,18 +6,19 @@ #include #include #include -#include +#include #include +#include #include #include #include "log.h" -#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/layers.h" -#include "sway/tree/layout.h" #include "sway/output.h" #include "sway/server.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" #include "sway/tree/view.h" /** @@ -145,13 +146,13 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, struct render_data { struct sway_output *output; - struct timespec *now; + struct timespec *when; }; -static void output_frame_view(struct sway_container *view, void *data) { +static void render_view(struct sway_container *view, void *data) { struct render_data *rdata = data; struct sway_output *output = rdata->output; - struct timespec *now = rdata->now; + struct timespec *when = rdata->when; struct wlr_output *wlr_output = output->wlr_output; struct sway_view *sway_view = view->sway_view; struct wlr_surface *surface = sway_view->surface; @@ -164,18 +165,18 @@ static void output_frame_view(struct sway_container *view, void *data) { case SWAY_XDG_SHELL_V6_VIEW: { int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; - render_surface(surface, wlr_output, now, + render_surface(surface, wlr_output, when, view->x - window_offset_x, view->y - window_offset_y, 0); render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, - now, view->x - window_offset_x, view->y - window_offset_y, 0); + when, view->x - window_offset_x, view->y - window_offset_y, 0); break; } case SWAY_WL_SHELL_VIEW: render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, - now, view->x, view->y, 0, false); + when, view->x, view->y, 0, false); break; case SWAY_XWAYLAND_VIEW: - render_surface(surface, wlr_output, now, view->x, view->y, 0); + render_surface(surface, wlr_output, when, view->x, view->y, 0); break; default: break; @@ -195,82 +196,134 @@ static void render_layer(struct sway_output *output, } } -static void handle_output_frame(struct wl_listener *listener, void *data) { - struct sway_output *soutput = wl_container_of(listener, soutput, frame); - struct wlr_output *wlr_output = data; +static void render_output(struct sway_output *output, struct timespec *when, + pixman_region32_t *damage) { + wlr_log(L_DEBUG, "render"); + struct wlr_output *wlr_output = output->wlr_output; struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); - wlr_output_make_current(wlr_output, NULL); wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); + if (!pixman_region32_not_empty(damage)) { + // Output isn't damaged but needs buffer swap + goto renderer_end; + } + + // TODO + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + pixman_region32_union_rect(damage, damage, 0, 0, width, height); + float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; wlr_renderer_clear(renderer, clear_color); - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - struct wlr_output_layout *layout = root_container.sway_root->output_layout; - const struct wlr_box *output_box = wlr_output_layout_get_box( - layout, wlr_output); + const struct wlr_box *output_box = + wlr_output_layout_get_box(layout, wlr_output); - render_layer(soutput, output_box, &now, - &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - render_layer(soutput, output_box, &now, - &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + render_layer(output, output_box, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); + render_layer(output, output_box, when, + &output->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); + sway_seat_get_focus_inactive(seat, output->swayc); struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : container_parent(focus, C_WORKSPACE)); struct render_data rdata = { - .output = soutput, - .now = &now, + .output = output, + .when = when, }; - container_descendants(workspace, C_VIEW, output_frame_view, &rdata); + container_descendants(workspace, C_VIEW, render_view, &rdata); // render unmanaged views on top struct sway_view *view; wl_list_for_each(view, &root_container.sway_root->unmanaged_views, unmanaged_view_link) { if (view->type == SWAY_XWAYLAND_VIEW) { - // the only kind of unamanged view right now is xwayland override redirect + // the only kind of unamanged view right now is xwayland override + // redirect int view_x = view->wlr_xwayland_surface->x; int view_y = view->wlr_xwayland_surface->y; - render_surface(view->surface, wlr_output, &soutput->last_frame, + render_surface(view->surface, wlr_output, &output->last_frame, view_x, view_y, 0); } } // TODO: Consider revising this when fullscreen windows are supported - render_layer(soutput, output_box, &now, - &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); - render_layer(soutput, output_box, &now, - &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); + render_layer(output, output_box, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); + render_layer(output, output_box, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); +renderer_end: wlr_renderer_end(renderer); - wlr_output_swap_buffers(wlr_output, &now, NULL); - soutput->last_frame = now; + if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { + return; + } + output->last_frame = *when; } -static void handle_output_destroy(struct wl_listener *listener, void *data) { - struct sway_output *output = wl_container_of(listener, output, destroy); +static void damage_handle_frame(struct wl_listener *listener, void *data) { + struct sway_output *output = + wl_container_of(listener, output, damage_frame); struct wlr_output *wlr_output = data; - wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); + if (!wlr_output->enabled) { + return; + } + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + bool needs_swap; + pixman_region32_t damage; + pixman_region32_init(&damage); + if (!wlr_output_damage_make_current(output->damage, &needs_swap, &damage)) { + return; + } + + if (needs_swap) { + render_output(output, &now, &damage); + } + + pixman_region32_fini(&damage); + + // TODO: send frame done events here instead of inside render_surface +} + +void output_damage_whole(struct sway_output *output) { + wlr_output_damage_add_whole(output->damage); +} + +void output_damage_whole_view(struct sway_output *output, + struct sway_view *view) { + // TODO + output_damage_whole(output); +} + +static void damage_handle_destroy(struct wl_listener *listener, void *data) { + struct sway_output *output = + wl_container_of(listener, output, damage_destroy); container_output_destroy(output->swayc); } -static void handle_output_mode(struct wl_listener *listener, void *data) { +static void handle_destroy(struct wl_listener *listener, void *data) { + struct sway_output *output = wl_container_of(listener, output, destroy); + container_output_destroy(output->swayc); +} + +static void handle_mode(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, mode); arrange_layers(output); arrange_windows(output->swayc, -1, -1); } -static void handle_output_transform(struct wl_listener *listener, void *data) { +static void handle_transform(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, transform); arrange_layers(output); arrange_windows(output->swayc, -1, -1); @@ -295,6 +348,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { wlr_output_set_mode(wlr_output, mode); } + output->damage = wlr_output_damage_create(wlr_output); + output->swayc = container_output_create(output); if (!output->swayc) { free(output); @@ -308,14 +363,17 @@ void handle_new_output(struct wl_listener *listener, void *data) { sway_input_manager_configure_xcursor(input_manager); - wl_signal_add(&wlr_output->events.frame, &output->frame); - output->frame.notify = handle_output_frame; wl_signal_add(&wlr_output->events.destroy, &output->destroy); - output->destroy.notify = handle_output_destroy; + output->destroy.notify = handle_destroy; wl_signal_add(&wlr_output->events.mode, &output->mode); - output->mode.notify = handle_output_mode; + output->mode.notify = handle_mode; wl_signal_add(&wlr_output->events.transform, &output->transform); - output->transform.notify = handle_output_transform; + output->transform.notify = handle_transform; + + wl_signal_add(&output->damage->events.frame, &output->damage_frame); + output->damage_frame.notify = damage_handle_frame; + wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); + output->damage_destroy.notify = damage_handle_destroy; arrange_layers(output); arrange_windows(&root_container, -1, -1); diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 4d4d1ed79..4fcc63178 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -67,6 +67,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { // TODO: Let floating views do whatever view->width = sway_surface->pending_width; view->height = sway_surface->pending_height; + view_damage_from(view); } static void handle_destroy(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 01f38d16a..68abc120c 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -76,6 +76,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { // TODO: Let floating views do whatever view->width = sway_surface->pending_width; view->height = sway_surface->pending_height; + view_damage_from(view); } static void handle_destroy(struct wl_listener *listener, void *data) { @@ -123,12 +124,12 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_view->sway_xdg_surface_v6 = sway_surface; sway_view->surface = xdg_surface->surface; sway_surface->view = sway_view; - + // TODO: // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria - + sway_surface->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, &sway_surface->commit); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index dfc54e867..79c675a07 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -14,10 +14,10 @@ #include "sway/input/input-manager.h" #include "log.h" - static bool assert_xwayland(struct sway_view *view) { - return sway_assert(view->type == SWAY_XWAYLAND_VIEW && view->wlr_xwayland_surface, - "Expected xwayland view!"); - } +static bool assert_xwayland(struct sway_view *view) { + return sway_assert(view->type == SWAY_XWAYLAND_VIEW, + "Expected xwayland view!"); +} static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { if (!assert_xwayland(view)) { @@ -99,6 +99,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { // TODO: Let floating views do whatever view->width = sway_surface->pending_width; view->height = sway_surface->pending_height; + view_damage_from(view); } static void handle_destroy(struct wl_listener *listener, void *data) { @@ -117,7 +118,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, unmap); - + view_damage_whole(sway_surface->view); wl_list_remove(&sway_surface->view->unmanaged_view_link); wl_list_init(&sway_surface->view->unmanaged_view_link); container_view_destroy(sway_surface->view->swayc); @@ -150,6 +151,8 @@ static void handle_map(struct wl_listener *listener, void *data) { arrange_windows(cont->parent, -1, -1); sway_input_manager_set_focus(input_manager, cont); } + + view_damage_whole(sway_surface->view); } static void handle_configure_request(struct wl_listener *listener, void *data) { diff --git a/sway/tree/container.c b/sway/tree/container.c index c3cf6c641..8705edc73 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -6,8 +6,8 @@ #include #include #include +#include "log.h" #include "sway/config.h" -#include "sway/tree/container.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/ipc-server.h" diff --git a/sway/tree/output.c b/sway/tree/output.c index 2246cb11c..7248fd006 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -26,9 +26,12 @@ struct sway_container *container_output_destroy(struct sway_container *output) { } } - wl_list_remove(&output->sway_output->frame.link); wl_list_remove(&output->sway_output->destroy.link); wl_list_remove(&output->sway_output->mode.link); + wl_list_remove(&output->sway_output->transform.link); + + wl_list_remove(&output->sway_output->damage_destroy.link); + wl_list_remove(&output->sway_output->damage_frame.link); wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); container_destroy(output); diff --git a/sway/tree/view.c b/sway/tree/view.c index 480ff693f..b7d1a41bd 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,9 +1,10 @@ #include #include +#include "log.h" +#include "sway/output.h" #include "sway/tree/container.h" #include "sway/tree/layout.h" #include "sway/tree/view.h" -#include "log.h" const char *view_get_title(struct sway_view *view) { if (view->iface.get_prop) { @@ -105,3 +106,18 @@ struct sway_container *container_view_destroy(struct sway_container *view) { arrange_windows(parent, -1, -1); return parent; } + +void view_damage_whole(struct sway_view *view) { + struct sway_container *cont = NULL; + for (int i = 0; i < root_container.children->length; ++i) { + cont = root_container.children->items[i]; + if (cont->type == C_OUTPUT) { + output_damage_whole_view(cont->sway_output, view); + } + } +} + +void view_damage_from(struct sway_view *view) { + // TODO + view_damage_whole(view); +} From 50219564c2492e4ce0bc788f062554f8a99d86f4 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 17:13:13 -0400 Subject: [PATCH 318/522] Fix white screen due to bad cast --- sway/desktop/output.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index ea457996d..2bcbad180 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -271,9 +271,8 @@ renderer_end: static void damage_handle_frame(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, damage_frame); - struct wlr_output *wlr_output = data; - if (!wlr_output->enabled) { + if (!output->wlr_output->enabled) { return; } From 3a68c012a9a32a0cda4fff772a370558d52077be Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 17:24:29 -0400 Subject: [PATCH 319/522] Remove debug, add explicit TODO --- sway/desktop/output.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2bcbad180..c248b29eb 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -198,7 +198,6 @@ static void render_layer(struct sway_output *output, static void render_output(struct sway_output *output, struct timespec *when, pixman_region32_t *damage) { - wlr_log(L_DEBUG, "render"); struct wlr_output *wlr_output = output->wlr_output; struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); @@ -210,7 +209,7 @@ static void render_output(struct sway_output *output, struct timespec *when, goto renderer_end; } - // TODO + // TODO: don't damage the whole output here int width, height; wlr_output_transformed_resolution(wlr_output, &width, &height); pixman_region32_union_rect(damage, damage, 0, 0, width, height); From 139f80b0f03cd772e408604203df81f285ca3f67 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 17:43:43 -0400 Subject: [PATCH 320/522] Handle map/unmap events in xdg-shell-v6 --- include/sway/tree/view.h | 4 +++- sway/desktop/xdg_shell_v6.c | 44 ++++++++++++++++++++++++++++--------- sway/desktop/xwayland.c | 2 -- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 526a84856..3965d2b73 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -15,6 +15,8 @@ struct sway_xdg_surface_v6 { struct wl_listener request_move; struct wl_listener request_resize; struct wl_listener request_maximize; + struct wl_listener map; + struct wl_listener unmap; struct wl_listener destroy; int pending_width, pending_height; @@ -28,8 +30,8 @@ struct sway_xwayland_surface { struct wl_listener request_resize; struct wl_listener request_maximize; struct wl_listener request_configure; - struct wl_listener unmap; struct wl_listener map; + struct wl_listener unmap; struct wl_listener destroy; int pending_width, pending_height; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 68abc120c..713437f2e 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -79,6 +79,34 @@ static void handle_commit(struct wl_listener *listener, void *data) { view_damage_from(view); } +static void handle_unmap(struct wl_listener *listener, void *data) { + struct sway_xdg_surface_v6 *sway_surface = + wl_container_of(listener, sway_surface, unmap); + view_damage_whole(sway_surface->view); + container_view_destroy(sway_surface->view->swayc); + sway_surface->view->swayc = NULL; + sway_surface->view->surface = NULL; +} + +static void handle_map(struct wl_listener *listener, void *data) { + struct sway_xdg_surface_v6 *sway_surface = + wl_container_of(listener, sway_surface, map); + struct sway_view *view = sway_surface->view; + + sway_surface->view->surface = view->wlr_xdg_surface_v6->surface; + + container_view_destroy(view->swayc); + + 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, view); + view->swayc = cont; + arrange_windows(cont->parent, -1, -1); + sway_input_manager_set_focus(input_manager, cont); + + view_damage_whole(sway_surface->view); +} + static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_xdg_surface_v6 *sway_xdg_surface = wl_container_of(listener, sway_xdg_surface, destroy); @@ -122,7 +150,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { 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; sway_surface->view = sway_view; // TODO: @@ -133,15 +160,12 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { sway_surface->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, &sway_surface->commit); + sway_surface->map.notify = handle_map; + wl_signal_add(&xdg_surface->events.map, &sway_surface->map); + + sway_surface->unmap.notify = handle_unmap; + wl_signal_add(&xdg_surface->events.unmap, &sway_surface->unmap); + sway_surface->destroy.notify = handle_destroy; 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); - sway_view->swayc = cont; - - arrange_windows(cont->parent, -1, -1); - - sway_input_manager_set_focus(input_manager, cont); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 79c675a07..01c993b38 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -127,7 +127,6 @@ static void handle_unmap(struct wl_listener *listener, void *data) { } static void handle_map(struct wl_listener *listener, void *data) { - // TODO put the view back into the tree struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, map); struct wlr_xwayland_surface *xsurface = data; @@ -193,7 +192,6 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { sway_view->iface.close = close_view; sway_view->wlr_xwayland_surface = xsurface; sway_view->sway_xwayland_surface = sway_surface; - sway_view->surface = xsurface->surface; sway_surface->view = sway_view; wl_list_init(&sway_view->unmanaged_view_link); From 6907a2f2cf134354da9902e9154211081fb88b63 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 18:29:43 -0400 Subject: [PATCH 321/522] Set exclusive zone to -1 for swaybg --- swaybg/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/swaybg/main.c b/swaybg/main.c index f431526cb..203082f64 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -300,6 +300,7 @@ int main(int argc, const char **argv) { ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); + zwlr_layer_surface_v1_set_exclusive_zone(state.layer_surface, -1); zwlr_layer_surface_v1_add_listener(state.layer_surface, &layer_surface_listener, &state); state.run_display = true; From f5470f33384713ce62c1628a550f3a52b16a6fe5 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 21:03:35 -0400 Subject: [PATCH 322/522] Pass pointer events to surface layers --- sway/input/cursor.c | 78 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d814e08ea..b498a517d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -9,8 +9,10 @@ #include "list.h" #include "log.h" #include "sway/input/cursor.h" +#include "sway/layers.h" #include "sway/output.h" #include "sway/tree/view.h" +#include "wlr-layer-shell-unstable-v1-protocol.h" static void cursor_update_position(struct sway_cursor *cursor) { double x = cursor->cursor->x; @@ -20,9 +22,35 @@ static void cursor_update_position(struct sway_cursor *cursor) { cursor->y = y; } +static struct wlr_surface *layer_surface_at(struct sway_output *output, + struct wl_list *layer, double ox, double oy, double *sx, double *sy) { + struct sway_layer_surface *sway_layer; + wl_list_for_each_reverse(sway_layer, layer, link) { + struct wlr_surface *wlr_surface = + sway_layer->layer_surface->surface; + double _sx = ox - sway_layer->geo.x; + double _sy = oy - sway_layer->geo.y; + struct wlr_box box = { + .x = sway_layer->geo.x, + .y = sway_layer->geo.y, + .width = wlr_surface->current->width, + .height = wlr_surface->current->height, + }; + // TODO: Test popups/subsurfaces + if (wlr_box_contains_point(&box, ox, oy) && + pixman_region32_contains_point( + &wlr_surface->current->input, _sx, _sy, NULL)) { + *sx = _sx; + *sy = _sy; + return wlr_surface; + } + } + return NULL; +} + /** - * Returns the container at the cursor's position. If the container is a view, - * stores the surface at the cursor's position in `*surface`. + * Returns the container at the cursor's position. If there is a surface at that + * location, it is stored in **surface (it may not be a view). */ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, struct wlr_surface **surface, double *sx, double *sy) { @@ -57,20 +85,47 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, return NULL; } struct sway_output *output = wlr_output->data; + double ox = cursor->x, oy = cursor->y; + wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); // find the focused workspace on the output for this seat - struct sway_container *workspace_cont = + struct sway_container *ws = sway_seat_get_focus_inactive(cursor->seat, output->swayc); - if (workspace_cont != NULL && workspace_cont->type != C_WORKSPACE) { - workspace_cont = container_parent(workspace_cont, C_WORKSPACE); + if (ws && ws->type != C_WORKSPACE) { + ws = container_parent(ws, C_WORKSPACE); } - if (workspace_cont == NULL) { + if (!ws) { return output->swayc; } - struct sway_container *view_cont = container_at(workspace_cont, - cursor->x, cursor->y, surface, sx, sy); - return view_cont != NULL ? view_cont : workspace_cont; + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + ox, oy, sx, sy))) { + return ws; + } + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + ox, oy, sx, sy))) { + return ws; + } + + struct sway_container *c; + if ((c = container_at(ws, cursor->x, cursor->y, surface, sx, sy))) { + return c; + } + + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + ox, oy, sx, sy))) { + return ws; + } + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + ox, oy, sx, sy))) { + return ws; + } + + return NULL; } static void cursor_send_pointer_motion(struct sway_cursor *cursor, @@ -78,8 +133,7 @@ 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; - struct sway_container *cont = - container_at_cursor(cursor, &surface, &sx, &sy); + container_at_cursor(cursor, &surface, &sx, &sy); // reset cursor if switching between clients struct wl_client *client = NULL; @@ -93,7 +147,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, } // send pointer enter/leave - if (cont != NULL && surface != NULL) { + if (surface != NULL) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); } else { From 8d1425bde9e7f17a5a9e6bce73dffcf296dad6a1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 21:38:28 -0400 Subject: [PATCH 323/522] Initialize seat pointer in swaybar --- include/swaybar/bar.h | 10 ++++ meson.build | 1 + swaybar/bar.c | 105 ++++++++++++++++++++++++++++++++++++++++++ swaybar/meson.build | 4 +- 4 files changed, 118 insertions(+), 2 deletions(-) diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 1bf2ea2d5..0768a6833 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -8,14 +8,24 @@ struct swaybar_config; struct swaybar_output; struct swaybar_workspace; +struct swaybar_pointer { + struct wl_pointer *pointer; + struct wl_cursor_theme *cursor_theme; + struct wl_cursor_image *cursor_image; + struct wl_surface *cursor_surface; + struct swaybar_output *current; +}; + struct swaybar { struct wl_display *display; struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; struct wl_shm *shm; + struct wl_seat *seat; struct swaybar_config *config; struct swaybar_output *focused_output; + struct swaybar_pointer pointer; struct status_line *status; int ipc_event_socketfd; diff --git a/meson.build b/meson.build index 49824b30c..01788fd9f 100644 --- a/meson.build +++ b/meson.build @@ -24,6 +24,7 @@ pcre = dependency('libpcre') wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots']) wayland_server = dependency('wayland-server') wayland_client = dependency('wayland-client') +wayland_cursor = dependency('wayland-cursor') wayland_egl = dependency('wayland-egl') wayland_protos = dependency('wayland-protocols') xkbcommon = dependency('xkbcommon') diff --git a/swaybar/bar.c b/swaybar/bar.c index 0fc415178..e7b8b2ca4 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -9,7 +9,13 @@ #include #include #include +#include #include +#ifdef __FreeBSD__ +#include +#else +#include +#endif #include "swaybar/render.h" #include "swaybar/config.h" #include "swaybar/event_loop.h" @@ -56,12 +62,102 @@ struct zwlr_layer_surface_v1_listener layer_surface_listener = { .closed = layer_surface_closed, }; +static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + struct swaybar *bar = data; + struct swaybar_pointer *pointer = &bar->pointer; + wl_surface_attach(pointer->cursor_surface, + wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); + wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, + pointer->cursor_image->hotspot_x, + pointer->cursor_image->hotspot_y); + wl_surface_commit(pointer->cursor_surface); +} + +static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) { + // Who cares +} + +static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { + wlr_log(L_DEBUG, "motion"); + // TODO +} + +static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + wlr_log(L_DEBUG, "button"); + // TODO +} + +static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { + wlr_log(L_DEBUG, "axis"); + // TODO +} + +static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { + // Who cares +} + +static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) { + // Who cares +} + +static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) { + // Who cares +} + +static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) { + // Who cares +} + +struct wl_pointer_listener pointer_listener = { + .enter = wl_pointer_enter, + .leave = wl_pointer_leave, + .motion = wl_pointer_motion, + .button = wl_pointer_button, + .axis = wl_pointer_axis, + .frame = wl_pointer_frame, + .axis_source = wl_pointer_axis_source, + .axis_stop = wl_pointer_axis_stop, + .axis_discrete = wl_pointer_axis_discrete, +}; + +static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) { + struct swaybar *bar = data; + if ((caps & WL_SEAT_CAPABILITY_POINTER)) { + bar->pointer.pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(bar->pointer.pointer, &pointer_listener, bar); + } +} + +static void seat_handle_name(void *data, struct wl_seat *wl_seat, + const char *name) { + // Who cares +} + +const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; + 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_seat_interface.name) == 0) { + bar->seat = wl_registry_bind(registry, name, + &wl_seat_interface, 1); + wl_seat_add_listener(bar->seat, &seat_listener, bar); } else if (strcmp(interface, wl_shm_interface.name) == 0) { bar->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); @@ -116,6 +212,15 @@ void bar_setup(struct swaybar *bar, wl_registry_add_listener(registry, ®istry_listener, bar); wl_display_roundtrip(bar->display); assert(bar->compositor && bar->layer_shell && bar->shm); + struct swaybar_pointer *pointer = &bar->pointer; + + assert(pointer->cursor_theme = wl_cursor_theme_load(NULL, 16, bar->shm)); + struct wl_cursor *cursor; + assert(cursor = wl_cursor_theme_get_cursor( + pointer->cursor_theme, "left_ptr")); + pointer->cursor_image = cursor->images[0]; + assert(pointer->cursor_surface = + wl_compositor_create_surface(bar->compositor)); // TODO: we might not necessarily be meant to do all of the outputs struct swaybar_output *output; diff --git a/swaybar/meson.build b/swaybar/meson.build index d15e8b5c1..bf6f6d7a2 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -1,6 +1,5 @@ executable( - 'swaybar', - [ + 'swaybar', [ 'bar.c', 'config.c', 'event_loop.c', @@ -20,6 +19,7 @@ executable( pangocairo, rt, wayland_client, + wayland_cursor, wlroots, ], link_with: [lib_sway_common, lib_sway_client], From ae14dfc7ae70f16a31a10f4ff2395d4ac432308d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 22:02:55 -0400 Subject: [PATCH 324/522] Implement scroll wheel workspace switching --- include/swaybar/ipc.h | 1 + swaybar/bar.c | 44 +++++++++++++++++++++++++++++++++++++++---- swaybar/ipc.c | 8 ++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 278baef0d..6ea7c4d67 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -6,5 +6,6 @@ void ipc_initialize(struct swaybar *bar, const char *bar_id); bool handle_ipc_event(struct swaybar *bar); void ipc_get_workspaces(struct swaybar *bar); +void ipc_send_workspace_command(struct swaybar *bar, const char *ws); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index e7b8b2ca4..5679a8921 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -24,6 +24,7 @@ #include "swaybar/ipc.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" @@ -67,6 +68,13 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct swaybar *bar = data; struct swaybar_pointer *pointer = &bar->pointer; + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + if (output->surface == surface) { + pointer->current = output; + break; + } + } wl_surface_attach(pointer->cursor_surface, wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, @@ -77,12 +85,12 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { - // Who cares + struct swaybar *bar = data; + bar->pointer.current = NULL; } static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - wlr_log(L_DEBUG, "motion"); // TODO } @@ -94,8 +102,36 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { - wlr_log(L_DEBUG, "axis"); - // TODO + struct swaybar *bar = data; + struct swaybar_output *output = bar->pointer.current; + if (!output) { + return; + } + double amt = wl_fixed_to_double(value); + if (!bar->config->wrap_scroll) { + int i = 0; + struct swaybar_workspace *ws = NULL; + wl_list_for_each(ws, &output->workspaces, link) { + if (ws->focused) { + break; + } + ++i; + } + int len = wl_list_length(&output->workspaces); + if (!sway_assert(i != len, "axis with null workspace")) { + return; + } + if (i == 0 && amt > 0) { + return; // Do not wrap + } + if (i == len - 1 && amt < 0) { + return; // Do not wrap + } + } + + const char *workspace_name = + amt < 0 ? "prev_on_output" : "next_on_output"; + ipc_send_workspace_command(bar, workspace_name); } static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 326f25cc2..64583df06 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -8,6 +8,14 @@ #include "swaybar/ipc.h" #include "ipc-client.h" +void ipc_send_workspace_command(struct swaybar *bar, const char *ws) { + const char *fmt = "workspace \"%s\""; + uint32_t size = snprintf(NULL, 0, fmt, ws); + char command[size]; + snprintf(command, size, fmt, ws); + ipc_single_command(bar->ipc_socketfd, IPC_COMMAND, command, &size); +} + char *parse_font(const char *font) { char *new_font = NULL; if (strncmp("pango:", font, 6) == 0) { From 2a5108a2786383cf5c3bcefd653605c916193837 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 22:42:59 -0400 Subject: [PATCH 325/522] Implement workspace switch on click --- include/swaybar/bar.h | 13 +++++++++++-- swaybar/bar.c | 34 ++++++++++++++++++++++++---------- swaybar/render.c | 39 ++++++++++++++++++++++++++++++++------- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 0768a6833..74292519f 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -2,7 +2,6 @@ #define _SWAYBAR_BAR_H #include #include "pool-buffer.h" -#include "list.h" struct swaybar_config; struct swaybar_output; @@ -14,6 +13,16 @@ struct swaybar_pointer { struct wl_cursor_image *cursor_image; struct wl_surface *cursor_surface; struct swaybar_output *current; + int x, y; +}; + +struct swaybar_hotspot { + struct wl_list link; + int x, y, width, height; + void (*callback)(struct swaybar_output *output, + int x, int y, uint32_t button, void *data); + void (*destroy)(void *data); + void *data; }; struct swaybar { @@ -42,6 +51,7 @@ struct swaybar_output { struct zwlr_layer_surface_v1 *layer_surface; struct wl_list workspaces; + struct wl_list hotspots; char *name; size_t index; @@ -61,7 +71,6 @@ struct swaybar_workspace { bool urgent; }; -// TODO: Rename stuff to match wlroots conventions (init/create/etc) void bar_setup(struct swaybar *bar, const char *socket_path, const char *bar_id); diff --git a/swaybar/bar.c b/swaybar/bar.c index 5679a8921..f743236c2 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -34,12 +34,6 @@ static void bar_init(struct swaybar *bar) { wl_list_init(&bar->outputs); } -struct swaybar_output *new_output(const char *name) { - struct swaybar_output *output = malloc(sizeof(struct swaybar_output)); - output->name = strdup(name); - return output; -} - static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height) { @@ -91,20 +85,39 @@ static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - // TODO + struct swaybar *bar = data; + bar->pointer.x = wl_fixed_to_int(surface_x); + bar->pointer.y = wl_fixed_to_int(surface_y); } static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { - wlr_log(L_DEBUG, "button"); - // TODO + struct swaybar *bar = data; + struct swaybar_pointer *pointer = &bar->pointer; + struct swaybar_output *output = pointer->current; + if (!sway_assert(output, "button with no active output")) { + return; + } + if (state != WL_POINTER_BUTTON_STATE_PRESSED) { + return; + } + struct swaybar_hotspot *hotspot; + wl_list_for_each(hotspot, &output->hotspots, link) { + if (pointer->x >= hotspot->x + && pointer->y >= hotspot->y + && pointer->x < hotspot->x + hotspot->width + && pointer->y < hotspot->y + hotspot->height) { + hotspot->callback(output, pointer->x, pointer->y, + button, hotspot->data); + } + } } static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { struct swaybar *bar = data; struct swaybar_output *output = bar->pointer.current; - if (!output) { + if (!sway_assert(output, "axis with no active output")) { return; } double amt = wl_fixed_to_double(value); @@ -206,6 +219,7 @@ static void handle_global(void *data, struct wl_registry *registry, &wl_output_interface, 1); output->index = index++; wl_list_init(&output->workspaces); + wl_list_init(&output->hotspots); wl_list_insert(&bar->outputs, &output->link); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { bar->layer_shell = wl_registry_bind( diff --git a/swaybar/render.c b/swaybar/render.c index 3d9ef66bb..c23587245 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -8,6 +9,7 @@ #include "pool-buffer.h" #include "swaybar/bar.h" #include "swaybar/config.h" +#include "swaybar/ipc.h" #include "swaybar/render.h" #include "swaybar/status_line.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" @@ -108,9 +110,14 @@ static const char *strip_workspace_number(const char *ws_name) { return ws_name; } +static void workspace_hotspot_callback(struct swaybar_output *output, + int x, int y, uint32_t button, void *data) { + ipc_send_workspace_command(output->bar, (const char *)data); +} + static uint32_t render_workspace_button(cairo_t *cairo, - struct swaybar_config *config, struct swaybar_workspace *ws, - double *x, uint32_t height) { + struct swaybar_output *output, struct swaybar_config *config, + struct swaybar_workspace *ws, double *x, uint32_t height) { const char *name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); @@ -156,8 +163,18 @@ static uint32_t render_workspace_button(cairo_t *cairo, cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); pango_printf(cairo, config->font, 1, true, "%s", name); + struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); + hotspot->x = *x; + hotspot->y = 0; + hotspot->height = height; + hotspot->width = width; + hotspot->callback = workspace_hotspot_callback; + hotspot->destroy = free; + hotspot->data = strdup(name); + wl_list_insert(&output->hotspots, &hotspot->link); + *x += width; - return ideal_height; + return height; } static uint32_t render_to_cairo(cairo_t *cairo, @@ -184,8 +201,8 @@ static uint32_t render_to_cairo(cairo_t *cairo, if (config->workspace_buttons) { struct swaybar_workspace *ws; wl_list_for_each_reverse(ws, &output->workspaces, link) { - uint32_t h = render_workspace_button( - cairo, config, ws, &x, output->height); + uint32_t h = render_workspace_button(cairo, + output, config, ws, &x, output->height); max_height = h > max_height ? h : max_height; } } @@ -203,8 +220,16 @@ static uint32_t render_to_cairo(cairo_t *cairo, return max_height > output->height ? max_height : output->height; } -void render_frame(struct swaybar *bar, - struct swaybar_output *output) { +void render_frame(struct swaybar *bar, struct swaybar_output *output) { + struct swaybar_hotspot *hotspot, *tmp; + wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) { + if (hotspot->destroy) { + hotspot->destroy(hotspot->data); + } + wl_list_remove(&hotspot->link); + free(hotspot); + } + cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); From 212b5039927842f22295c95f4e0a4f914b243194 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 23:08:24 -0400 Subject: [PATCH 326/522] Use wlr_surface_point_accepts_input --- sway/input/cursor.c | 10 +--------- sway/tree/container.c | 9 ++------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index b498a517d..7390816f4 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -30,16 +30,8 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output, sway_layer->layer_surface->surface; double _sx = ox - sway_layer->geo.x; double _sy = oy - sway_layer->geo.y; - struct wlr_box box = { - .x = sway_layer->geo.x, - .y = sway_layer->geo.y, - .width = wlr_surface->current->width, - .height = wlr_surface->current->height, - }; // TODO: Test popups/subsurfaces - if (wlr_box_contains_point(&box, ox, oy) && - pixman_region32_contains_point( - &wlr_surface->current->input, _sx, _sy, NULL)) { + if (wlr_surface_point_accepts_input(wlr_surface, _sx, _sy)) { *sx = _sx; *sy = _sy; return wlr_surface; diff --git a/sway/tree/container.c b/sway/tree/container.c index 8705edc73..746dbf1f9 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -290,8 +290,6 @@ struct sway_container *container_at(struct sway_container *parent, double oy = ly - output_box->y; double view_sx = ox - swayc->x; double view_sy = oy - swayc->y; - int width = swayc->sway_view->surface->current->width; - int height = swayc->sway_view->surface->current->height; switch (sview->type) { case SWAY_WL_SHELL_VIEW: @@ -333,11 +331,8 @@ struct sway_container *container_at(struct sway_container *parent, return swayc; } - if (view_sx > 0 && view_sx < width && - view_sy > 0 && view_sy < height && - pixman_region32_contains_point( - &sview->surface->current->input, - view_sx, view_sy, NULL)) { + if (wlr_surface_point_accepts_input( + sview->surface, view_sx, view_sy)) { *sx = view_sx; *sy = view_sy; *surface = swayc->sway_view->surface; From 5f3fce75198791ea5fd63178e5b42cfe83bccc58 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 23:58:40 -0400 Subject: [PATCH 327/522] Maximize xwayland views by default --- sway/desktop/xwayland.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 01c993b38..83e97a4ba 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -143,8 +143,11 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_view *view = sway_surface->view; container_view_destroy(view->swayc); + wlr_xwayland_surface_set_maximized(xsurface, true); + 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 *focus = sway_seat_get_focus_inactive(seat, + &root_container); struct sway_container *cont = container_view_create(focus, view); view->swayc = cont; arrange_windows(cont->parent, -1, -1); From b237fa0b22d36e52fc0be7fe785e02ea1d2456f7 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 00:13:26 -0400 Subject: [PATCH 328/522] Set xwayland cursor --- include/sway/server.h | 1 + sway/input/seat.c | 4 ++-- sway/server.c | 13 +++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index 61f21cdbd..296fbf224 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -33,6 +33,7 @@ struct sway_server { struct wl_listener xdg_shell_v6_surface; struct wlr_xwayland *xwayland; + struct wlr_xcursor_manager *xcursor_manager; struct wl_listener xwayland_surface; struct wl_listener xwayland_ready; diff --git a/sway/input/seat.c b/sway/input/seat.c index ae5362640..f969636a8 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -259,11 +259,11 @@ void sway_seat_remove_device(struct sway_seat *seat, void sway_seat_configure_xcursor(struct sway_seat *seat) { // TODO configure theme and size - const char *cursor_theme = "default"; + const char *cursor_theme = NULL; if (!seat->cursor->xcursor_manager) { seat->cursor->xcursor_manager = - wlr_xcursor_manager_create("default", 24); + wlr_xcursor_manager_create(cursor_theme, 24); if (sway_assert(seat->cursor->xcursor_manager, "Cannot create XCursor manager for theme %s", cursor_theme)) { diff --git a/sway/server.c b/sway/server.c index 728e624e5..9c1671c36 100644 --- a/sway/server.c +++ b/sway/server.c @@ -11,6 +11,7 @@ #include #include #include +#include #include // TODO WLR: make Xwayland optional #include @@ -78,6 +79,18 @@ bool server_init(struct sway_server *server) { // TODO: call server_ready now if xwayland is not enabled server->xwayland_ready.notify = server_ready; + // TODO: configurable cursor theme and size + server->xcursor_manager = wlr_xcursor_manager_create(NULL, 24); + wlr_xcursor_manager_load(server->xcursor_manager, 1); + struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( + server->xcursor_manager, "left_ptr", 1); + if (xcursor != NULL) { + struct wlr_xcursor_image *image = xcursor->images[0]; + wlr_xwayland_set_cursor(server->xwayland, image->buffer, + image->width * 4, image->width, image->height, image->hotspot_x, + image->hotspot_y); + } + server->wl_shell = wlr_wl_shell_create(server->wl_display); wl_signal_add(&server->wl_shell->events.new_surface, &server->wl_shell_surface); From 18173fb5ade5af0d09a3e270701207f55bb5f97e Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 00:35:06 -0400 Subject: [PATCH 329/522] Free bar configs on reload and exit --- sway/config.c | 17 ++++++++++------- sway/config/bar.c | 2 ++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/sway/config.c b/sway/config.c index 347d9e73f..e9e7057d2 100644 --- a/sway/config.c +++ b/sway/config.c @@ -57,38 +57,41 @@ static void free_mode(struct sway_mode *mode) { void free_config(struct sway_config *config) { config_clear_handler_context(config); - int i; - if (!config) { return; } // TODO: handle all currently unhandled lists as we add implementations if (config->symbols) { - for (i = 0; i < config->symbols->length; i++) { + for (int 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++) { + for (int i = 0; i < config->modes->length; ++i) { free_mode(config->modes->items[i]); } list_free(config->modes); } - list_free(config->bars); + if (config->bars) { + for (int i = 0; i < config->bars->length; ++i) { + free_bar_config(config->bars->items[i]); + } + list_free(config->bars); + } list_free(config->cmd_queue); list_free(config->workspace_outputs); list_free(config->pid_workspaces); list_free(config->output_configs); if (config->input_configs) { - for (i = 0; i < config->input_configs->length; i++) { + for (int i = 0; i < config->input_configs->length; i++) { free_input_config(config->input_configs->items[i]); } list_free(config->input_configs); } if (config->seat_configs) { - for (i = 0; i < config->seat_configs->length; i++) { + for (int i = 0; i < config->seat_configs->length; i++) { free_seat_config(config->seat_configs->items[i]); } list_free(config->seat_configs); diff --git a/sway/config/bar.c b/sway/config/bar.c index 48b2fc7c4..2913f059d 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -16,6 +16,7 @@ #include "log.h" static void terminate_swaybar(pid_t pid) { + wlr_log(L_DEBUG, "Terminating swaybar %d", pid); int ret = kill(pid, SIGTERM); if (ret != 0) { wlr_log_errno(L_ERROR, "Unable to terminate swaybar %d", pid); @@ -185,6 +186,7 @@ void invoke_swaybar(struct bar_config *bar) { execvp(cmd[0], cmd); exit(1); } + wlr_log(L_DEBUG, "Spawned swaybar %d", bar->pid); close(filedes[0]); ssize_t len; if (read(filedes[1], &len, sizeof(int)) == sizeof(int)) { From ae0552606b00decceaced48707fc24fedbbecad4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 09:21:15 -0400 Subject: [PATCH 330/522] Configure linux_dmabuf, primary_selection --- sway/server.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sway/server.c b/sway/server.c index 9c1671c36..59e7dc3f8 100644 --- a/sway/server.c +++ b/sway/server.c @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -54,6 +56,7 @@ bool server_init(struct sway_server *server) { wlr_screenshooter_create(server->wl_display); wlr_gamma_control_manager_create(server->wl_display); + wlr_primary_selection_device_manager_create(server->wl_display); server->new_output.notify = handle_new_output; wl_signal_add(&server->backend->events.new_output, &server->new_output); @@ -68,6 +71,11 @@ bool server_init(struct sway_server *server) { &server->xdg_shell_v6_surface); server->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface; + server->wl_shell = wlr_wl_shell_create(server->wl_display); + wl_signal_add(&server->wl_shell->events.new_surface, + &server->wl_shell_surface); + server->wl_shell_surface.notify = handle_wl_shell_surface; + // TODO make xwayland optional server->xwayland = wlr_xwayland_create(server->wl_display, server->compositor); @@ -91,10 +99,8 @@ bool server_init(struct sway_server *server) { image->hotspot_y); } - server->wl_shell = wlr_wl_shell_create(server->wl_display); - wl_signal_add(&server->wl_shell->events.new_surface, - &server->wl_shell_surface); - server->wl_shell_surface.notify = handle_wl_shell_surface; + struct wlr_egl *egl = wlr_backend_get_egl(server->backend); + wlr_linux_dmabuf_create(server->wl_display, egl); server->socket = wl_display_add_socket_auto(server->wl_display); if (!server->socket) { From 5c08e13e5093a393a42b7310de9ac24bb374d313 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 09:29:34 -0400 Subject: [PATCH 331/522] Set Xwayland seat on focus Necessary to make primary selection syncronize --- sway/input/seat.c | 8 +++++++- sway/server.c | 1 - 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index f969636a8..8d5928721 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -291,7 +291,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) { +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) { @@ -311,6 +312,11 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe if (container->type == C_VIEW) { struct sway_view *view = container->sway_view; view_set_activated(view, true); + if (view->type == SWAY_XWAYLAND_VIEW) { + struct wlr_xwayland *xwayland = + seat->input->server->xwayland; + wlr_xwayland_set_seat(xwayland, seat->wlr_seat); + } struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); if (keyboard) { diff --git a/sway/server.c b/sway/server.c index 59e7dc3f8..f5cc199c3 100644 --- a/sway/server.c +++ b/sway/server.c @@ -110,7 +110,6 @@ bool server_init(struct sway_server *server) { } input_manager = sway_input_manager_create(server); - return true; } From 8aa195e3116d7dbc897da50d2795e4a638c0b184 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 09:45:11 -0400 Subject: [PATCH 332/522] Fix #1104 --- sway/input/cursor.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 7390816f4..6b8522bf4 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -175,7 +175,13 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { double sx, sy; struct sway_container *cont = container_at_cursor(cursor, &surface, &sx, &sy); - sway_seat_set_focus(cursor->seat, cont); + // TODO: Actually test if the surface accepts keyboard input, rather + // than assuming it does not + // Layer surfaces with keyboard_interactive=true will change how this + // works, for example. + if (!surface || cont->type == C_VIEW) { + sway_seat_set_focus(cursor->seat, cont); + } } wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, From a44a71c116b3bc7fcc80628d3213e2612b701f6c Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 10:39:05 -0400 Subject: [PATCH 333/522] Make it clear that unmanaged views don't have a container view->swayc is NULL anyway. --- sway/input/cursor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 6b8522bf4..b5ba51363 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -63,7 +63,7 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, *surface = xsurface->surface; *sx = cursor->x - box.x; *sy = cursor->y - box.y; - return view->swayc; + return NULL; } } } From ccdcaa478f139736157da6bc7c648977027fac3c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 10:47:04 -0400 Subject: [PATCH 334/522] Fix bug with previous commit --- sway/input/cursor.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 6b8522bf4..75c98836d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -175,11 +175,26 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { double sx, sy; struct sway_container *cont = container_at_cursor(cursor, &surface, &sx, &sy); - // TODO: Actually test if the surface accepts keyboard input, rather - // than assuming it does not - // Layer surfaces with keyboard_interactive=true will change how this - // works, for example. - if (!surface || cont->type == C_VIEW) { + // 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->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); } } From eb5a8e03ff10d956de70f121bc70fd4cad524a9f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 10:51:39 -0400 Subject: [PATCH 335/522] Check for null container --- sway/input/cursor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index f558a37a2..74af64268 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -182,7 +182,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { // // TODO: Replace this condition with something like // !surface_accepts_keyboard_input - if (surface && cont->type != C_VIEW) { + 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); From 65797179944b146e6e16894eb6c8e9d71fda09eb Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 10:28:01 -0400 Subject: [PATCH 336/522] Fix xwayland configure position --- sway/desktop/xwayland.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 01c993b38..5f9c99a3b 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -67,13 +67,10 @@ static void set_position(struct sway_view *view, double ox, double oy) { view->swayc->x = ox; view->swayc->y = oy; - if (view->width == 0 || view->height == 0) { - return; - } - wlr_xwayland_surface_configure(view->wlr_xwayland_surface, ox + loutput->x, oy + loutput->y, - view->width, view->height); + view->wlr_xwayland_surface->width, + view->wlr_xwayland_surface->height); } static void set_activated(struct sway_view *view, bool activated) { From 0f7936735cfc8224f9926199b7e807e95d86d900 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 10:56:49 -0400 Subject: [PATCH 337/522] Fix unmanaged views rendering on all outputs --- sway/desktop/output.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index c248b29eb..24c0bf403 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -243,14 +243,23 @@ static void render_output(struct sway_output *output, struct timespec *when, struct sway_view *view; wl_list_for_each(view, &root_container.sway_root->unmanaged_views, unmanaged_view_link) { - if (view->type == SWAY_XWAYLAND_VIEW) { - // the only kind of unamanged view right now is xwayland override - // redirect - int view_x = view->wlr_xwayland_surface->x; - int view_y = view->wlr_xwayland_surface->y; - render_surface(view->surface, wlr_output, &output->last_frame, - view_x, view_y, 0); + if (view->type != SWAY_XWAYLAND_VIEW) { + continue; } + + const struct wlr_box view_box = { + .x = view->wlr_xwayland_surface->x, + .y = view->wlr_xwayland_surface->y, + .width = view->wlr_xwayland_surface->width, + .height = view->wlr_xwayland_surface->height, + }; + struct wlr_box intersection; + if (!wlr_box_intersection(&view_box, output_box, &intersection)) { + continue; + } + + render_surface(view->surface, wlr_output, &output->last_frame, + view_box.x - output_box->x, view_box.y - output_box->y, 0); } // TODO: Consider revising this when fullscreen windows are supported From c901510e01f7648a549187b128ed9d0f9c5627eb Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Sat, 31 Mar 2018 11:13:20 -0400 Subject: [PATCH 338/522] Fixes back-and-forth name saving for non-empty ws --- sway/tree/workspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c629f1f17..de1bf1590 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -351,7 +351,7 @@ bool workspace_switch(struct sway_container *workspace) { } struct sway_container *active_ws = focus; if (active_ws->type != C_WORKSPACE) { - container_parent(focus, C_WORKSPACE); + active_ws = container_parent(focus, C_WORKSPACE); } if (config->auto_back_and_forth From 98b67e2399df70d1e8354d5641744d1730a60189 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 11:30:15 -0400 Subject: [PATCH 339/522] Fix xwayland configure in set_size --- sway/desktop/output.c | 10 ++++++---- sway/desktop/xwayland.c | 6 +++--- sway/input/cursor.c | 30 ++++++++++++++++-------------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 24c0bf403..0d706c528 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -247,11 +247,13 @@ static void render_output(struct sway_output *output, struct timespec *when, continue; } + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; + const struct wlr_box view_box = { - .x = view->wlr_xwayland_surface->x, - .y = view->wlr_xwayland_surface->y, - .width = view->wlr_xwayland_surface->width, - .height = view->wlr_xwayland_surface->height, + .x = xsurface->x, + .y = xsurface->y, + .width = xsurface->width, + .height = xsurface->height, }; struct wlr_box intersection; if (!wlr_box_intersection(&view_box, output_box, &intersection)) { diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 5f9c99a3b..bbaa88c81 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -41,7 +41,7 @@ static void set_size(struct sway_view *view, int width, int height) { view->sway_xwayland_surface->pending_height = height; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - wlr_xwayland_surface_configure(xsurface, view->swayc->x, view->swayc->y, + wlr_xwayland_surface_configure(xsurface, xsurface->x, xsurface->y, width, height); } @@ -151,7 +151,7 @@ static void handle_map(struct wl_listener *listener, void *data) { view_damage_whole(sway_surface->view); } -static void handle_configure_request(struct wl_listener *listener, void *data) { +static void handle_request_configure(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, request_configure); struct wlr_xwayland_surface_configure_event *ev = data; @@ -206,7 +206,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xsurface->events.request_configure, &sway_surface->request_configure); - sway_surface->request_configure.notify = handle_configure_request; + sway_surface->request_configure.notify = handle_request_configure; wl_signal_add(&xsurface->events.unmap, &sway_surface->unmap); sway_surface->unmap.notify = handle_unmap; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 74af64268..67776f8fe 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -50,21 +50,23 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; struct sway_view *view; wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) { - if (view->type == SWAY_XWAYLAND_VIEW) { - struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - struct wlr_box box = { - .x = xsurface->x, - .y = xsurface->y, - .width = xsurface->width, - .height = xsurface->height, - }; + if (view->type != SWAY_XWAYLAND_VIEW) { + continue; + } - if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { - *surface = xsurface->surface; - *sx = cursor->x - box.x; - *sy = cursor->y - box.y; - return NULL; - } + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; + struct wlr_box box = { + .x = xsurface->x, + .y = xsurface->y, + .width = xsurface->width, + .height = xsurface->height, + }; + + if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { + *surface = xsurface->surface; + *sx = cursor->x - box.x; + *sy = cursor->y - box.y; + return NULL; } } From 59f362196b84d6cf455b574d887ec3e0c3163eb3 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 12:01:02 -0400 Subject: [PATCH 340/522] assert(fd != -1); Thanks @martinetd --- client/pool-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pool-buffer.c b/client/pool-buffer.c index 93cfcfc5a..b5ed9c988 100644 --- a/client/pool-buffer.c +++ b/client/pool-buffer.c @@ -57,7 +57,7 @@ static struct pool_buffer *create_buffer(struct wl_shm *shm, char *name; int fd = create_pool_file(size, &name); - assert(fd); + assert(fd != -1); void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); buf->buffer = wl_shm_pool_create_buffer(pool, 0, From ae6d459000865f0a3a54a1d0429ee28b282a7954 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 10:49:52 -0400 Subject: [PATCH 341/522] Implement mouse warping --- sway/commands.c | 1 + sway/commands/mouse_warping.c | 19 +++++++++++++++++++ sway/input/cursor.c | 4 ++-- sway/input/seat.c | 18 ++++++++++++++++-- sway/meson.build | 1 + 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 sway/commands/mouse_warping.c diff --git a/sway/commands.c b/sway/commands.c index eee7f254e..d983dcbb1 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -101,6 +101,7 @@ static struct cmd_handler handlers[] = { { "include", cmd_include }, { "input", cmd_input }, { "mode", cmd_mode }, + { "mouse_warping", cmd_mouse_warping }, { "output", cmd_output }, { "seat", cmd_seat }, { "workspace", cmd_workspace }, diff --git a/sway/commands/mouse_warping.c b/sway/commands/mouse_warping.c new file mode 100644 index 000000000..eef32ce78 --- /dev/null +++ b/sway/commands/mouse_warping.c @@ -0,0 +1,19 @@ +#include +#include +#include "sway/commands.h" + +struct cmd_results *cmd_mouse_warping(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) { + return error; + } else if (strcasecmp(argv[0], "output") == 0) { + config->mouse_warping = true; + } else if (strcasecmp(argv[0], "none") == 0) { + config->mouse_warping = false; + } else { + return cmd_results_new(CMD_FAILURE, "mouse_warping", + "Expected 'mouse_warping output|none'"); + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 74af64268..9cdd66d8e 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -156,8 +156,8 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { cursor_send_pointer_motion(cursor, event->time_msec); } -static void handle_cursor_motion_absolute(struct wl_listener *listener, - void *data) { +static void handle_cursor_motion_absolute( + struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; diff --git a/sway/input/seat.c b/sway/input/seat.c index 8d5928721..eab5cf40d 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -333,15 +333,29 @@ void sway_seat_set_focus(struct sway_seat *seat, if (last_focus) { struct sway_container *last_ws = last_focus; if (last_ws && last_ws->type != C_WORKSPACE) { - last_ws = container_parent(last_focus, C_WORKSPACE); + last_ws = container_parent(last_ws, C_WORKSPACE); } if (last_ws) { - wlr_log(L_DEBUG, "sending workspace event"); ipc_event_workspace(last_ws, container, "focus"); if (last_ws->children->length == 0) { container_workspace_destroy(last_ws); } } + struct sway_container *last_output = last_focus; + if (last_output && last_output->type != C_OUTPUT) { + last_output = container_parent(last_output, C_OUTPUT); + } + struct sway_container *new_output = container; + if (new_output && new_output->type != C_OUTPUT) { + new_output = container_parent(new_output, C_OUTPUT); + } + if (new_output != last_output && config->mouse_warping) { + struct wlr_output *output = new_output->sway_output->wlr_output; + // TODO: Change container coords to layout coords + double x = container->x + output->lx + container->width / 2.0; + double y = container->y + output->ly + container->height / 2.0; + wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + } } if (last_focus && last_focus->type == C_VIEW && diff --git a/sway/meson.build b/sway/meson.build index e8a192f03..5bc579648 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -63,6 +63,7 @@ sway_sources = files( 'commands/input/xkb_options.c', 'commands/input/xkb_rules.c', 'commands/input/xkb_variant.c', + 'commands/mouse_warping.c', 'commands/output.c', 'commands/reload.c', 'commands/workspace.c', From 9b38ef950fcf293ba11f54c14d8b3a87f050b154 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 10:11:15 -0400 Subject: [PATCH 342/522] 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 diff --git a/include/sway/config.h b/include/sway/config.h index ac1105b49..03b51948c 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 d983dcbb1..905442208 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 000000000..661e7852b --- /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 e9e7057d2..0eecf7f6c 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 9cdd66d8e..35dd5dc8e 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 5bc579648..0cc620ea8 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', From b9d2983324c91f0a2805b1f10afcf2a929f939b4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 11:18:29 -0400 Subject: [PATCH 343/522] Fix interaction between warping and following --- sway/input/cursor.c | 5 ++++- sway/input/seat.c | 13 ++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 35dd5dc8e..2a0960336 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -120,6 +120,9 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, return NULL; } +void _sway_seat_set_focus(struct sway_seat *seat, + struct sway_container *container, bool warp); + static void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time) { struct wlr_seat *seat = cursor->seat->wlr_seat; @@ -127,7 +130,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, double 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); + _sway_seat_set_focus(cursor->seat, c, false); } // reset cursor if switching between clients diff --git a/sway/input/seat.c b/sway/input/seat.c index eab5cf40d..4e7e018de 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -291,8 +291,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) { +void _sway_seat_set_focus(struct sway_seat *seat, + struct sway_container *container, bool warp) { struct sway_container *last_focus = sway_seat_get_focus(seat); if (container && last_focus == container) { @@ -349,7 +349,9 @@ void sway_seat_set_focus(struct sway_seat *seat, if (new_output && new_output->type != C_OUTPUT) { new_output = container_parent(new_output, C_OUTPUT); } - if (new_output != last_output && config->mouse_warping) { + if (new_output && last_output && new_output != last_output + && config->mouse_warping && warp) { + wlr_log(L_DEBUG, "warpin the mouse baby"); struct wlr_output *output = new_output->sway_output->wlr_output; // TODO: Change container coords to layout coords double x = container->x + output->lx + container->width / 2.0; @@ -367,6 +369,11 @@ void sway_seat_set_focus(struct sway_seat *seat, seat->has_focus = (container != NULL); } +void sway_seat_set_focus(struct sway_seat *seat, + struct sway_container *container) { + _sway_seat_set_focus(seat, container, true); +} + struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { struct sway_seat_container *current = NULL; struct sway_container *parent = NULL; From 8aedc042eeaa95a7a0be7c1dd06e3739ee1c7bd4 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 13:47:22 -0400 Subject: [PATCH 344/522] Fix two segfaults when destroying outputs --- sway/desktop/layer_shell.c | 5 +++-- sway/tree/layout.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 5c96659a1..c18f51c71 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -238,11 +238,12 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&sway_layer->unmap.link); wl_list_remove(&sway_layer->surface_commit.link); if (sway_layer->layer_surface->output != NULL) { + struct sway_output *output = sway_layer->layer_surface->output->data; + arrange_layers(output); + wl_list_remove(&sway_layer->output_destroy.link); } - struct sway_output *output = sway_layer->layer_surface->output->data; free(sway_layer); - arrange_layers(output); } static void handle_map(struct wl_listener *listener, void *data) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 588ceb2db..ce0682dc9 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -107,7 +107,7 @@ struct sway_container *container_reap_empty(struct sway_container *container) { return NULL; } wlr_log(L_DEBUG, "reaping %p %s", container, container->name); - while (container->children->length == 0) { + while (container != &root_container && container->children->length == 0) { if (container->type == C_WORKSPACE) { if (!workspace_is_visible(container)) { struct sway_container *parent = container->parent; From f2332dc75c05a62f87ba290433f12f4ce7f467ec Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 15:13:27 -0400 Subject: [PATCH 345/522] Address review feedback --- include/sway/input/seat.h | 3 +++ sway/input/cursor.c | 5 +---- sway/input/seat.c | 13 ++++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 496bfd5d0..31210a5a1 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -56,6 +56,9 @@ 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_warp(struct sway_seat *seat, + struct sway_container *container, bool warp); + struct sway_container *sway_seat_get_focus(struct sway_seat *seat); /** diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 2a0960336..4a3f558d4 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -120,9 +120,6 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, return NULL; } -void _sway_seat_set_focus(struct sway_seat *seat, - struct sway_container *container, bool warp); - static void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time) { struct wlr_seat *seat = cursor->seat->wlr_seat; @@ -130,7 +127,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, double 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, false); + sway_seat_set_focus_warp(cursor->seat, c, false); } // reset cursor if switching between clients diff --git a/sway/input/seat.c b/sway/input/seat.c index 4e7e018de..9aa34acac 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,5 +1,6 @@ #define _XOPEN_SOURCE 700 #include +#include #include #include "sway/tree/container.h" #include "sway/input/seat.h" @@ -291,7 +292,7 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -void _sway_seat_set_focus(struct sway_seat *seat, +void sway_seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { struct sway_container *last_focus = sway_seat_get_focus(seat); @@ -351,12 +352,14 @@ void _sway_seat_set_focus(struct sway_seat *seat, } if (new_output && last_output && new_output != last_output && config->mouse_warping && warp) { - wlr_log(L_DEBUG, "warpin the mouse baby"); struct wlr_output *output = new_output->sway_output->wlr_output; - // TODO: Change container coords to layout coords double x = container->x + output->lx + container->width / 2.0; double y = container->y + output->ly + container->height / 2.0; - wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + if (!wlr_output_layout_contains_point( + root_container.sway_root->output_layout, + output, seat->cursor->cursor->x, seat->cursor->cursor->y)) { + wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + } } } @@ -371,7 +374,7 @@ void _sway_seat_set_focus(struct sway_seat *seat, void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container) { - _sway_seat_set_focus(seat, container, true); + sway_seat_set_focus_warp(seat, container, true); } struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { From 7706d83160267be61accb1b6f7bdc2f43299cae7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 00:44:17 -0400 Subject: [PATCH 346/522] basic split containers --- include/sway/input/seat.h | 2 +- include/sway/tree/container.h | 2 + include/sway/tree/layout.h | 3 + sway/commands.c | 4 ++ sway/commands/kill.c | 29 +++++---- sway/commands/split.c | 107 ++++++++++++++++++++++++++++++++++ sway/input/seat.c | 42 ++++++------- sway/meson.build | 1 + sway/tree/container.c | 7 ++- sway/tree/layout.c | 99 ++++++++++++++++++++++++++----- 10 files changed, 245 insertions(+), 51 deletions(-) create mode 100644 sway/commands/split.c diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 31210a5a1..38795e14d 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -74,7 +74,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 sway_container_type type); + struct sway_container *container, 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 6aa66da02..46f1c5aba 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -87,6 +87,8 @@ struct sway_container { } events; }; +struct sway_container *container_create(enum sway_container_type type); + // TODO only one container create function and pass the type? struct sway_container *container_output_create( struct sway_output *sway_output); diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 0a904c4b5..79c14edaf 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -54,4 +54,7 @@ void arrange_windows(struct sway_container *container, struct sway_container *container_get_in_direction(struct sway_container *container, struct sway_seat *seat, enum movement_direction dir); +struct sway_container *container_split(struct sway_container *child, + enum sway_container_layout layout); + #endif diff --git a/sway/commands.c b/sway/commands.c index 905442208..c85ddf7a4 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -163,6 +163,10 @@ static struct cmd_handler command_handlers[] = { { "kill", cmd_kill }, { "layout", cmd_layout }, { "reload", cmd_reload }, + { "split", cmd_split }, + { "splith", cmd_splith }, + { "splitt", cmd_splitt }, + { "splitv", cmd_splitv }, }; static int handler_compare(const void *_a, const void *_b) { diff --git a/sway/commands/kill.c b/sway/commands/kill.c index f67747679..801208322 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -3,21 +3,30 @@ #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/tree/view.h" +#include "sway/tree/container.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; - if (type != C_VIEW && type != C_CONTAINER) { + struct sway_container *con = + config->handler_context.current_container; + + switch (con->type) { + case C_ROOT: + case C_OUTPUT: + case C_WORKSPACE: return cmd_results_new(CMD_INVALID, NULL, "Can only kill views and containers with this command"); - } - - // TODO close arbitrary containers without a view - struct sway_view *view = - config->handler_context.current_container->sway_view; - - if (view) { - view_close(view); + break; + case C_CONTAINER: + con = container_destroy(con); + con = container_reap_empty(con); + arrange_windows(con, -1, -1); + break; + case C_VIEW: + view_close(con->sway_view); + break; + default: + break; } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/split.c b/sway/commands/split.c new file mode 100644 index 000000000..6df20e88d --- /dev/null +++ b/sway/commands/split.c @@ -0,0 +1,107 @@ +#include +#include +#include "sway/commands.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" +#include "sway/tree/view.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" +#include "log.h" + +static struct cmd_results *_do_split(int argc, char **argv, int layout) { + char *name = layout == L_VERT ? "splitv" : + layout == L_HORIZ ? "splith" : "split"; + struct cmd_results *error = NULL; + if (config->reading) { + return cmd_results_new(CMD_FAILURE, name, + "Can't be used in config file."); + } + if (!config->active) { + return cmd_results_new(CMD_FAILURE, name, + "Can only be used when sway is running."); + } + if ((error = checkarg(argc, name, EXPECTED_EQUAL_TO, 0))) { + return error; + } + + struct sway_container *focused = config->handler_context.current_container; + + // TODO floating: dont split + + /* Case that focus is on an workspace with 0/1 children.change its layout */ + if (focused->type == C_WORKSPACE && focused->children->length <= 1) { + wlr_log(L_DEBUG, "changing workspace layout"); + container_set_layout(focused, layout); + } else if (focused->type != C_WORKSPACE && + focused->parent->children->length == 1) { + /* Case of no siblings. change parent layout */ + wlr_log(L_DEBUG, "changing container layout"); + container_set_layout(focused->parent, layout); + } else { + // regular case where new split container is build around focused + // container or in case of workspace, container inherits its children + wlr_log(L_DEBUG, + "Adding new container around current focused container"); + wlr_log(L_INFO, "FOCUSED SIZE: %.f %.f", + focused->width, focused->height); + + struct sway_container *parent = container_split(focused, layout); + arrange_windows(parent, -1, -1); + } + + // TODO borders: update borders + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *cmd_split(int argc, char **argv) { + struct cmd_results *error = NULL; + if (config->reading) { + return cmd_results_new(CMD_FAILURE, "split", + "Can't be used in config file."); + } + if (!config->active) { + return cmd_results_new(CMD_FAILURE, "split", + "Can only be used when sway is running."); + } + if ((error = checkarg(argc, "split", EXPECTED_EQUAL_TO, 1))) { + return error; + } + if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { + _do_split(argc - 1, argv + 1, L_VERT); + } else if (strcasecmp(argv[0], "h") == 0 || + strcasecmp(argv[0], "horizontal") == 0) { + _do_split(argc - 1, argv + 1, L_HORIZ); + } else if (strcasecmp(argv[0], "t") == 0 || + strcasecmp(argv[0], "toggle") == 0) { + struct sway_container *focused = + config->handler_context.current_container; + if (focused->parent->layout == L_VERT) { + _do_split(argc - 1, argv + 1, L_HORIZ); + } else { + _do_split(argc - 1, argv + 1, L_VERT); + } + } else { + error = cmd_results_new(CMD_FAILURE, "split", + "Invalid split command (expected either horizontal or vertical)."); + return error; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *cmd_splitv(int argc, char **argv) { + return _do_split(argc, argv, L_VERT); +} + +struct cmd_results *cmd_splith(int argc, char **argv) { + return _do_split(argc, argv, L_HORIZ); +} + +struct cmd_results *cmd_splitt(int argc, char **argv) { + struct sway_container *focused = config->handler_context.current_container; + if (focused->parent->layout == L_VERT) { + return _do_split(argc, argv, L_HORIZ); + } else { + return _do_split(argc, argv, L_VERT); + } +} diff --git a/sway/input/seat.c b/sway/input/seat.c index 9aa34acac..e0fd314ad 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include #include #include #include @@ -378,24 +379,7 @@ void sway_seat_set_focus(struct sway_seat *seat, } struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { - struct sway_seat_container *current = NULL; - struct sway_container *parent = NULL; - wl_list_for_each(current, &seat->focus_stack, link) { - parent = current->container->parent; - - if (current->container == container) { - return current->container; - } - - while (parent) { - if (parent == container) { - return current->container; - } - parent = parent->parent; - } - } - - return NULL; + return sway_seat_get_focus_by_type(seat, container, C_TYPES); } struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { @@ -406,13 +390,25 @@ struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { } 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; + struct sway_container *container, enum sway_container_type type) { + struct sway_seat_container *current = NULL; + struct sway_container *parent = NULL; + wl_list_for_each(current, &seat->focus_stack, link) { + parent = current->container->parent; + + if (current->container == container) { + return current->container; + } + + while (parent) { + if (parent == container && (type == C_TYPES || current->container->type == type)) { + return current->container; + } + parent = parent->parent; + } } - return container_parent(focus, type); + return NULL; } void sway_seat_set_config(struct sway_seat *seat, diff --git a/sway/meson.build b/sway/meson.build index 0cc620ea8..b4775d586 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -19,6 +19,7 @@ sway_sources = files( 'commands/input.c', 'commands/layout.c', 'commands/mode.c', + 'commands/split.c', 'commands/seat.c', 'commands/seat/attach.c', 'commands/seat/fallback.c', diff --git a/sway/tree/container.c b/sway/tree/container.c index 746dbf1f9..7b88cccbc 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -38,7 +38,7 @@ static void notify_new_container(struct sway_container *container) { ipc_event_window(container, "new"); } -static struct sway_container *container_create(enum sway_container_type type) { +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; struct sway_container *c = calloc(1, sizeof(struct sway_container)); @@ -66,13 +66,14 @@ struct sway_container *container_destroy(struct sway_container *cont) { wl_signal_emit(&cont->events.destroy, cont); struct sway_container *parent = cont->parent; - if (cont->children) { + if (cont->children != NULL) { // remove children until there are no more, container_destroy calls // container_remove_child, which removes child from this container - while (cont->children->length) { + while (cont->children->length != 0) { container_destroy(cont->children->items[0]); } list_free(cont->children); + cont->children = NULL; } if (cont->marks) { list_foreach(cont->marks, free); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce0682dc9..62df19e9f 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -100,6 +101,8 @@ void container_add_child(struct sway_container *parent, parent, parent->type, parent->width, parent->height); list_add(parent->children, child); child->parent = parent; + // TODO: set focus for this container? + sway_input_manager_set_focus(input_manager, child); } struct sway_container *container_reap_empty(struct sway_container *container) { @@ -135,7 +138,7 @@ struct sway_container *container_remove_child(struct sway_container *child) { } } child->parent = NULL; - return container_reap_empty(parent); + return parent; } void container_move_to(struct sway_container* container, @@ -322,7 +325,12 @@ static void apply_horiz_layout(struct sway_container *container, wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); - view_set_position(child->sway_view, child_x, y); + if (child->type == C_VIEW) { + view_set_position(child->sway_view, child_x, y); + } else { + child->x = child_x; + child->y = y; + } if (i == end - 1) { double remaining_width = x + width - child_x; @@ -505,9 +513,9 @@ 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) { +struct sway_container *container_get_in_direction( + struct sway_container *container, struct sway_seat *seat, + enum movement_direction dir) { if (dir == MOVE_CHILD) { return sway_seat_get_focus_inactive(seat, container); } @@ -559,7 +567,6 @@ static struct sway_container *get_swayc_in_direction_under( struct sway_container *wrap_candidate = NULL; while (true) { - // Test if we can even make a difference here bool can_move = false; int desired; int idx = index_child(container); @@ -589,7 +596,7 @@ static struct sway_container *get_swayc_in_direction_under( } if (next->children && next->children->length) { // TODO consider floating children as well - return sway_seat_get_focus_inactive(seat, next); + return sway_seat_get_focus_by_type(seat, next, C_VIEW); } else { return next; } @@ -619,21 +626,22 @@ static struct sway_container *get_swayc_in_direction_under( wrap_candidate = parent->children->items[0]; } if (config->force_focus_wrapping) { - return wrap_candidate; + return sway_seat_get_focus_by_type(seat, wrap_candidate, C_VIEW); } } } else { 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]; + return sway_seat_get_focus_by_type(seat, + parent->children->items[desired], C_VIEW); } } if (!can_move) { container = parent; parent = parent->parent; - if (!parent || container == limit) { + if (!parent) { // wrapping is the last chance return wrap_candidate; } @@ -641,8 +649,71 @@ static struct sway_container *get_swayc_in_direction_under( } } -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); +struct sway_container *container_replace_child(struct sway_container *child, + struct sway_container *new_child) { + struct sway_container *parent = child->parent; + if (parent == NULL) { + return NULL; + } + int i = index_child(child); + + // TODO floating + parent->children->items[i] = new_child; + new_child->parent = parent; + child->parent = NULL; + + // Set geometry for new child + new_child->x = child->x; + new_child->y = child->y; + new_child->width = child->width; + new_child->height = child->height; + + // reset geometry for child + child->width = 0; + child->height = 0; + + return parent; +} + +struct sway_container *container_split(struct sway_container *child, + enum sway_container_layout layout) { + // TODO floating: cannot split a floating container + if (!sway_assert(child, "child cannot be null")) { + return NULL; + } + struct sway_container *cont = container_create(C_CONTAINER); + + wlr_log(L_DEBUG, "creating container %p around %p", cont, child); + + cont->prev_layout = L_NONE; + cont->layout = layout; + cont->width = child->width; + cont->height = child->height; + cont->x = child->x; + cont->y = child->y; + + /* Container inherits all of workspaces children, layout and whatnot */ + if (child->type == C_WORKSPACE) { + struct sway_container *workspace = child; + // reorder focus + int i; + for (i = 0; i < workspace->children->length; ++i) { + ((struct sway_container *)workspace->children->items[i])->parent = + cont; + } + + // Swap children + list_t *tmp_list = workspace->children; + workspace->children = cont->children; + cont->children = tmp_list; + // add container to workspace chidren + container_add_child(workspace, cont); + // give them proper layouts + cont->layout = workspace->workspace_layout; + cont->prev_layout = workspace->prev_layout; + } else { // Or is built around container + container_replace_child(child, cont); + container_add_child(cont, child); + } + return cont; } From f7a20726fc82c7eee1fe6756eb3aefebecb34ce6 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 10:43:46 -0400 Subject: [PATCH 347/522] temporarily add LD_LIBRARY_PATH stuff --- sway/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/main.c b/sway/main.c index ded922ee7..e7f8ddd38 100644 --- a/sway/main.c +++ b/sway/main.c @@ -118,7 +118,7 @@ void run_as_ipc_client(char *command, char *socket_path) { static void log_env() { const char *log_vars[] = { "PATH", - "LD_LOAD_PATH", + "LD_LIBRARY_PATH", "LD_PRELOAD_PATH", "LD_LIBRARY_PATH", "SWAY_CURSOR_THEME", From e7ecb001d70c71f799547d15cd45c235412af402 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 13:20:05 -0400 Subject: [PATCH 348/522] reap container parent on destroy --- sway/commands/kill.c | 1 - sway/tree/container.c | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 801208322..e6036cb3b 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -19,7 +19,6 @@ struct cmd_results *cmd_kill(int argc, char **argv) { break; case C_CONTAINER: con = container_destroy(con); - con = container_reap_empty(con); arrange_windows(con, -1, -1); break; case C_VIEW: diff --git a/sway/tree/container.c b/sway/tree/container.c index 7b88cccbc..f972ac24f 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -58,7 +58,7 @@ struct sway_container *container_create(enum sway_container_type type) { return c; } -struct sway_container *container_destroy(struct sway_container *cont) { +static struct sway_container *_container_destroy(struct sway_container *cont) { if (cont == NULL) { return NULL; } @@ -89,6 +89,11 @@ struct sway_container *container_destroy(struct sway_container *cont) { return parent; } +struct sway_container *container_destroy(struct sway_container *cont) { + cont = _container_destroy(cont); + return container_reap_empty(cont->parent); +} + struct sway_container *container_output_create( struct sway_output *sway_output) { struct wlr_box size; From 6f7b33e6919b2a8467ea1638ee56ac0232408793 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 15:22:10 -0400 Subject: [PATCH 349/522] handle container destroy in the seat --- include/sway/tree/container.h | 3 + sway/input/seat.c | 104 +++++++++++++++++++++++----------- sway/tree/container.c | 13 +++++ 3 files changed, 88 insertions(+), 32 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 46f1c5aba..285f10111 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -150,4 +150,7 @@ void container_for_each_descendant_dfs(struct sway_container *container, bool container_has_anscestor(struct sway_container *descendant, struct sway_container *anscestor); +bool container_has_child(struct sway_container *con, + struct sway_container *child); + #endif diff --git a/sway/input/seat.c b/sway/input/seat.c index e0fd314ad..e3d53cb65 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -27,6 +27,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { } void sway_seat_destroy(struct sway_seat *seat) { + // TODO destroy seat containers struct sway_seat_device *seat_device, *next; wl_list_for_each_safe(seat_device, next, &seat->devices, link) { seat_device_destroy(seat_device); @@ -36,30 +37,57 @@ void sway_seat_destroy(struct sway_seat *seat) { wlr_seat_destroy(seat->wlr_seat); } +static struct sway_seat_container *seat_container_from_container( + struct sway_seat *seat, struct sway_container *con); + +static void seat_container_destroy(struct sway_seat_container *seat_con) { + struct sway_container *con = seat_con->container; + struct sway_container *child = NULL; + + if (con->children != NULL) { + for (int i = 0; i < con->children->length; ++i) { + child = con->children->items[i]; + struct sway_seat_container *seat_child = + seat_container_from_container(seat_con->seat, child); + seat_container_destroy(seat_child); + } + } + + wl_list_remove(&seat_con->destroy.link); + wl_list_remove(&seat_con->link); + free(seat_con); +} + static void handle_seat_container_destroy(struct wl_listener *listener, void *data) { 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; + struct sway_container *parent = con->parent; + struct sway_container *focus = sway_seat_get_focus(seat); - bool is_focus = (sway_seat_get_focus(seat) == con); + // TODO handle workspace switch in the seat? + bool set_focus = + (focus == con || container_has_child(con, focus)) && + con->type != C_WORKSPACE; - wl_list_remove(&seat_con->link); + seat_container_destroy(seat_con); - if (is_focus) { - // pick next focus - sway_seat_set_focus(seat, NULL); - struct sway_container *next = sway_seat_get_focus_inactive(seat, con->parent); - if (next == NULL) { - next = con->parent; + if (set_focus && con->type != C_WORKSPACE) { + struct sway_container *next_focus = NULL; + while (next_focus == NULL) { + next_focus = sway_seat_get_focus_by_type(seat, parent, C_VIEW); + parent = parent->parent; + + if (next_focus == NULL && parent->type == C_WORKSPACE) { + next_focus = parent; + break; + } } - sway_seat_set_focus(seat, next); + + sway_seat_set_focus(seat, next_focus); } - - wl_list_remove(&seat_con->destroy.link); - - free(seat_con); } static struct sway_seat_container *seat_container_from_container( @@ -293,11 +321,37 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } +static void seat_send_focus(struct sway_seat *seat, + struct sway_container *con) { + if (con->type != C_VIEW) { + return; + } + struct sway_view *view = con->sway_view; + if (view->type == SWAY_XWAYLAND_VIEW) { + struct wlr_xwayland *xwayland = + seat->input->server->xwayland; + wlr_xwayland_set_seat(xwayland, seat->wlr_seat); + } + view_set_activated(view, true); + 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); + } else { + wlr_seat_keyboard_notify_enter( + seat->wlr_seat, view->surface, NULL, 0, NULL); + } + +} + void sway_seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { struct sway_container *last_focus = sway_seat_get_focus(seat); if (container && last_focus == container) { + seat_send_focus(seat, container); return; } @@ -312,23 +366,7 @@ void sway_seat_set_focus_warp(struct sway_seat *seat, wl_list_insert(&seat->focus_stack, &seat_con->link); if (container->type == C_VIEW) { - struct sway_view *view = container->sway_view; - view_set_activated(view, true); - if (view->type == SWAY_XWAYLAND_VIEW) { - struct wlr_xwayland *xwayland = - seat->input->server->xwayland; - wlr_xwayland_set_seat(xwayland, 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); - } else { - wlr_seat_keyboard_notify_enter( - seat->wlr_seat, view->surface, NULL, 0, NULL); - } + seat_send_focus(seat, container); } } @@ -378,7 +416,8 @@ void sway_seat_set_focus(struct sway_seat *seat, sway_seat_set_focus_warp(seat, container, true); } -struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { +struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, + struct sway_container *container) { return sway_seat_get_focus_by_type(seat, container, C_TYPES); } @@ -401,7 +440,8 @@ struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, } while (parent) { - if (parent == container && (type == C_TYPES || current->container->type == type)) { + if (parent == container && (type == C_TYPES || + current->container->type == type)) { return current->container; } parent = parent->parent; diff --git a/sway/tree/container.c b/sway/tree/container.c index f972ac24f..e2fe9e7cf 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -401,3 +401,16 @@ bool container_has_anscestor(struct sway_container *descendant, } return false; } + +bool find_child_func(struct sway_container *con, void *data) { + struct sway_container *child = data; + return con == child; +} + +bool container_has_child(struct sway_container *con, + struct sway_container *child) { + if (child->type == C_VIEW || child->children->length == 0) { + return false; + } + return container_find(con, find_child_func, child); +} From 2aec85bf241f4bad59a23e8492e91d3e7add6ab6 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 17:07:37 -0400 Subject: [PATCH 350/522] clean up view destroy seat cleanup --- sway/input/seat.c | 61 +++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index e3d53cb65..adc4cb0a4 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -58,6 +58,31 @@ static void seat_container_destroy(struct sway_seat_container *seat_con) { free(seat_con); } +static void seat_send_focus(struct sway_seat *seat, + struct sway_container *con) { + if (con->type != C_VIEW) { + return; + } + struct sway_view *view = con->sway_view; + if (view->type == SWAY_XWAYLAND_VIEW) { + struct wlr_xwayland *xwayland = + seat->input->server->xwayland; + wlr_xwayland_set_seat(xwayland, seat->wlr_seat); + } + view_set_activated(view, true); + 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); + } else { + wlr_seat_keyboard_notify_enter( + seat->wlr_seat, view->surface, NULL, 0, NULL); + } + +} + static void handle_seat_container_destroy(struct wl_listener *listener, void *data) { struct sway_seat_container *seat_con = @@ -74,7 +99,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, seat_container_destroy(seat_con); - if (set_focus && con->type != C_WORKSPACE) { + if (set_focus) { struct sway_container *next_focus = NULL; while (next_focus == NULL) { next_focus = sway_seat_get_focus_by_type(seat, parent, C_VIEW); @@ -86,7 +111,13 @@ static void handle_seat_container_destroy(struct wl_listener *listener, } } - sway_seat_set_focus(seat, next_focus); + // the structure change might have caused it to move up to the top of + // the focus stack without sending focus notifications to the view + if (sway_seat_get_focus(seat) == next_focus) { + seat_send_focus(seat, next_focus); + } else { + sway_seat_set_focus(seat, next_focus); + } } } @@ -321,37 +352,11 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -static void seat_send_focus(struct sway_seat *seat, - struct sway_container *con) { - if (con->type != C_VIEW) { - return; - } - struct sway_view *view = con->sway_view; - if (view->type == SWAY_XWAYLAND_VIEW) { - struct wlr_xwayland *xwayland = - seat->input->server->xwayland; - wlr_xwayland_set_seat(xwayland, seat->wlr_seat); - } - view_set_activated(view, true); - 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); - } else { - wlr_seat_keyboard_notify_enter( - seat->wlr_seat, view->surface, NULL, 0, NULL); - } - -} - void sway_seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { struct sway_container *last_focus = sway_seat_get_focus(seat); if (container && last_focus == container) { - seat_send_focus(seat, container); return; } From b2c2ee693b6f1cdaeb204a1469c0fa1b775a498c Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 17:49:40 -0400 Subject: [PATCH 351/522] Introduce common functions to create, map, unmap, destroy views --- include/sway/output.h | 1 + include/sway/tree/container.h | 3 +- include/sway/tree/view.h | 15 +++- sway/desktop/output.c | 73 +++++++++++++------- sway/desktop/wl_shell.c | 38 ++++------- sway/desktop/xdg_shell_v6.c | 46 ++++--------- sway/desktop/xwayland.c | 61 +++++------------ sway/tree/view.c | 125 +++++++++++++++++++++++++++------- 8 files changed, 212 insertions(+), 150 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index b4980cd8d..cfe7502b3 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -24,6 +24,7 @@ struct sway_output { struct wl_listener destroy; struct wl_listener mode; struct wl_listener transform; + struct wl_listener scale; struct wl_listener damage_destroy; struct wl_listener damage_frame; diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 6aa66da02..d707df17e 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -70,9 +70,8 @@ struct sway_container { enum sway_container_layout prev_layout; enum sway_container_layout workspace_layout; - // TODO convert to layout coordinates + // in output-local coordinates double x, y; - // does not include borders or gaps. double width, height; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 3965d2b73..82a5541b3 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -4,6 +4,8 @@ #include #include #include +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" struct sway_container; struct sway_view; @@ -94,9 +96,13 @@ struct sway_view { } iface; // only used for unmanaged views (shell specific) - struct wl_list unmanaged_view_link; // sway_root::unmanaged views + struct wl_list unmanaged_view_link; // sway_root::unmanaged_views }; +struct sway_view *view_create(enum sway_view_type type); + +void view_destroy(struct sway_view *view); + const char *view_get_title(struct sway_view *view); const char *view_get_app_id(struct sway_view *view); @@ -113,7 +119,12 @@ 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); +void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); + +void view_map_unmanaged(struct sway_view *view, + struct wlr_surface *wlr_surface); + +void view_unmap(struct sway_view *view); void view_damage_whole(struct sway_view *view); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0d706c528..6c97ac37c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -39,6 +39,32 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, } } +/** + * Checks whether a surface at (lx, ly) intersects an output. If `box` is not + * NULL, it populates it with the surface box in the output, in output-local + * coordinates. + */ +static bool surface_intersect_output(struct wlr_surface *surface, + struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, + double lx, double ly, float rotation, struct wlr_box *box) { + double ox = lx, oy = ly; + wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); + + if (box != NULL) { + box->x = ox * wlr_output->scale; + box->y = oy * wlr_output->scale; + box->width = surface->current->width * wlr_output->scale; + box->height = surface->current->height * wlr_output->scale; + } + + struct wlr_box layout_box = { + .x = lx, .y = ly, + .width = surface->current->width, .height = surface->current->height, + }; + wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); + return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); +} + static void render_surface(struct wlr_surface *surface, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation) { @@ -48,29 +74,21 @@ static void render_surface(struct wlr_surface *surface, if (!wlr_surface_has_buffer(surface)) { return; } - struct wlr_output_layout *layout = root_container.sway_root->output_layout; - int width = surface->current->width; - int height = surface->current->height; - int render_width = width * wlr_output->scale; - int render_height = height * wlr_output->scale; - int owidth, oheight; - wlr_output_effective_resolution(wlr_output, &owidth, &oheight); - // FIXME: view coords are inconsistently assumed to be in output or layout coords - struct wlr_box layout_box = { - .x = lx + wlr_output->lx, .y = ly + wlr_output->ly, - .width = render_width, .height = render_height, - }; - if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { - struct wlr_box render_box = { - .x = lx, .y = ly, - .width = render_width, .height = render_height - }; + struct wlr_output_layout *layout = root_container.sway_root->output_layout; + + struct wlr_box box; + bool intersects = surface_intersect_output(surface, layout, wlr_output, + lx, ly, rotation, &box); + if (intersects) { float matrix[9]; - wlr_matrix_project_box(matrix, &render_box, surface->current->transform, - 0, wlr_output->transform_matrix); - wlr_render_texture_with_matrix(renderer, surface->texture, matrix, - 1.0f); // TODO: configurable alpha + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current->transform); + wlr_matrix_project_box(matrix, &box, transform, rotation, + wlr_output->transform_matrix); + + // TODO: configurable alpha + wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f); wlr_surface_send_frame_done(surface, when); } @@ -80,9 +98,8 @@ static void render_surface(struct wlr_surface *surface, struct wlr_surface_state *state = subsurface->surface->current; double sx = state->subsurface_position.x; double sy = state->subsurface_position.y; - double sw = state->buffer_width / state->scale; - double sh = state->buffer_height / state->scale; - rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); + rotate_child_position(&sx, &sy, state->width, state->height, + surface->current->width, surface->current->height, rotation); render_surface(subsurface->surface, wlr_output, when, lx + sx, ly + sy, rotation); @@ -338,6 +355,12 @@ static void handle_transform(struct wl_listener *listener, void *data) { arrange_windows(output->swayc, -1, -1); } +static void handle_scale(struct wl_listener *listener, void *data) { + struct sway_output *output = wl_container_of(listener, output, scale); + arrange_layers(output); + arrange_windows(output->swayc, -1, -1); +} + void handle_new_output(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; @@ -378,6 +401,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->mode.notify = handle_mode; wl_signal_add(&wlr_output->events.transform, &output->transform); output->transform.notify = handle_transform; + wl_signal_add(&wlr_output->events.scale, &output->scale); + output->scale.notify = handle_scale; wl_signal_add(&output->damage->events.frame, &output->damage_frame); output->damage_frame.notify = damage_handle_frame; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 4fcc63178..ab969b17c 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -75,15 +75,13 @@ 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); - free(sway_surface->view); + view_destroy(sway_surface->view); free(sway_surface); - arrange_windows(parent, -1, -1); } void handle_wl_shell_surface(struct wl_listener *listener, void *data) { - struct sway_server *server = wl_container_of( - listener, server, wl_shell_surface); + struct sway_server *server = wl_container_of(listener, server, + wl_shell_surface); struct wlr_wl_shell_surface *shell_surface = data; if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { @@ -103,20 +101,18 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); - if (!sway_assert(sway_view, "Failed to allocate view!")) { + struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW); + if (!sway_assert(view, "Failed to allocate view")) { return; } - sway_view->type = SWAY_WL_SHELL_VIEW; - sway_view->iface.get_prop = get_prop; - 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; - sway_surface->view = sway_view; + view->iface.get_prop = get_prop; + view->iface.set_size = set_size; + view->iface.set_position = set_position; + view->iface.set_activated = set_activated; + view->iface.close = close; + view->wlr_wl_shell_surface = shell_surface; + view->sway_wl_shell_surface = sway_surface; + sway_surface->view = view; // TODO: // - Wire up listeners @@ -132,11 +128,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { sway_surface->destroy.notify = handle_destroy; 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); - sway_view->swayc = cont; - - arrange_windows(cont->parent, -1, -1); - sway_input_manager_set_focus(input_manager, cont); + view_map(view, shell_surface->surface); } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 713437f2e..77a35b13f 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -82,29 +82,14 @@ static void handle_commit(struct wl_listener *listener, void *data) { static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_xdg_surface_v6 *sway_surface = wl_container_of(listener, sway_surface, unmap); - view_damage_whole(sway_surface->view); - container_view_destroy(sway_surface->view->swayc); - sway_surface->view->swayc = NULL; - sway_surface->view->surface = NULL; + view_unmap(sway_surface->view); } static void handle_map(struct wl_listener *listener, void *data) { struct sway_xdg_surface_v6 *sway_surface = wl_container_of(listener, sway_surface, map); struct sway_view *view = sway_surface->view; - - sway_surface->view->surface = view->wlr_xdg_surface_v6->surface; - - container_view_destroy(view->swayc); - - 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, view); - view->swayc = cont; - arrange_windows(cont->parent, -1, -1); - sway_input_manager_set_focus(input_manager, cont); - - view_damage_whole(sway_surface->view); + view_map(view, view->wlr_xdg_surface_v6->surface); } static void handle_destroy(struct wl_listener *listener, void *data) { @@ -112,8 +97,9 @@ 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); - container_view_destroy(sway_xdg_surface->view->swayc); - free(sway_xdg_surface->view); + wl_list_remove(&sway_xdg_surface->map.link); + wl_list_remove(&sway_xdg_surface->unmap.link); + view_destroy(sway_xdg_surface->view); free(sway_xdg_surface); } @@ -138,23 +124,21 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); - if (!sway_assert(sway_view, "Failed to allocate view!")) { + struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW); + if (!sway_assert(view, "Failed to allocate view")) { return; } - sway_view->type = SWAY_XDG_SHELL_V6_VIEW; - sway_view->iface.get_prop = get_prop; - 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_surface->view = sway_view; + view->iface.get_prop = get_prop; + view->iface.set_size = set_size; + view->iface.set_position = set_position; + view->iface.set_activated = set_activated; + view->iface.close = close; + view->wlr_xdg_surface_v6 = xdg_surface; + view->sway_xdg_surface_v6 = sway_surface; + sway_surface->view = view; // TODO: // - Look up pid and open on appropriate workspace - // - Set new view to maximized so it behaves nicely // - Criteria sway_surface->commit.notify = handle_commit; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 273ca2bf8..e1c2ad084 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -102,56 +102,35 @@ static void handle_commit(struct wl_listener *listener, void *data) { static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, destroy); - wl_list_remove(&sway_surface->commit.link); wl_list_remove(&sway_surface->destroy.link); wl_list_remove(&sway_surface->request_configure.link); - wl_list_remove(&sway_surface->view->unmanaged_view_link); - container_view_destroy(sway_surface->view->swayc); - sway_surface->view->swayc = NULL; - sway_surface->view->surface = NULL; + wl_list_remove(&sway_surface->map.link); + wl_list_remove(&sway_surface->unmap.link); + view_destroy(sway_surface->view); + free(sway_surface); } static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, unmap); - view_damage_whole(sway_surface->view); - wl_list_remove(&sway_surface->view->unmanaged_view_link); - wl_list_init(&sway_surface->view->unmanaged_view_link); - container_view_destroy(sway_surface->view->swayc); - sway_surface->view->swayc = NULL; - sway_surface->view->surface = NULL; + view_unmap(sway_surface->view); } static void handle_map(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, map); struct wlr_xwayland_surface *xsurface = data; - - sway_surface->view->surface = xsurface->surface; + struct sway_view *view = sway_surface->view; // put it back into the tree if (wlr_xwayland_surface_is_unmanaged(xsurface) || xsurface->override_redirect) { - wl_list_remove(&sway_surface->view->unmanaged_view_link); - wl_list_insert(&root_container.sway_root->unmanaged_views, - &sway_surface->view->unmanaged_view_link); + view_map_unmanaged(view, xsurface->surface); } else { - struct sway_view *view = sway_surface->view; - container_view_destroy(view->swayc); - wlr_xwayland_surface_set_maximized(xsurface, true); - - 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, view); - view->swayc = cont; - arrange_windows(cont->parent, -1, -1); - sway_input_manager_set_focus(input_manager, cont); + view_map(view, xsurface->surface); } - - view_damage_whole(sway_surface->view); } static void handle_request_configure(struct wl_listener *listener, void *data) { @@ -180,25 +159,21 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); - if (!sway_assert(sway_view, "Failed to allocate view!")) { + struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW); + if (!sway_assert(view, "Failed to allocate view")) { return; } - sway_view->type = SWAY_XWAYLAND_VIEW; - sway_view->iface.get_prop = get_prop; - 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_view; - sway_view->wlr_xwayland_surface = xsurface; - sway_view->sway_xwayland_surface = sway_surface; - sway_surface->view = sway_view; - - wl_list_init(&sway_view->unmanaged_view_link); + view->iface.get_prop = get_prop; + view->iface.set_size = set_size; + view->iface.set_position = set_position; + view->iface.set_activated = set_activated; + view->iface.close = close_view; + view->wlr_xwayland_surface = xsurface; + view->sway_xwayland_surface = sway_surface; + sway_surface->view = view; // TODO: // - Look up pid and open on appropriate workspace - // - Set new view to maximized so it behaves nicely // - Criteria wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); diff --git a/sway/tree/view.c b/sway/tree/view.c index b7d1a41bd..2950812a5 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,3 +1,4 @@ +#include #include #include #include "log.h" @@ -6,6 +7,31 @@ #include "sway/tree/layout.h" #include "sway/tree/view.h" +struct sway_view *view_create(enum sway_view_type type) { + struct sway_view *view = calloc(1, sizeof(struct sway_view)); + if (view == NULL) { + return NULL; + } + view->type = type; + wl_list_init(&view->unmanaged_view_link); + return view; +} + +void view_destroy(struct sway_view *view) { + if (view == NULL) { + return; + } + + if (view->surface != NULL) { + view_unmap(view); + } + if (view->swayc != NULL) { + container_view_destroy(view->swayc); + } + + free(view); +} + const char *view_get_title(struct sway_view *view) { if (view->iface.get_prop) { return view->iface.get_prop(view, VIEW_PROP_TITLE); @@ -34,6 +60,31 @@ const char *view_get_instance(struct sway_view *view) { return NULL; } +static void view_update_outputs(struct sway_view *view, + const struct wlr_box *before) { + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; + struct wlr_box box = { + .x = view->swayc->x, + .y = view->swayc->y, + .width = view->width, + .height = view->height, + }; + struct wlr_output_layout_output *layout_output; + wl_list_for_each(layout_output, &output_layout->outputs, link) { + bool intersected = before != NULL && wlr_output_layout_intersects( + output_layout, layout_output->output, before); + bool intersects = wlr_output_layout_intersects(output_layout, + layout_output->output, &box); + if (intersected && !intersects) { + wlr_surface_send_leave(view->surface, layout_output->output); + } + if (!intersected && intersects) { + wlr_surface_send_enter(view->surface, layout_output->output); + } + } +} + void view_set_size(struct sway_view *view, int width, int height) { if (view->iface.set_size) { struct wlr_box box = { @@ -73,30 +124,6 @@ void view_close(struct sway_view *view) { } } -void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { - struct wlr_output_layout *output_layout = - root_container.sway_root->output_layout; - struct wlr_box box = { - .x = view->swayc->x, - .y = view->swayc->y, - .width = view->width, - .height = view->height, - }; - struct wlr_output_layout_output *layout_output; - wl_list_for_each(layout_output, &output_layout->outputs, link) { - bool intersected = before != NULL && wlr_output_layout_intersects( - output_layout, layout_output->output, before); - bool intersects = wlr_output_layout_intersects(output_layout, - layout_output->output, &box); - if (intersected && !intersects) { - wlr_surface_send_leave(view->surface, layout_output->output); - } - if (!intersected && intersects) { - wlr_surface_send_enter(view->surface, layout_output->output); - } - } -} - struct sway_container *container_view_destroy(struct sway_container *view) { if (!view) { return NULL; @@ -107,6 +134,56 @@ struct sway_container *container_view_destroy(struct sway_container *view) { return parent; } +void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { + if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { + return; + } + + 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, view); + + view->surface = wlr_surface; + view->swayc = cont; + + arrange_windows(cont->parent, -1, -1); + sway_input_manager_set_focus(input_manager, cont); + + view_damage_whole(view); +} + +void view_map_unmanaged(struct sway_view *view, + struct wlr_surface *wlr_surface) { + if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { + return; + } + + view->surface = wlr_surface; + view->swayc = NULL; + + wl_list_insert(&root_container.sway_root->unmanaged_views, + &view->unmanaged_view_link); + + view_damage_whole(view); +} + +void view_unmap(struct sway_view *view) { + if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) { + return; + } + + view_damage_whole(view); + + wl_list_remove(&view->unmanaged_view_link); + wl_list_init(&view->unmanaged_view_link); + + container_view_destroy(view->swayc); + + view->swayc = NULL; + view->surface = NULL; +} + void view_damage_whole(struct sway_view *view) { struct sway_container *cont = NULL; for (int i = 0; i < root_container.children->length; ++i) { From 1d68f9ecca8870f2f2a6823072c77657436b123a Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 18:07:44 -0400 Subject: [PATCH 352/522] Add sway_view_impl --- include/sway/tree/view.h | 31 +++++++++++++++++-------------- sway/desktop/wl_shell.c | 18 ++++++++---------- sway/desktop/xdg_shell_v6.c | 15 +++++++++------ sway/desktop/xwayland.c | 17 ++++++++++------- sway/tree/view.c | 36 +++++++++++++++++++----------------- 5 files changed, 63 insertions(+), 54 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 82a5541b3..c68739d64 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -66,10 +66,23 @@ enum sway_view_prop { VIEW_PROP_INSTANCE, }; +struct sway_view_impl { + 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); +}; + struct sway_view { enum sway_view_type type; - struct sway_container *swayc; - struct wlr_surface *surface; + const struct sway_view_impl *impl; + + struct sway_container *swayc; // NULL for unmanaged views + struct wlr_surface *surface; // NULL for unmapped views int width, height; union { @@ -84,22 +97,12 @@ struct sway_view { 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 }; -struct sway_view *view_create(enum sway_view_type type); +struct sway_view *view_create(enum sway_view_type type, + const struct sway_view_impl *impl); void view_destroy(struct sway_view *view); diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index ab969b17c..e0909a03a 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -47,10 +47,6 @@ static void set_position(struct sway_view *view, double ox, double oy) { view->swayc->y = oy; } -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; @@ -59,6 +55,13 @@ static void close(struct sway_view *view) { wl_client_destroy(view->wlr_wl_shell_surface->client); } +static const struct sway_view_impl view_impl = { + .get_prop = get_prop, + .set_size = set_size, + .set_position = set_position, + .close = close, +}; + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_wl_shell_surface *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -101,15 +104,10 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW); + struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW, &view_impl); if (!sway_assert(view, "Failed to allocate view")) { return; } - view->iface.get_prop = get_prop; - view->iface.set_size = set_size; - view->iface.set_position = set_position; - view->iface.set_activated = set_activated; - view->iface.close = close; view->wlr_wl_shell_surface = shell_surface; view->sway_wl_shell_surface = sway_surface; sway_surface->view = view; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 77a35b13f..c1adc7feb 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -67,6 +67,14 @@ static void close(struct sway_view *view) { } } +static const struct sway_view_impl view_impl = { + .get_prop = get_prop, + .set_size = set_size, + .set_position = set_position, + .set_activated = set_activated, + .close = close, +}; + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xdg_surface_v6 *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -124,15 +132,10 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW); + struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW, &view_impl); if (!sway_assert(view, "Failed to allocate view")) { return; } - view->iface.get_prop = get_prop; - view->iface.set_size = set_size; - view->iface.set_position = set_position; - view->iface.set_activated = set_activated; - view->iface.close = close; view->wlr_xdg_surface_v6 = xdg_surface; view->sway_xdg_surface_v6 = sway_surface; sway_surface->view = view; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index e1c2ad084..93c782286 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -81,13 +81,21 @@ static void set_activated(struct sway_view *view, bool activated) { wlr_xwayland_surface_activate(surface, activated); } -static void close_view(struct sway_view *view) { +static void _close(struct sway_view *view) { if (!assert_xwayland(view)) { return; } wlr_xwayland_surface_close(view->wlr_xwayland_surface); } +static const struct sway_view_impl view_impl = { + .get_prop = get_prop, + .set_size = set_size, + .set_position = set_position, + .set_activated = set_activated, + .close = _close, +}; + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_surface *sway_surface = wl_container_of(listener, sway_surface, commit); @@ -159,15 +167,10 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW); + struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW, &view_impl); if (!sway_assert(view, "Failed to allocate view")) { return; } - view->iface.get_prop = get_prop; - view->iface.set_size = set_size; - view->iface.set_position = set_position; - view->iface.set_activated = set_activated; - view->iface.close = close_view; view->wlr_xwayland_surface = xsurface; view->sway_xwayland_surface = sway_surface; sway_surface->view = view; diff --git a/sway/tree/view.c b/sway/tree/view.c index 2950812a5..d7a52e19e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -7,12 +7,14 @@ #include "sway/tree/layout.h" #include "sway/tree/view.h" -struct sway_view *view_create(enum sway_view_type type) { +struct sway_view *view_create(enum sway_view_type type, + const struct sway_view_impl *impl) { struct sway_view *view = calloc(1, sizeof(struct sway_view)); if (view == NULL) { return NULL; } view->type = type; + view->impl = impl; wl_list_init(&view->unmanaged_view_link); return view; } @@ -33,29 +35,29 @@ void view_destroy(struct sway_view *view) { } const char *view_get_title(struct sway_view *view) { - if (view->iface.get_prop) { - return view->iface.get_prop(view, VIEW_PROP_TITLE); + if (view->impl->get_prop) { + return view->impl->get_prop(view, VIEW_PROP_TITLE); } return NULL; } const char *view_get_app_id(struct sway_view *view) { - if (view->iface.get_prop) { - return view->iface.get_prop(view, VIEW_PROP_APP_ID); + if (view->impl->get_prop) { + return view->impl->get_prop(view, VIEW_PROP_APP_ID); } return NULL; } const char *view_get_class(struct sway_view *view) { - if (view->iface.get_prop) { - return view->iface.get_prop(view, VIEW_PROP_CLASS); + if (view->impl->get_prop) { + return view->impl->get_prop(view, VIEW_PROP_CLASS); } return NULL; } const char *view_get_instance(struct sway_view *view) { - if (view->iface.get_prop) { - return view->iface.get_prop(view, VIEW_PROP_INSTANCE); + if (view->impl->get_prop) { + return view->impl->get_prop(view, VIEW_PROP_INSTANCE); } return NULL; } @@ -86,41 +88,41 @@ static void view_update_outputs(struct sway_view *view, } void view_set_size(struct sway_view *view, int width, int height) { - if (view->iface.set_size) { + if (view->impl->set_size) { struct wlr_box box = { .x = view->swayc->x, .y = view->swayc->y, .width = view->width, .height = view->height, }; - view->iface.set_size(view, width, height); + view->impl->set_size(view, width, height); view_update_outputs(view, &box); } } // TODO make view coordinates in layout coordinates void view_set_position(struct sway_view *view, double ox, double oy) { - if (view->iface.set_position) { + if (view->impl->set_position) { struct wlr_box box = { .x = view->swayc->x, .y = view->swayc->y, .width = view->width, .height = view->height, }; - view->iface.set_position(view, ox, oy); + view->impl->set_position(view, ox, oy); view_update_outputs(view, &box); } } void view_set_activated(struct sway_view *view, bool activated) { - if (view->iface.set_activated) { - view->iface.set_activated(view, activated); + if (view->impl->set_activated) { + view->impl->set_activated(view, activated); } } void view_close(struct sway_view *view) { - if (view->iface.close) { - view->iface.close(view); + if (view->impl->close) { + view->impl->close(view); } } From eda425fdabb4050eb2ecc8741793d83e3a7bf154 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 18:52:02 -0400 Subject: [PATCH 353/522] fix some segfaults --- sway/input/seat.c | 7 +++++-- sway/tree/container.c | 19 ++++++++++++------- sway/tree/layout.c | 4 ++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index adc4cb0a4..a1b1caa84 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -94,6 +94,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, // TODO handle workspace switch in the seat? bool set_focus = + focus != NULL && (focus == con || container_has_child(con, focus)) && con->type != C_WORKSPACE; @@ -103,12 +104,13 @@ static void handle_seat_container_destroy(struct wl_listener *listener, struct sway_container *next_focus = NULL; while (next_focus == NULL) { next_focus = sway_seat_get_focus_by_type(seat, parent, C_VIEW); - parent = parent->parent; if (next_focus == NULL && parent->type == C_WORKSPACE) { next_focus = parent; break; } + + parent = parent->parent; } // the structure change might have caused it to move up to the top of @@ -440,7 +442,8 @@ struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, wl_list_for_each(current, &seat->focus_stack, link) { parent = current->container->parent; - if (current->container == container) { + if (current->container == container && + (type == C_TYPES || container->type == type)) { return current->container; } diff --git a/sway/tree/container.c b/sway/tree/container.c index e2fe9e7cf..b3c6d80f1 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -69,11 +69,11 @@ static struct sway_container *_container_destroy(struct sway_container *cont) { if (cont->children != NULL) { // remove children until there are no more, container_destroy calls // container_remove_child, which removes child from this container - while (cont->children->length != 0) { - container_destroy(cont->children->items[0]); + while (cont->children != NULL && cont->children->length != 0) { + struct sway_container *child = cont->children->items[0]; + container_remove_child(child); + container_destroy(child); } - list_free(cont->children); - cont->children = NULL; } if (cont->marks) { list_foreach(cont->marks, free); @@ -85,13 +85,17 @@ static struct sway_container *_container_destroy(struct sway_container *cont) { if (cont->name) { free(cont->name); } + list_free(cont->children); + cont->children = NULL; free(cont); return parent; } struct sway_container *container_destroy(struct sway_container *cont) { - cont = _container_destroy(cont); - return container_reap_empty(cont->parent); + struct sway_container *parent = _container_destroy(cont); + parent = container_reap_empty(parent); + arrange_windows(&root_container, -1, -1); + return parent; } struct sway_container *container_output_create( @@ -409,7 +413,8 @@ bool find_child_func(struct sway_container *con, void *data) { bool container_has_child(struct sway_container *con, struct sway_container *child) { - if (child->type == C_VIEW || child->children->length == 0) { + if (child == NULL || child->type == C_VIEW || + child->children->length == 0) { return false; } return container_find(con, find_child_func, child); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 62df19e9f..5098c8d1d 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -106,11 +106,11 @@ void container_add_child(struct sway_container *parent, } struct sway_container *container_reap_empty(struct sway_container *container) { - if (!sway_assert(container, "reaping null container")) { + if (container == NULL) { return NULL; } wlr_log(L_DEBUG, "reaping %p %s", container, container->name); - while (container != &root_container && container->children->length == 0) { + while (container->type != C_VIEW && container != &root_container && container->children->length == 0) { if (container->type == C_WORKSPACE) { if (!workspace_is_visible(container)) { struct sway_container *parent = container->parent; From 27e394f8b07fed21f791f2a06b93c3bfc0f991b7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 19:45:30 -0400 Subject: [PATCH 354/522] fix children list segfault --- sway/tree/container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index b3c6d80f1..f4c82abee 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -71,8 +71,8 @@ static struct sway_container *_container_destroy(struct sway_container *cont) { // container_remove_child, which removes child from this container while (cont->children != NULL && cont->children->length != 0) { struct sway_container *child = cont->children->items[0]; - container_remove_child(child); container_destroy(child); + list_del(cont->children, 0); } } if (cont->marks) { From 81556f4b2aad49c21058d9cc9695195a12f0239b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 20:52:34 -0400 Subject: [PATCH 355/522] add docstrings and todos --- include/sway/tree/container.h | 63 +++++++++++++++++++++++++---------- include/sway/tree/layout.h | 9 +++++ 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 285f10111..f0e87fb51 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -87,37 +87,55 @@ struct sway_container { } events; }; +// TODO make private and use the container-specific create functions struct sway_container *container_create(enum sway_container_type type); -// TODO only one container create function and pass the type? -struct sway_container *container_output_create( - struct sway_output *sway_output); +/** + * Create a new container container. A container container can be a a child of + * a workspace container or another container container. + */ +struct sway_container *container_container_create(); -struct sway_container *container_workspace_create( - struct sway_container *output, const char *name); +/** + * Create a new output. Outputs are children of the root container and have no + * order in the tree structure. + */ +struct sway_container *container_output_create(struct sway_output *sway_output); +/** + * Create a new workspace container. Workspaces are children of an output + * container and are ordered alphabetically by name. + */ +struct sway_container *container_workspace_create(struct sway_container *output, const char *name); + +/* + * Create a new view container. A view can be a child of a workspace container + * or a container container and are rendered in the order and structure of + * how they are attached to the tree. + */ +// TODO view containers should be created in a detached state. 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); +// TODO don't return the parent on destroy +struct sway_container *container_destroy(struct sway_container *container); -struct sway_container *container_workspace_destroy( - struct sway_container *workspace); - -struct sway_container *container_view_destroy(struct sway_container *view); - -struct sway_container *container_destroy(struct sway_container *cont); +struct sway_container *container_workspace_destroy(struct sway_container *container); +struct sway_container *container_output_destroy(struct sway_container *container); +struct sway_container *container_view_destroy(struct sway_container *container); +// TODO move to layout.c struct sway_container *container_set_layout(struct sway_container *container, enum sway_container_layout layout); +// TODO rename to container_descendants_for_each() void container_descendants(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. + * Search a container's descendants 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); @@ -125,18 +143,21 @@ struct sway_container *container_find(struct sway_container *container, /** * Finds a parent container with the given struct sway_containerype. */ +// TODO rename to container_parent_of_type() struct sway_container *container_parent(struct sway_container *container, enum sway_container_type type); /** - * Find a container at the given coordinates. + * Find a container at the given coordinates. Returns the the surface and + * surface-local coordinates of the given layout coordinates if the container + * is a view and the view contains a surface at those coordinates. */ -struct sway_container *container_at(struct sway_container *parent, +struct sway_container *container_at(struct sway_container *container, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); /** - * Apply the function for each child of the container breadth first. + * Apply the function for each descendant of the container breadth first. */ void container_for_each_descendant_bfs(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data); @@ -147,9 +168,15 @@ void container_for_each_descendant_bfs(struct sway_container *container, void container_for_each_descendant_dfs(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data); -bool container_has_anscestor(struct sway_container *descendant, +/** + * Returns true if the given container is an ancestor of this container. + */ +bool container_has_anscestor(struct sway_container *container, struct sway_container *anscestor); +/** + * Returns true if the given container is a child descendant of this container. + */ bool container_has_child(struct sway_container *con, struct sway_container *child); diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 79c14edaf..53f72ec46 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -32,28 +32,37 @@ struct sway_root { void layout_init(void); +// TODO move to tree.h void container_add_child(struct sway_container *parent, struct sway_container *child); +// TODO move to tree.h struct sway_container *container_add_sibling(struct sway_container *parent, struct sway_container *child); +// TODO move to tree.h struct sway_container *container_remove_child(struct sway_container *child); +// TODO PRIVATE in tree.h struct sway_container *container_reap_empty(struct sway_container *container); +// TODO move to tree.h void container_move_to(struct sway_container* container, struct sway_container* destination); +// TODO move to output.c enum sway_container_layout container_get_default_layout(struct sway_container *output); +// TODO move to output.c void container_sort_workspaces(struct sway_container *output); void arrange_windows(struct sway_container *container, double width, double height); +// TODO move to container.h struct sway_container *container_get_in_direction(struct sway_container *container, struct sway_seat *seat, enum movement_direction dir); +// TODO move to tree.h struct sway_container *container_split(struct sway_container *child, enum sway_container_layout layout); From b5d49cc4e86b5da5a3479c2d2a763be50184f75d Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 31 Mar 2018 21:05:58 -0400 Subject: [PATCH 356/522] remove default from kill switch --- sway/commands/kill.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/commands/kill.c b/sway/commands/kill.c index e6036cb3b..46d6e98e6 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -14,6 +14,7 @@ struct cmd_results *cmd_kill(int argc, char **argv) { case C_ROOT: case C_OUTPUT: case C_WORKSPACE: + case C_TYPES: return cmd_results_new(CMD_INVALID, NULL, "Can only kill views and containers with this command"); break; @@ -24,8 +25,6 @@ struct cmd_results *cmd_kill(int argc, char **argv) { case C_VIEW: view_close(con->sway_view); break; - default: - break; } return cmd_results_new(CMD_SUCCESS, NULL, NULL); From e677c5b204971af00d71f9a50a89206d01b46a36 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 08:45:37 -0400 Subject: [PATCH 357/522] rename seat functions --- include/sway/input/seat.h | 24 +++++++-------- sway/commands.c | 2 +- sway/commands/focus.c | 4 +-- sway/commands/workspace.c | 2 +- sway/config.c | 2 +- sway/desktop/output.c | 2 +- sway/desktop/wl_shell.c | 2 +- sway/desktop/xdg_shell_v6.c | 2 +- sway/desktop/xwayland.c | 2 +- sway/input/cursor.c | 10 +++---- sway/input/input-manager.c | 28 +++++++++--------- sway/input/seat.c | 58 ++++++++++++++++++------------------- sway/ipc-json.c | 4 +-- sway/ipc-server.c | 4 +-- sway/tree/container.c | 2 +- sway/tree/layout.c | 8 ++--- sway/tree/workspace.c | 14 ++++----- 17 files changed, 85 insertions(+), 85 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 31210a5a1..38a6379c9 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -38,28 +38,28 @@ struct sway_seat { struct wl_list link; // input_manager::seats }; -struct sway_seat *sway_seat_create(struct sway_input_manager *input, +struct sway_seat *seat_create(struct sway_input_manager *input, const char *seat_name); -void sway_seat_destroy(struct sway_seat *seat); +void seat_destroy(struct sway_seat *seat); -void sway_seat_add_device(struct sway_seat *seat, +void seat_add_device(struct sway_seat *seat, struct sway_input_device *device); -void sway_seat_configure_device(struct sway_seat *seat, +void seat_configure_device(struct sway_seat *seat, struct sway_input_device *device); -void sway_seat_remove_device(struct sway_seat *seat, +void seat_remove_device(struct sway_seat *seat, struct sway_input_device *device); -void sway_seat_configure_xcursor(struct sway_seat *seat); +void seat_configure_xcursor(struct sway_seat *seat); -void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); +void seat_set_focus(struct sway_seat *seat, struct sway_container *container); -void sway_seat_set_focus_warp(struct sway_seat *seat, +void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp); -struct sway_container *sway_seat_get_focus(struct sway_seat *seat); +struct sway_container *seat_get_focus(struct sway_seat *seat); /** * Return the last container to be focused for the seat (or the most recently @@ -70,12 +70,12 @@ 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 *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, +struct sway_container *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); +void seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); #endif diff --git a/sway/commands.c b/sway/commands.c index 905442208..91b44fbfb 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -340,7 +340,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { // without criteria, the command acts upon the focused // container config->handler_context.current_container = - sway_seat_get_focus_inactive(seat, &root_container); + seat_get_focus_inactive(seat, &root_container); if (!sway_assert(config->handler_context.current_container, "could not get focus-inactive for root container")) { return NULL; diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 64f079f4e..4fb732ddf 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -40,7 +40,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) { } if (argc == 0) { - sway_seat_set_focus(seat, con); + seat_set_focus(seat, con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -53,7 +53,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) { struct sway_container *next_focus = container_get_in_direction(con, seat, direction); if (next_focus) { - sway_seat_set_focus(seat, next_focus); + seat_set_focus(seat, next_focus); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 8f39e5fc8..aa4096f71 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -91,7 +91,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { } workspace_switch(ws); current_container = - sway_seat_get_focus(config->handler_context.seat); + seat_get_focus(config->handler_context.seat); struct sway_container *new_output = container_parent(current_container, C_OUTPUT); if (config->mouse_warping && old_output != new_output) { diff --git a/sway/config.c b/sway/config.c index 0eecf7f6c..90b833ab7 100644 --- a/sway/config.c +++ b/sway/config.c @@ -125,7 +125,7 @@ static void destroy_removed_seats(struct sway_config *old_config, seat_name_cmp, seat_config->name) < 0) { seat = input_manager_get_seat(input_manager, seat_config->name); - sway_seat_destroy(seat); + seat_destroy(seat); } } } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0d706c528..86b023cbd 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -228,7 +228,7 @@ static void render_output(struct sway_output *output, struct timespec *when, struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *focus = - sway_seat_get_focus_inactive(seat, output->swayc); + seat_get_focus_inactive(seat, output->swayc); struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : container_parent(focus, C_WORKSPACE)); diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 4fcc63178..3e275f2b4 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -133,7 +133,7 @@ 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 *focus = seat_get_focus_inactive(seat, &root_container); struct sway_container *cont = container_view_create(focus, sway_view); sway_view->swayc = cont; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 713437f2e..286d52cc1 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -98,7 +98,7 @@ static void handle_map(struct wl_listener *listener, void *data) { container_view_destroy(view->swayc); 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 *focus = seat_get_focus_inactive(seat, &root_container); struct sway_container *cont = container_view_create(focus, view); view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 273ca2bf8..8fb6cb52a 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -143,7 +143,7 @@ static void handle_map(struct wl_listener *listener, void *data) { wlr_xwayland_surface_set_maximized(xsurface, true); struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = sway_seat_get_focus_inactive(seat, + struct sway_container *focus = seat_get_focus_inactive(seat, &root_container); struct sway_container *cont = container_view_create(focus, view); view->swayc = cont; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d608a9cf0..7d05e9420 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -84,7 +84,7 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, // find the focused workspace on the output for this seat struct sway_container *ws = - sway_seat_get_focus_inactive(cursor->seat, output->swayc); + seat_get_focus_inactive(cursor->seat, output->swayc); if (ws && ws->type != C_WORKSPACE) { ws = container_parent(ws, C_WORKSPACE); } @@ -129,7 +129,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, double sx, sy; struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); if (c && config->focus_follows_mouse) { - sway_seat_set_focus_warp(cursor->seat, c, false); + seat_set_focus_warp(cursor->seat, c, false); } // reset cursor if switching between clients @@ -191,15 +191,15 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { 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); + struct sway_container *old_ws = 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); + seat_set_focus(cursor->seat, cont); } } else { - sway_seat_set_focus(cursor->seat, cont); + seat_set_focus(cursor->seat, cont); } wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index d421a03f1..66ade685d 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -40,7 +40,7 @@ struct sway_seat *input_manager_get_seat( } } - return sway_seat_create(input, seat_name); + return seat_create(input, seat_name); } static char *get_device_identifier(struct wlr_input_device *device) { @@ -175,7 +175,7 @@ static void handle_device_destroy(struct wl_listener *listener, void *data) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input_manager->seats, link) { - sway_seat_remove_device(seat, input_device); + seat_remove_device(seat, input_device); } wl_list_remove(&input_device->link); @@ -221,7 +221,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { if (!input_has_seat_configuration(input)) { wlr_log(L_DEBUG, "no seat configuration, using default seat"); seat = input_manager_get_seat(input, default_seat); - sway_seat_add_device(seat, input_device); + seat_add_device(seat, input_device); return; } @@ -232,7 +232,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { seat_config_get_attachment(seat->config, "*")); if (has_attachment) { - sway_seat_add_device(seat, input_device); + seat_add_device(seat, input_device); added = true; } } @@ -240,7 +240,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { if (!added) { wl_list_for_each(seat, &input->seats, link) { if (seat->config && seat->config->fallback == 1) { - sway_seat_add_device(seat, input_device); + seat_add_device(seat, input_device); added = true; } } @@ -281,7 +281,7 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, struct sway_container *container) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { - if (sway_seat_get_focus(seat) == container) { + if (seat_get_focus(seat) == container) { return true; } } @@ -293,7 +293,7 @@ void sway_input_manager_set_focus(struct sway_input_manager *input, struct sway_container *container) { struct sway_seat *seat ; wl_list_for_each(seat, &input->seats, link) { - sway_seat_set_focus(seat, container); + seat_set_focus(seat, container); } } @@ -311,7 +311,7 @@ void sway_input_manager_apply_input_config(struct sway_input_manager *input, struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { - sway_seat_configure_device(seat, input_device); + seat_configure_device(seat, input_device); } } } @@ -326,7 +326,7 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, return; } - sway_seat_set_config(seat, seat_config); + seat_set_config(seat, seat_config); // for every device, try to add it to a seat and if no seat has it // attached, add it to the fallback seats. @@ -355,17 +355,17 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, } } if (attached) { - sway_seat_add_device(seat, input_device); + seat_add_device(seat, input_device); } else { - sway_seat_remove_device(seat, input_device); + 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); + seat_add_device(seat, input_device); } else { - sway_seat_remove_device(seat, input_device); + seat_remove_device(seat, input_device); } } } @@ -376,7 +376,7 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, 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); + seat_configure_xcursor(seat); } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 9aa34acac..703951445 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -25,7 +25,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { free(seat_device); } -void sway_seat_destroy(struct sway_seat *seat) { +void seat_destroy(struct sway_seat *seat) { struct sway_seat_device *seat_device, *next; wl_list_for_each_safe(seat_device, next, &seat->devices, link) { seat_device_destroy(seat_device); @@ -42,18 +42,18 @@ static void handle_seat_container_destroy(struct wl_listener *listener, struct sway_seat *seat = seat_con->seat; struct sway_container *con = seat_con->container; - bool is_focus = (sway_seat_get_focus(seat) == con); + bool is_focus = (seat_get_focus(seat) == con); wl_list_remove(&seat_con->link); if (is_focus) { // pick next focus - sway_seat_set_focus(seat, NULL); - struct sway_container *next = sway_seat_get_focus_inactive(seat, con->parent); + seat_set_focus(seat, NULL); + struct sway_container *next = seat_get_focus_inactive(seat, con->parent); if (next == NULL) { next = con->parent; } - sway_seat_set_focus(seat, next); + seat_set_focus(seat, next); } wl_list_remove(&seat_con->destroy.link); @@ -110,7 +110,7 @@ static void collect_focus_iter(struct sway_container *con, void *data) { wl_list_insert(&seat->focus_stack, &seat_con->link); } -struct sway_seat *sway_seat_create(struct sway_input_manager *input, +struct sway_seat *seat_create(struct sway_input_manager *input, const char *seat_name) { struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); if (!seat) { @@ -147,7 +147,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH); - sway_seat_configure_xcursor(seat); + seat_configure_xcursor(seat); wl_list_insert(&input->seats, &seat->link); @@ -169,7 +169,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); + struct sway_container *focus = 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); @@ -179,7 +179,7 @@ static void seat_configure_keyboard(struct sway_seat *seat, } } -static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, +static struct sway_seat_device *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) { @@ -191,10 +191,10 @@ static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, return NULL; } -void sway_seat_configure_device(struct sway_seat *seat, +void 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); + seat_get_device(seat, input_device); if (!seat_device) { return; } @@ -219,10 +219,10 @@ void sway_seat_configure_device(struct sway_seat *seat, } } -void sway_seat_add_device(struct sway_seat *seat, +void 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); + if (seat_get_device(seat, input_device)) { + seat_configure_device(seat, input_device); return; } @@ -240,13 +240,13 @@ void sway_seat_add_device(struct sway_seat *seat, seat_device->input_device = input_device; wl_list_insert(&seat->devices, &seat_device->link); - sway_seat_configure_device(seat, input_device); + seat_configure_device(seat, input_device); } -void sway_seat_remove_device(struct sway_seat *seat, +void seat_remove_device(struct sway_seat *seat, struct sway_input_device *input_device) { struct sway_seat_device *seat_device = - sway_seat_get_device(seat, input_device); + seat_get_device(seat, input_device); if (!seat_device) { return; @@ -258,7 +258,7 @@ void sway_seat_remove_device(struct sway_seat *seat, seat_device_destroy(seat_device); } -void sway_seat_configure_xcursor(struct sway_seat *seat) { +void seat_configure_xcursor(struct sway_seat *seat) { // TODO configure theme and size const char *cursor_theme = NULL; @@ -292,9 +292,9 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -void sway_seat_set_focus_warp(struct sway_seat *seat, +void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { - struct sway_container *last_focus = sway_seat_get_focus(seat); + struct sway_container *last_focus = seat_get_focus(seat); if (container && last_focus == container) { return; @@ -372,12 +372,12 @@ void sway_seat_set_focus_warp(struct sway_seat *seat, seat->has_focus = (container != NULL); } -void sway_seat_set_focus(struct sway_seat *seat, +void seat_set_focus(struct sway_seat *seat, struct sway_container *container) { - sway_seat_set_focus_warp(seat, container, true); + seat_set_focus_warp(seat, container, true); } -struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { +struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { struct sway_seat_container *current = NULL; struct sway_container *parent = NULL; wl_list_for_each(current, &seat->focus_stack, link) { @@ -398,16 +398,16 @@ 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) { +struct sway_container *seat_get_focus(struct sway_seat *seat) { if (!seat->has_focus) { return NULL; } - return sway_seat_get_focus_inactive(seat, &root_container); + return seat_get_focus_inactive(seat, &root_container); } -struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, +struct sway_container *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); + struct sway_container *focus = seat_get_focus_inactive(seat, &root_container); if (focus->type == type) { return focus; } @@ -415,7 +415,7 @@ struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, return container_parent(focus, type); } -void sway_seat_set_config(struct sway_seat *seat, +void seat_set_config(struct sway_seat *seat, struct seat_config *seat_config) { // clear configs free_seat_config(seat->config); @@ -434,6 +434,6 @@ void sway_seat_set_config(struct sway_seat *seat, seat->config = copy_seat_config(seat_config); wl_list_for_each(seat_device, &seat->devices, link) { - sway_seat_configure_device(seat, seat_device->input_device); + seat_configure_device(seat, seat_device->input_device); } } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 7c5f73047..1b906e6f1 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -92,7 +92,7 @@ static void ipc_json_describe_output(struct sway_container *container, json_obje const char *ws = NULL; if (seat) { struct sway_container *focus = - sway_seat_get_focus_inactive(seat, container); + seat_get_focus_inactive(seat, container); if (focus && focus->type != C_WORKSPACE) { focus = container_parent(focus, C_WORKSPACE); } @@ -140,7 +140,7 @@ json_object *ipc_json_describe_container(struct sway_container *c) { } struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); - bool focused = sway_seat_get_focus(seat) == c; + bool focused = seat_get_focus(seat) == c; json_object *object = json_object_new_object(); diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 869f1ed02..8c06f71ba 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -389,7 +389,7 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace, // it's set differently for the get_workspaces reply struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); - struct sway_container *focused_ws = sway_seat_get_focus(seat); + struct sway_container *focused_ws = seat_get_focus(seat); if (focused_ws != NULL && focused_ws->type != C_WORKSPACE) { focused_ws = container_parent(focused_ws, C_WORKSPACE); } @@ -399,7 +399,7 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace, json_object_new_boolean(focused)); json_object_array_add((json_object *)data, workspace_json); - focused_ws = sway_seat_get_focus_inactive(seat, workspace->parent); + focused_ws = seat_get_focus_inactive(seat, workspace->parent); if (focused_ws->type != C_WORKSPACE) { focused_ws = container_parent(focused_ws, C_WORKSPACE); } diff --git a/sway/tree/container.c b/sway/tree/container.c index 746dbf1f9..2d7528620 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -144,7 +144,7 @@ struct sway_container *container_output_create( struct sway_seat *seat = NULL; wl_list_for_each(seat, &input_manager->seats, link) { if (!seat->has_focus) { - sway_seat_set_focus(seat, ws); + seat_set_focus(seat, ws); } } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce0682dc9..0a766b226 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -404,7 +404,7 @@ static struct sway_container *get_swayc_in_output_direction( return NULL; } - struct sway_container *ws = sway_seat_get_focus_inactive(seat, output); + struct sway_container *ws = seat_get_focus_inactive(seat, output); if (ws->type != C_WORKSPACE) { ws = container_parent(ws, C_WORKSPACE); } @@ -425,7 +425,7 @@ static struct sway_container *get_swayc_in_output_direction( case MOVE_UP: case MOVE_DOWN: { struct sway_container *focused = - sway_seat_get_focus_inactive(seat, ws); + seat_get_focus_inactive(seat, ws); if (focused && focused->parent) { struct sway_container *parent = focused->parent; if (parent->layout == L_VERT) { @@ -509,7 +509,7 @@ 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); + return seat_get_focus_inactive(seat, container); } struct sway_container *parent = container->parent; @@ -589,7 +589,7 @@ static struct sway_container *get_swayc_in_direction_under( } if (next->children && next->children->length) { // TODO consider floating children as well - return sway_seat_get_focus_inactive(seat, next); + return seat_get_focus_inactive(seat, next); } else { return next; } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c629f1f17..c47bab332 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -158,7 +158,7 @@ static bool _workspace_by_name(struct sway_container *view, void *data) { struct sway_container *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); + struct sway_container *focus = seat_get_focus(seat); if (focus) { current_workspace = container_parent(focus, C_WORKSPACE); current_output = container_parent(focus, C_OUTPUT); @@ -200,7 +200,7 @@ 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); + seat_get_focus_inactive(seat, &root_container); parent = focus; parent = container_parent(parent, C_OUTPUT); struct sway_container *new_ws = container_workspace_create(parent, name); @@ -260,7 +260,7 @@ struct sway_container *workspace_output_prev_next_impl( } struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); + struct sway_container *focus = seat_get_focus_inactive(seat, output); struct sway_container *workspace = (focus->type == C_WORKSPACE ? focus : container_parent(focus, C_WORKSPACE)); @@ -345,7 +345,7 @@ bool workspace_switch(struct sway_container *workspace) { } struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *focus = - sway_seat_get_focus_inactive(seat, &root_container); + seat_get_focus_inactive(seat, &root_container); if (!seat || !focus) { return false; } @@ -376,11 +376,11 @@ bool workspace_switch(struct sway_container *workspace) { wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); - struct sway_container *next = sway_seat_get_focus_inactive(seat, workspace); + struct sway_container *next = seat_get_focus_inactive(seat, workspace); if (next == NULL) { next = workspace; } - sway_seat_set_focus(seat, next); + seat_set_focus(seat, next); struct sway_container *output = container_parent(workspace, C_OUTPUT); arrange_windows(output, -1, -1); return true; @@ -389,7 +389,7 @@ bool workspace_switch(struct sway_container *workspace) { bool workspace_is_visible(struct sway_container *ws) { struct sway_container *output = container_parent(ws, C_OUTPUT); struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); + struct sway_container *focus = seat_get_focus_inactive(seat, output); if (focus->type != C_WORKSPACE) { focus = container_parent(focus, C_WORKSPACE); } From 0828c772514a85080c53ecade0b8b400314d5b03 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 08:49:38 -0400 Subject: [PATCH 358/522] rename input-manager functions --- include/sway/input/input-manager.h | 15 +++++++-------- sway/commands.c | 6 +++--- sway/desktop/output.c | 2 +- sway/desktop/wl_shell.c | 2 +- sway/desktop/xdg_shell_v6.c | 2 +- sway/desktop/xwayland.c | 2 +- sway/input/input-manager.c | 24 ++++++++++++------------ sway/input/seat.c | 2 +- sway/ipc-json.c | 4 ++-- sway/ipc-server.c | 2 +- sway/server.c | 2 +- 11 files changed, 31 insertions(+), 32 deletions(-) diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index c6c73dbab..8515c7385 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -27,24 +27,23 @@ struct sway_input_manager { struct wl_listener new_input; }; -struct sway_input_manager *sway_input_manager_create( - struct sway_server *server); +struct sway_input_manager *input_manager_create(struct sway_server *server); -bool sway_input_manager_has_focus(struct sway_input_manager *input, +bool input_manager_has_focus(struct sway_input_manager *input, struct sway_container *container); -void sway_input_manager_set_focus(struct sway_input_manager *input, +void input_manager_set_focus(struct sway_input_manager *input, struct sway_container *container); -void sway_input_manager_configure_xcursor(struct sway_input_manager *input); +void input_manager_configure_xcursor(struct sway_input_manager *input); -void sway_input_manager_apply_input_config(struct sway_input_manager *input, +void 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, +void 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_seat *input_manager_get_default_seat( struct sway_input_manager *input); struct sway_seat *input_manager_get_seat(struct sway_input_manager *input, diff --git a/sway/commands.c b/sway/commands.c index 91b44fbfb..dc6c867f5 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -72,7 +72,7 @@ void apply_input_config(struct input_config *input) { list_add(config->input_configs, input); } - sway_input_manager_apply_input_config(input_manager, input); + input_manager_apply_input_config(input_manager, input); } void apply_seat_config(struct seat_config *seat) { @@ -88,7 +88,7 @@ void apply_seat_config(struct seat_config *seat) { list_add(config->seat_configs, seat); } - sway_input_manager_apply_seat_config(input_manager, seat); + input_manager_apply_seat_config(input_manager, seat); } /* Keep alphabetized */ @@ -262,7 +262,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { if (seat == NULL) { // passing a NULL seat means we just pick the default seat - seat = sway_input_manager_get_default_seat(input_manager); + seat = input_manager_get_default_seat(input_manager); if (!sway_assert(seat, "could not find a seat to run the command on")) { return NULL; } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 86b023cbd..ea3938a47 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -370,7 +370,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { wl_list_init(&output->layers[i]); } - sway_input_manager_configure_xcursor(input_manager); + input_manager_configure_xcursor(input_manager); wl_signal_add(&wlr_output->events.destroy, &output->destroy); output->destroy.notify = handle_destroy; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 3e275f2b4..c44fcf270 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -138,5 +138,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); - sway_input_manager_set_focus(input_manager, cont); + input_manager_set_focus(input_manager, cont); } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 286d52cc1..cffe83fbb 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -102,7 +102,7 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_container *cont = container_view_create(focus, view); view->swayc = cont; arrange_windows(cont->parent, -1, -1); - sway_input_manager_set_focus(input_manager, cont); + input_manager_set_focus(input_manager, cont); view_damage_whole(sway_surface->view); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 8fb6cb52a..17f827d98 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -148,7 +148,7 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_container *cont = container_view_create(focus, view); view->swayc = cont; arrange_windows(cont->parent, -1, -1); - sway_input_manager_set_focus(input_manager, cont); + input_manager_set_focus(input_manager, cont); } view_damage_whole(sway_surface->view); diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 66ade685d..4f3c3ee58 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -26,7 +26,7 @@ struct seat_config *current_seat_config = NULL; struct sway_seat *input_manager_current_seat(struct sway_input_manager *input) { struct sway_seat *seat = config->handler_context.seat; if (!seat) { - seat = sway_input_manager_get_default_seat(input_manager); + seat = input_manager_get_default_seat(input_manager); } return seat; } @@ -91,7 +91,7 @@ static bool input_has_seat_configuration(struct sway_input_manager *input) { return false; } -static void sway_input_manager_libinput_config_pointer(struct sway_input_device *input_device) { +static void input_manager_libinput_config_pointer(struct sway_input_device *input_device) { struct wlr_input_device *wlr_device = input_device->wlr_device; struct input_config *ic = input_device->config; struct libinput_device *libinput_device; @@ -101,7 +101,7 @@ static void sway_input_manager_libinput_config_pointer(struct sway_input_device } libinput_device = wlr_libinput_get_device_handle(wlr_device); - wlr_log(L_DEBUG, "sway_input_manager_libinput_config_pointer(%s)", ic->identifier); + wlr_log(L_DEBUG, "input_manager_libinput_config_pointer(%s)", ic->identifier); if (ic->accel_profile != INT_MIN) { wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", @@ -214,7 +214,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { } if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { - sway_input_manager_libinput_config_pointer(input_device); + input_manager_libinput_config_pointer(input_device); } struct sway_seat *seat = NULL; @@ -256,7 +256,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { input_device->device_destroy.notify = handle_device_destroy; } -struct sway_input_manager *sway_input_manager_create( +struct sway_input_manager *input_manager_create( struct sway_server *server) { struct sway_input_manager *input = calloc(1, sizeof(struct sway_input_manager)); @@ -277,7 +277,7 @@ struct sway_input_manager *sway_input_manager_create( return input; } -bool sway_input_manager_has_focus(struct sway_input_manager *input, +bool input_manager_has_focus(struct sway_input_manager *input, struct sway_container *container) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { @@ -289,7 +289,7 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, return false; } -void sway_input_manager_set_focus(struct sway_input_manager *input, +void input_manager_set_focus(struct sway_input_manager *input, struct sway_container *container) { struct sway_seat *seat ; wl_list_for_each(seat, &input->seats, link) { @@ -297,7 +297,7 @@ void sway_input_manager_set_focus(struct sway_input_manager *input, } } -void sway_input_manager_apply_input_config(struct sway_input_manager *input, +void input_manager_apply_input_config(struct sway_input_manager *input, struct input_config *input_config) { struct sway_input_device *input_device = NULL; wl_list_for_each(input_device, &input->devices, link) { @@ -306,7 +306,7 @@ void sway_input_manager_apply_input_config(struct sway_input_manager *input, 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); + input_manager_libinput_config_pointer(input_device); } struct sway_seat *seat = NULL; @@ -317,7 +317,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, +void input_manager_apply_seat_config(struct sway_input_manager *input, struct seat_config *seat_config) { wlr_log(L_DEBUG, "applying new seat config for seat %s", seat_config->name); @@ -373,14 +373,14 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, } } -void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { +void input_manager_configure_xcursor(struct sway_input_manager *input) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { seat_configure_xcursor(seat); } } -struct sway_seat *sway_input_manager_get_default_seat( +struct sway_seat *input_manager_get_default_seat( struct sway_input_manager *input) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { diff --git a/sway/input/seat.c b/sway/input/seat.c index 703951445..c2ecd1c4d 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -364,7 +364,7 @@ void seat_set_focus_warp(struct sway_seat *seat, } if (last_focus && last_focus->type == C_VIEW && - !sway_input_manager_has_focus(seat->input, last_focus)) { + !input_manager_has_focus(seat->input, last_focus)) { struct sway_view *view = last_focus->sway_view; view_set_activated(view, false); } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 1b906e6f1..3427c8ec3 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -88,7 +88,7 @@ static void ipc_json_describe_output(struct sway_container *container, json_obje json_object_new_string( ipc_json_get_output_transform(wlr_output->transform))); - struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); + struct sway_seat *seat = input_manager_get_default_seat(input_manager); const char *ws = NULL; if (seat) { struct sway_container *focus = @@ -139,7 +139,7 @@ json_object *ipc_json_describe_container(struct sway_container *c) { return NULL; } - struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); + struct sway_seat *seat = input_manager_get_default_seat(input_manager); bool focused = seat_get_focus(seat) == c; json_object *object = json_object_new_object(); diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 8c06f71ba..df5fb699f 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -388,7 +388,7 @@ static void ipc_get_workspaces_callback(struct sway_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); + input_manager_get_default_seat(input_manager); struct sway_container *focused_ws = seat_get_focus(seat); if (focused_ws != NULL && focused_ws->type != C_WORKSPACE) { focused_ws = container_parent(focused_ws, C_WORKSPACE); diff --git a/sway/server.c b/sway/server.c index f5cc199c3..549453121 100644 --- a/sway/server.c +++ b/sway/server.c @@ -109,7 +109,7 @@ bool server_init(struct sway_server *server) { return false; } - input_manager = sway_input_manager_create(server); + input_manager = input_manager_create(server); return true; } From 53bb7ea9962c5d97e0672eabcf1b9dfb7ffad0f1 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 10:37:31 -0400 Subject: [PATCH 359/522] dont copy seat config on the seat --- include/sway/input/seat.h | 5 +++-- sway/input/input-manager.c | 25 +++++++++++++++---------- sway/input/seat.c | 27 +++++++++++++++++---------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 38a6379c9..3a1cf350c 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -23,7 +23,6 @@ struct sway_seat_container { struct sway_seat { struct wlr_seat *wlr_seat; - struct seat_config *config; struct sway_cursor *cursor; struct sway_input_manager *input; @@ -76,6 +75,8 @@ struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, enum sway_container_type type); -void seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); +void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config); + +struct seat_config *seat_get_config(struct sway_seat *seat); #endif diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 4f3c3ee58..d9d20200f 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -83,7 +83,8 @@ static struct sway_input_device *input_sway_device_from_wlr( 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) { + struct seat_config *seat_config = seat_get_config(seat); + if (seat_config) { return true; } } @@ -225,11 +226,13 @@ static void handle_new_input(struct wl_listener *listener, void *data) { return; } + struct seat_config *seat_config = seat_get_config(seat); + bool added = false; wl_list_for_each(seat, &input->seats, link) { - bool has_attachment = seat->config && - (seat_config_get_attachment(seat->config, input_device->identifier) || - seat_config_get_attachment(seat->config, "*")); + bool has_attachment = config && + (seat_config_get_attachment(seat_config, input_device->identifier) || + seat_config_get_attachment(seat_config, "*")); if (has_attachment) { seat_add_device(seat, input_device); @@ -239,7 +242,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { if (!added) { wl_list_for_each(seat, &input->seats, link) { - if (seat->config && seat->config->fallback == 1) { + if (seat_config && seat_config->fallback == 1) { seat_add_device(seat, input_device); added = true; } @@ -326,7 +329,7 @@ void input_manager_apply_seat_config(struct sway_input_manager *input, return; } - seat_set_config(seat, seat_config); + seat_apply_config(seat, seat_config); // for every device, try to add it to a seat and if no seat has it // attached, add it to the fallback seats. @@ -335,11 +338,12 @@ void input_manager_apply_seat_config(struct sway_input_manager *input, list_t *seat_list = create_list(); struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { - if (!seat->config) { + struct seat_config *seat_config = seat_get_config(seat); + if (!seat_config) { continue; } - if (seat_config_get_attachment(seat->config, "*") || - seat_config_get_attachment(seat->config, + if (seat_config_get_attachment(seat_config, "*") || + seat_config_get_attachment(seat_config, input_device->identifier)) { list_add(seat_list, seat); } @@ -362,7 +366,8 @@ void input_manager_apply_seat_config(struct sway_input_manager *input, } } else { wl_list_for_each(seat, &input->seats, link) { - if (seat->config && seat->config->fallback == 1) { + struct seat_config *seat_config = seat_get_config(seat); + if (seat_config && seat_config->fallback == 1) { seat_add_device(seat, input_device); } else { seat_remove_device(seat, input_device); diff --git a/sway/input/seat.c b/sway/input/seat.c index c2ecd1c4d..91a9e32bb 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -199,9 +199,11 @@ void seat_configure_device(struct sway_seat *seat, return; } - if (seat->config) { + 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); + seat_config_get_attachment(seat_config, input_device->identifier); } switch (input_device->wlr_device->type) { @@ -415,12 +417,8 @@ struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, return container_parent(focus, type); } -void seat_set_config(struct sway_seat *seat, +void seat_apply_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; wl_list_for_each(seat_device, &seat->devices, link) { seat_device->attachment_config = NULL; @@ -430,10 +428,19 @@ void seat_set_config(struct sway_seat *seat, return; } - // add configs - seat->config = copy_seat_config(seat_config); - wl_list_for_each(seat_device, &seat->devices, link) { seat_configure_device(seat, seat_device->input_device); } } + +struct seat_config *seat_get_config(struct sway_seat *seat) { + struct seat_config *seat_config = NULL; + for (int i = 0; i < config->seat_configs->length; ++i ) { + seat_config = config->seat_configs->items[i]; + if (strcmp(seat->wlr_seat->name, seat_config->name) == 0) { + return seat_config; + } + } + + return NULL; +} From 61fabede14bb3a8fe9ee5a249352cd405fd1b9bf Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 2 Apr 2018 10:57:45 -0400 Subject: [PATCH 360/522] Address review comments --- include/sway/tree/view.h | 21 +++--- sway/desktop/wl_shell.c | 23 +++--- sway/desktop/xdg_shell_v6.c | 24 +++---- sway/desktop/xwayland.c | 31 +++----- sway/tree/layout.c | 8 ++- sway/tree/output.c | 1 + sway/tree/view.c | 139 +++++++++++++++++++++--------------- 7 files changed, 125 insertions(+), 122 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index c68739d64..4e753b2a1 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -69,10 +69,8 @@ enum sway_view_prop { struct sway_view_impl { 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 (*configure)(struct sway_view *view, double ox, double oy, int width, + int height); void (*set_activated)(struct sway_view *view, bool activated); void (*close)(struct sway_view *view); }; @@ -114,14 +112,19 @@ 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_configure(struct sway_view *view, double ox, double oy, int width, + int height); void view_set_activated(struct sway_view *view, bool activated); void view_close(struct sway_view *view); +void view_damage_whole(struct sway_view *view); + +void view_damage_from(struct sway_view *view); + +// view implementation + void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); void view_map_unmanaged(struct sway_view *view, @@ -129,8 +132,8 @@ void view_map_unmanaged(struct sway_view *view, void view_unmap(struct sway_view *view); -void view_damage_whole(struct sway_view *view); +void view_update_position(struct sway_view *view, double ox, double oy); -void view_damage_from(struct sway_view *view); +void view_update_size(struct sway_view *view, int width, int height); #endif diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index e0909a03a..6528a3972 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -30,24 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } } -static void set_size(struct sway_view *view, int width, int height) { +static void configure(struct sway_view *view, double ox, double oy, int width, + int height) { if (!assert_wl_shell(view)) { return; } + view_update_position(view, ox, oy); view->sway_wl_shell_surface->pending_width = width; view->sway_wl_shell_surface->pending_height = height; wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); } -static void set_position(struct sway_view *view, double ox, double oy) { - if (!assert_wl_shell(view)) { - return; - } - view->swayc->x = ox; - view->swayc->y = oy; -} - -static void close(struct sway_view *view) { +static void _close(struct sway_view *view) { if (!assert_wl_shell(view)) { return; } @@ -57,9 +51,8 @@ static void close(struct sway_view *view) { static const struct sway_view_impl view_impl = { .get_prop = get_prop, - .set_size = set_size, - .set_position = set_position, - .close = close, + .configure = configure, + .close = _close, }; static void handle_commit(struct wl_listener *listener, void *data) { @@ -68,8 +61,8 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_view *view = sway_surface->view; // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever - view->width = sway_surface->pending_width; - view->height = sway_surface->pending_height; + view_update_size(view, sway_surface->pending_width, + sway_surface->pending_height); view_damage_from(view); } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index c1adc7feb..49305b39e 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -30,23 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } } -static void set_size(struct sway_view *view, int width, int height) { +static void configure(struct sway_view *view, double ox, double oy, int width, + int height) { if (!assert_xdg(view)) { return; } + + view_update_position(view, ox, oy); view->sway_xdg_surface_v6->pending_width = width; view->sway_xdg_surface_v6->pending_height = height; wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); } -static void set_position(struct sway_view *view, double ox, double oy) { - if (!assert_xdg(view)) { - return; - } - view->swayc->x = ox; - view->swayc->y = oy; -} - static void set_activated(struct sway_view *view, bool activated) { if (!assert_xdg(view)) { return; @@ -57,7 +52,7 @@ static void set_activated(struct sway_view *view, bool activated) { } } -static void close(struct sway_view *view) { +static void _close(struct sway_view *view) { if (!assert_xdg(view)) { return; } @@ -69,10 +64,9 @@ static void close(struct sway_view *view) { static const struct sway_view_impl view_impl = { .get_prop = get_prop, - .set_size = set_size, - .set_position = set_position, + .configure = configure, .set_activated = set_activated, - .close = close, + .close = _close, }; static void handle_commit(struct wl_listener *listener, void *data) { @@ -82,8 +76,8 @@ static void handle_commit(struct wl_listener *listener, void *data) { // NOTE: We intentionally discard the view's desired width here // TODO: Store this for restoration when moving to floating plane // TODO: Let floating views do whatever - view->width = sway_surface->pending_width; - view->height = sway_surface->pending_height; + view_update_size(view, sway_surface->pending_width, + sway_surface->pending_height); view_damage_from(view); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 93c782286..39076fabd 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -33,22 +33,13 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { } } -static void set_size(struct sway_view *view, int width, int height) { +static void configure(struct sway_view *view, double ox, double oy, int width, + int height) { if (!assert_xwayland(view)) { return; } - view->sway_xwayland_surface->pending_width = width; - view->sway_xwayland_surface->pending_height = height; - struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - wlr_xwayland_surface_configure(xsurface, xsurface->x, xsurface->y, - width, height); -} -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); if (!sway_assert(output, "view must be within tree to set position")) { return; @@ -64,13 +55,12 @@ static void set_position(struct sway_view *view, double ox, double oy) { return; } - view->swayc->x = ox; - view->swayc->y = oy; + view_update_position(view, ox, oy); - wlr_xwayland_surface_configure(view->wlr_xwayland_surface, - ox + loutput->x, oy + loutput->y, - view->wlr_xwayland_surface->width, - view->wlr_xwayland_surface->height); + view->sway_xwayland_surface->pending_width = width; + view->sway_xwayland_surface->pending_height = height; + wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, + width, height); } static void set_activated(struct sway_view *view, bool activated) { @@ -90,8 +80,7 @@ static void _close(struct sway_view *view) { static const struct sway_view_impl view_impl = { .get_prop = get_prop, - .set_size = set_size, - .set_position = set_position, + .configure = configure, .set_activated = set_activated, .close = _close, }; @@ -102,8 +91,8 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_view *view = sway_surface->view; // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever - view->width = sway_surface->pending_width; - view->height = sway_surface->pending_height; + view_update_size(view, sway_surface->pending_width, + sway_surface->pending_height); view_damage_from(view); } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce0682dc9..3fec02a1c 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -261,7 +261,7 @@ void arrange_windows(struct sway_container *container, { container->width = width; container->height = height; - view_set_size(container->sway_view, + view_configure(container->sway_view, container->x, container->y, container->width, container->height); wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", container->width, container->height, @@ -322,7 +322,8 @@ static void apply_horiz_layout(struct sway_container *container, wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); - view_set_position(child->sway_view, child_x, y); + view_configure(child->sway_view, child_x, y, child->width, + child->height); if (i == end - 1) { double remaining_width = x + width - child_x; @@ -373,7 +374,8 @@ void apply_vert_layout(struct sway_container *container, wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); - view_set_position(child->sway_view, x, child_y); + view_configure(child->sway_view, x, child_y, child->width, + child->height); if (i == end - 1) { double remaining_height = y + height - child_y; diff --git a/sway/tree/output.c b/sway/tree/output.c index 7248fd006..80a36ac76 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -29,6 +29,7 @@ struct sway_container *container_output_destroy(struct sway_container *output) { wl_list_remove(&output->sway_output->destroy.link); wl_list_remove(&output->sway_output->mode.link); wl_list_remove(&output->sway_output->transform.link); + wl_list_remove(&output->sway_output->scale.link); wl_list_remove(&output->sway_output->damage_destroy.link); wl_list_remove(&output->sway_output->damage_frame.link); diff --git a/sway/tree/view.c b/sway/tree/view.c index d7a52e19e..73e3d4452 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -62,55 +62,10 @@ const char *view_get_instance(struct sway_view *view) { return NULL; } -static void view_update_outputs(struct sway_view *view, - const struct wlr_box *before) { - struct wlr_output_layout *output_layout = - root_container.sway_root->output_layout; - struct wlr_box box = { - .x = view->swayc->x, - .y = view->swayc->y, - .width = view->width, - .height = view->height, - }; - struct wlr_output_layout_output *layout_output; - wl_list_for_each(layout_output, &output_layout->outputs, link) { - bool intersected = before != NULL && wlr_output_layout_intersects( - output_layout, layout_output->output, before); - bool intersects = wlr_output_layout_intersects(output_layout, - layout_output->output, &box); - if (intersected && !intersects) { - wlr_surface_send_leave(view->surface, layout_output->output); - } - if (!intersected && intersects) { - wlr_surface_send_enter(view->surface, layout_output->output); - } - } -} - -void view_set_size(struct sway_view *view, int width, int height) { - if (view->impl->set_size) { - struct wlr_box box = { - .x = view->swayc->x, - .y = view->swayc->y, - .width = view->width, - .height = view->height, - }; - view->impl->set_size(view, width, height); - view_update_outputs(view, &box); - } -} - -// TODO make view coordinates in layout coordinates -void view_set_position(struct sway_view *view, double ox, double oy) { - if (view->impl->set_position) { - struct wlr_box box = { - .x = view->swayc->x, - .y = view->swayc->y, - .width = view->width, - .height = view->height, - }; - view->impl->set_position(view, ox, oy); - view_update_outputs(view, &box); +void view_configure(struct sway_view *view, double ox, double oy, int width, + int height) { + if (view->impl->configure) { + view->impl->configure(view, ox, oy, width, height); } } @@ -136,6 +91,56 @@ struct sway_container *container_view_destroy(struct sway_container *view) { return parent; } +void view_damage_whole(struct sway_view *view) { + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *cont = root_container.children->items[i]; + if (cont->type == C_OUTPUT) { + output_damage_whole_view(cont->sway_output, view); + } + } +} + +void view_damage_from(struct sway_view *view) { + // TODO + view_damage_whole(view); +} + +static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { + struct sway_container *cont = container_parent(view->swayc, C_OUTPUT); + + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; + struct wlr_box *output_box = wlr_output_layout_get_box(output_layout, + cont->sway_output->wlr_output); + + box->x = output_box->x + view->swayc->x; + box->y = output_box->y + view->swayc->y; + box->width = view->width; + box->height = view->height; +} + +static void view_update_outputs(struct sway_view *view, + const struct wlr_box *before) { + struct wlr_box box; + view_get_layout_box(view, &box); + + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; + struct wlr_output_layout_output *layout_output; + wl_list_for_each(layout_output, &output_layout->outputs, link) { + bool intersected = before != NULL && wlr_output_layout_intersects( + output_layout, layout_output->output, before); + bool intersects = wlr_output_layout_intersects(output_layout, + layout_output->output, &box); + if (intersected && !intersects) { + wlr_surface_send_leave(view->surface, layout_output->output); + } + if (!intersected && intersects) { + wlr_surface_send_enter(view->surface, layout_output->output); + } + } +} + void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { return; @@ -153,6 +158,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { sway_input_manager_set_focus(input_manager, cont); view_damage_whole(view); + view_update_outputs(view, NULL); } void view_map_unmanaged(struct sway_view *view, @@ -168,6 +174,8 @@ void view_map_unmanaged(struct sway_view *view, &view->unmanaged_view_link); view_damage_whole(view); + // TODO: make this work for unmanaged views + //view_update_outputs(view, NULL); } void view_unmap(struct sway_view *view) { @@ -186,17 +194,30 @@ void view_unmap(struct sway_view *view) { view->surface = NULL; } -void view_damage_whole(struct sway_view *view) { - struct sway_container *cont = NULL; - for (int i = 0; i < root_container.children->length; ++i) { - cont = root_container.children->items[i]; - if (cont->type == C_OUTPUT) { - output_damage_whole_view(cont->sway_output, view); - } +void view_update_position(struct sway_view *view, double ox, double oy) { + if (view->swayc->x == ox && view->swayc->y == oy) { + return; } -} -void view_damage_from(struct sway_view *view) { - // TODO + struct wlr_box box; + view_get_layout_box(view, &box); + view_damage_whole(view); + view->swayc->x = ox; + view->swayc->y = oy; + view_update_outputs(view, &box); + view_damage_whole(view); +} + +void view_update_size(struct sway_view *view, int width, int height) { + if (view->width == width && view->height == height) { + return; + } + + struct wlr_box box; + view_get_layout_box(view, &box); + view_damage_whole(view); + view->width = width; + view->height = height; + view_update_outputs(view, &box); view_damage_whole(view); } From ee85c918317ec6a685a999db46f692c7d13cdf2a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 13:07:22 -0400 Subject: [PATCH 361/522] Demarcate i3bar JSON into individual updates --- include/swaybar/status_line.h | 49 ++++++++++++++++++- swaybar/i3bar.c | 88 +++++++++++++++++++++++++++++++++++ swaybar/meson.build | 1 + swaybar/status_line.c | 62 ++++++++++++++++++++---- 4 files changed, 189 insertions(+), 11 deletions(-) create mode 100644 swaybar/i3bar.c diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 6c595df0f..3b93e28f1 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -7,10 +7,52 @@ enum status_protocol { PROTOCOL_UNDEF, + PROTOCOL_ERROR, PROTOCOL_TEXT, PROTOCOL_I3BAR, }; +struct text_protocol_state { + char *buffer; + size_t buffer_size; +}; + +enum json_node_type { + JSON_NODE_UNKNOWN, + JSON_NODE_ARRAY, + JSON_NODE_STRING, +}; + +struct i3bar_protocol_state { + bool click_events; + char *buffer; + size_t buffer_size; + size_t buffer_index; + const char *current_node; + bool escape; + size_t depth; + enum json_node_type nodes[16]; +}; + +struct i3bar_block { + struct wl_list link; + char *full_text, *short_text, *align; + bool urgent; + uint32_t color; + int min_width; + char *name, *instance; + bool separator; + int separator_block_width; + bool markup; + // Airblader features + uint32_t background; + uint32_t border; + int border_top; + int border_bottom; + int border_left; + int border_right; +}; + struct status_line { pid_t pid; int read_fd, write_fd; @@ -18,13 +60,16 @@ struct status_line { enum status_protocol protocol; const char *text; + struct wl_list blocks; // i3bar_block::link - char *buffer; - size_t buffer_size; + struct text_protocol_state text_state; + struct i3bar_protocol_state i3bar_state; }; struct status_line *status_line_init(char *cmd); void status_line_free(struct status_line *status); bool handle_status_readable(struct status_line *status); +int i3bar_readable(struct status_line *status); +void status_error(struct status_line *status, const char *text); #endif diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c new file mode 100644 index 000000000..5be348b24 --- /dev/null +++ b/swaybar/i3bar.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include "swaybar/config.h" +#include "swaybar/status_line.h" + +static void i3bar_parse_json(struct status_line *status, const char *text) { + wlr_log(L_DEBUG, "got json: %s", text); +} + +int i3bar_readable(struct status_line *status) { + struct i3bar_protocol_state *state = &status->i3bar_state; + + char *cur = &state->buffer[state->buffer_index]; + ssize_t n = read(status->read_fd, cur, + state->buffer_size - state->buffer_index); + if (n == 0) { + return 0; + } + + if (n == (ssize_t)(state->buffer_size - state->buffer_index)) { + state->buffer_size = state->buffer_size * 2; + char *new_buffer = realloc(state->buffer, state->buffer_size); + if (!new_buffer) { + free(state->buffer); + status_error(status, "[failed to allocate buffer]"); + return -1; + } + state->buffer = new_buffer; + } + + int handled = 0; + while (*cur) { + if (state->nodes[state->depth] == JSON_NODE_STRING) { + if (!state->escape && *cur == '"') { + --state->depth; + } + state->escape = !state->escape && *cur == '\\'; + } else { + switch (*cur) { + case '[': + ++state->depth; + if (state->depth > + sizeof(state->nodes) / sizeof(state->nodes[0])) { + status_error(status, "[i3bar json too deep]"); + return -1; + } + state->nodes[state->depth] = JSON_NODE_ARRAY; + if (state->depth == 1) { + state->current_node = cur; + } + break; + case ']': + if (state->nodes[state->depth] != JSON_NODE_ARRAY) { + status_error(status, "[failed to parse i3bar json]"); + return -1; + } + --state->depth; + if (state->depth == 0) { + // cur[1] is valid since cur[0] != '\0' + char p = cur[1]; + cur[1] = '\0'; + i3bar_parse_json(status, state->current_node); + cur[1] = p; + memmove(state->buffer, cur, + state->buffer_size - (cur - state->buffer)); + ++handled; + cur = state->buffer; + state->current_node = cur + 1; + } + break; + case '"': + ++state->depth; + if (state->depth > + sizeof(state->nodes) / sizeof(state->nodes[0])) { + status_error(status, "[i3bar json too deep]"); + return -1; + } + state->nodes[state->depth] = JSON_NODE_STRING; + break; + } + } + ++cur; + } + state->buffer_index = cur - state->buffer; + return handled; +} diff --git a/swaybar/meson.build b/swaybar/meson.build index bf6f6d7a2..d65edb11e 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -3,6 +3,7 @@ executable( 'bar.c', 'config.c', 'event_loop.c', + 'i3bar.c', 'ipc.c', 'main.c', 'render.c', diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 3454f2072..c94ac6d4e 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE #include +#include #include #include #include @@ -9,35 +10,78 @@ #include "swaybar/status_line.h" #include "readline.h" +void status_error(struct status_line *status, const char *text) { + close(status->read_fd); + close(status->write_fd); + status->protocol = PROTOCOL_ERROR; + status->text = text; +} + bool handle_status_readable(struct status_line *status) { - char *line = read_line_buffer(status->read, - status->buffer, status->buffer_size); + char *line; switch (status->protocol) { + case PROTOCOL_ERROR: + return false; case PROTOCOL_I3BAR: - // TODO + if (i3bar_readable(status) > 0) { + return true; + } break; case PROTOCOL_TEXT: - status->text = line; + line = read_line_buffer(status->read, + status->text_state.buffer, status->text_state.buffer_size); + if (!line) { + status_error(status, "[error reading from status command]"); + } else { + status->text = line; + } return true; case PROTOCOL_UNDEF: + line = read_line_buffer(status->read, + status->text_state.buffer, status->text_state.buffer_size); if (!line) { + status_error(status, "[error reading from status command]"); return false; } if (line[0] == '{') { - // TODO: JSON + 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) { + wlr_log(L_DEBUG, "Switched to i3bar protocol."); + status->protocol = PROTOCOL_I3BAR; + } + json_object *click_events; + if (json_object_object_get_ex( + proto, "click_events", &click_events) + && json_object_get_boolean(click_events)) { + wlr_log(L_DEBUG, "Enabled click events."); + status->i3bar_state.click_events = true; + const char *events_array = "[\n"; + write(status->write_fd, events_array, strlen(events_array)); + } + json_object_put(proto); + } + + status->protocol = PROTOCOL_I3BAR; + free(status->text_state.buffer); + status->i3bar_state.buffer_size = 4096; + status->i3bar_state.buffer = + malloc(status->i3bar_state.buffer_size); } else { - status->text = line; status->protocol = PROTOCOL_TEXT; + status->text = line; } - return false; + return true; } return false; } struct status_line *status_line_init(char *cmd) { struct status_line *status = calloc(1, sizeof(struct status_line)); - status->buffer_size = 4096; - status->buffer = malloc(status->buffer_size); + status->text_state.buffer_size = 8192; + status->text_state.buffer = malloc(status->text_state.buffer_size); int pipe_read_fd[2]; int pipe_write_fd[2]; From 333dbcbe72b6af95573e374b66ad6ab63f274299 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 14:39:18 -0400 Subject: [PATCH 362/522] Render i3bar blocks --- include/swaybar/ipc.h | 2 +- include/swaybar/status_line.h | 6 +- swaybar/bar.c | 4 +- swaybar/i3bar.c | 120 +++++++++++++++++-- swaybar/ipc.c | 2 +- swaybar/render.c | 209 +++++++++++++++++++++++++++++++--- swaybar/status_line.c | 5 +- 7 files changed, 314 insertions(+), 34 deletions(-) diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 6ea7c4d67..a1696bcf9 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -4,7 +4,7 @@ #include "swaybar/bar.h" void ipc_initialize(struct swaybar *bar, const char *bar_id); -bool handle_ipc_event(struct swaybar *bar); +bool handle_ipc_readable(struct swaybar *bar); void ipc_get_workspaces(struct swaybar *bar); void ipc_send_workspace_command(struct swaybar *bar, const char *ws); diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 3b93e28f1..038985a36 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -38,7 +38,7 @@ struct i3bar_block { struct wl_list link; char *full_text, *short_text, *align; bool urgent; - uint32_t color; + uint32_t *color; int min_width; char *name, *instance; bool separator; @@ -68,8 +68,8 @@ struct status_line { struct status_line *status_line_init(char *cmd); void status_line_free(struct status_line *status); -bool handle_status_readable(struct status_line *status); -int i3bar_readable(struct status_line *status); +bool status_handle_readable(struct status_line *status); +bool i3bar_handle_readable(struct status_line *status); void status_error(struct status_line *status, const char *text); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index f743236c2..fb4170954 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -308,14 +308,14 @@ static void display_in(int fd, short mask, void *_bar) { static void ipc_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; - if (handle_ipc_event(bar)) { + if (handle_ipc_readable(bar)) { render_all_frames(bar); } } static void status_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; - if (handle_status_readable(bar->status)) { + if (status_handle_readable(bar->status)) { render_all_frames(bar); } } diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 5be348b24..41b711649 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -5,11 +7,109 @@ #include "swaybar/config.h" #include "swaybar/status_line.h" -static void i3bar_parse_json(struct status_line *status, const char *text) { - wlr_log(L_DEBUG, "got json: %s", text); +static void i3bar_block_free(struct i3bar_block *block) { + if (!block) { + return; + } + wl_list_remove(&block->link); + free(block->full_text); + free(block->short_text); + free(block->align); + free(block->name); + free(block->instance); + free(block->color); } -int i3bar_readable(struct status_line *status) { +static bool i3bar_parse_json(struct status_line *status, const char *text) { + struct i3bar_block *block, *tmp; + wl_list_for_each_safe(block, tmp, &status->blocks, link) { + i3bar_block_free(block); + } + json_object *results = json_tokener_parse(text); + if (!results) { + status_error(status, "[failed to parse i3bar json]"); + return false; + } + if (json_object_array_length(results) < 1) { + return true; + } + for (size_t 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 i3bar_block *block = calloc(1, sizeof(struct i3bar_block)); + block->full_text = full_text ? + strdup(json_object_get_string(full_text)) : NULL; + block->short_text = short_text ? + strdup(json_object_get_string(short_text)) : NULL; + if (color) { + block->color = malloc(sizeof(uint32_t)); + *block->color = parse_color(json_object_get_string(color)); + } + if (min_width) { + json_type type = json_object_get_type(min_width); + if (type == json_type_int) { + block->min_width = json_object_get_int(min_width); + } else if (type == json_type_string) { + /* the width will be calculated when rendering */ + block->min_width = 0; + } + } + block->align = strdup(align ? json_object_get_string(align) : "left"); + block->urgent = urgent ? json_object_get_int(urgent) : false; + block->name = name ? strdup(json_object_get_string(name)) : NULL; + block->instance = instance ? + strdup(json_object_get_string(instance)) : NULL; + if (markup) { + block->markup = false; + const char *markup_str = json_object_get_string(markup); + if (strcmp(markup_str, "pango") == 0) { + block->markup = true; + } + } + block->separator = separator ? json_object_get_int(separator) : true; + block->separator_block_width = separator_block_width ? + json_object_get_int(separator_block_width) : 9; + // Airblader features + block->background = background ? + parse_color(json_object_get_string(background)) : 0; + block->border = border ? + parse_color(json_object_get_string(border)) : 0; + block->border_top = border_top ? json_object_get_int(border_top) : 1; + block->border_bottom = border_bottom ? + json_object_get_int(border_bottom) : 1; + block->border_left = border_left ? json_object_get_int(border_left) : 1; + block->border_right = border_right ? + json_object_get_int(border_right) : 1; + wl_list_insert(&status->blocks, &block->link); + } + return true; +} + +bool i3bar_handle_readable(struct status_line *status) { struct i3bar_protocol_state *state = &status->i3bar_state; char *cur = &state->buffer[state->buffer_index]; @@ -30,7 +130,7 @@ int i3bar_readable(struct status_line *status) { state->buffer = new_buffer; } - int handled = 0; + bool redraw = false; while (*cur) { if (state->nodes[state->depth] == JSON_NODE_STRING) { if (!state->escape && *cur == '"') { @@ -44,7 +144,7 @@ int i3bar_readable(struct status_line *status) { if (state->depth > sizeof(state->nodes) / sizeof(state->nodes[0])) { status_error(status, "[i3bar json too deep]"); - return -1; + return false; } state->nodes[state->depth] = JSON_NODE_ARRAY; if (state->depth == 1) { @@ -54,18 +154,18 @@ int i3bar_readable(struct status_line *status) { case ']': if (state->nodes[state->depth] != JSON_NODE_ARRAY) { status_error(status, "[failed to parse i3bar json]"); - return -1; + return false; } --state->depth; if (state->depth == 0) { // cur[1] is valid since cur[0] != '\0' char p = cur[1]; cur[1] = '\0'; - i3bar_parse_json(status, state->current_node); + redraw = i3bar_parse_json( + status, state->current_node) || redraw; cur[1] = p; memmove(state->buffer, cur, state->buffer_size - (cur - state->buffer)); - ++handled; cur = state->buffer; state->current_node = cur + 1; } @@ -75,7 +175,7 @@ int i3bar_readable(struct status_line *status) { if (state->depth > sizeof(state->nodes) / sizeof(state->nodes[0])) { status_error(status, "[i3bar json too deep]"); - return -1; + return false; } state->nodes[state->depth] = JSON_NODE_STRING; break; @@ -84,5 +184,5 @@ int i3bar_readable(struct status_line *status) { ++cur; } state->buffer_index = cur - state->buffer; - return handled; + return redraw; } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 64583df06..ed5d9a315 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -323,7 +323,7 @@ void ipc_initialize(struct swaybar *bar, const char *bar_id) { IPC_SUBSCRIBE, subscribe, &len)); } -bool handle_ipc_event(struct swaybar *bar) { +bool handle_ipc_readable(struct swaybar *bar) { struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); if (!resp) { return false; diff --git a/swaybar/render.c b/swaybar/render.c index c23587245..3ad6d5d71 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -18,10 +18,33 @@ static const int ws_horizontal_padding = 5; static const double ws_vertical_padding = 1.5; static const double border_width = 1; +static uint32_t render_status_line_error(cairo_t *cairo, + struct swaybar_config *config, const char *error, + double *x, uint32_t width, uint32_t height) { + if (!error) { + return 0; + } + cairo_set_source_u32(cairo, 0xFF0000FF); + static const int margin = 3; + int text_width, text_height; + get_text_size(cairo, config->font, + &text_width, &text_height, 1, false, "%s", error); + uint32_t ideal_height = text_height + ws_vertical_padding * 2; + if (height < ideal_height) { + return ideal_height; + } + *x -= text_width + margin; + double text_y = height / 2.0 - text_height / 2.0; + cairo_move_to(cairo, *x, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, false, "%s", error); + *x -= margin; + return ideal_height; +} + static uint32_t render_status_line_text(cairo_t *cairo, - struct swaybar_config *config, struct status_line *status, - bool focused, uint32_t width, uint32_t height) { - if (!status->text) { + struct swaybar_config *config, const char *text, + bool focused, double *x, uint32_t width, uint32_t height) { + if (!text) { return 0; } cairo_set_source_u32(cairo, focused ? @@ -29,38 +52,193 @@ static uint32_t render_status_line_text(cairo_t *cairo, static const int margin = 3; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, config->pango_markup, "%s", status->text); + 1, config->pango_markup, "%s", text); uint32_t ideal_height = text_height + ws_vertical_padding * 2; if (height < ideal_height) { return ideal_height; } + *x -= text_width + margin; double text_y = height / 2.0 - text_height / 2.0; - cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, config->pango_markup, - "%s", status->text); + cairo_move_to(cairo, *x, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text); + *x -= margin; + return ideal_height; +} + +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 uint32_t render_status_block(cairo_t *cairo, + struct swaybar_config *config, struct i3bar_block *block, + double *x, uint32_t height, bool focused, bool edge) { + static const int margin = 3; + if (!block->full_text || !*block->full_text) { + return 0; + } + + int text_width, text_height; + get_text_size(cairo, config->font, &text_width, &text_height, + 1, block->markup, "%s", block->full_text); + int width = text_width; + if (width < block->min_width) { + width = block->min_width; + } + double block_width = width; + uint32_t ideal_height = text_height + ws_vertical_padding * 2; + if (height < ideal_height) { + return ideal_height; + } + + *x -= width; + if (block->border && block->border_left > 0) { + *x -= (block->border_left + margin); + block_width += block->border_left + margin; + } + if (block->border && block->border_right > 0) { + *x -= (block->border_right + margin); + block_width += block->border_right + margin; + } + + int sep_width; + if (!edge) { + if (config->sep_symbol) { + int _height; + get_text_size(cairo, config->font, &sep_width, &_height, + 1, false, "%s", config->sep_symbol); + uint32_t _ideal_height = _height + ws_vertical_padding * 2; + if (height < _ideal_height) { + return _height; + } + if (sep_width > block->separator_block_width) { + block->separator_block_width = sep_width + margin * 2; + } + } + *x -= block->separator_block_width; + } else { + *x -= margin; + } + + // TODO: Create hotspot here + + double pos = *x; + if (block->background) { + cairo_set_source_u32(cairo, block->background); + cairo_rectangle(cairo, pos - 0.5, 1, block_width, height); + cairo_fill(cairo); + } + + if (block->border && block->border_top > 0) { + render_sharp_line(cairo, block->border, + pos - 0.5, 1, block_width, block->border_top); + } + if (block->border && block->border_bottom > 0) { + render_sharp_line(cairo, block->border, + pos - 0.5, height - 1 - block->border_bottom, + block_width, block->border_bottom); + } + if (block->border != 0 && block->border_left > 0) { + render_sharp_line(cairo, block->border, + pos - 0.5, 1, block->border_left, height); + pos += block->border_left + margin; + } + + double offset = 0; + if (strncmp(block->align, "left", 5) == 0) { + offset = pos; + } else if (strncmp(block->align, "right", 5) == 0) { + offset = pos + width - text_width; + } else if (strncmp(block->align, "center", 6) == 0) { + offset = pos + (width - text_width) / 2; + } + cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); + uint32_t color = block->color ? *block->color : config->colors.statusline; + cairo_set_source_u32(cairo, color); + pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text); + pos += width; + + if (block->border && block->border_right > 0) { + pos += margin; + render_sharp_line(cairo, block->border, + pos - 0.5, 1, block->border_right, height); + pos += block->border_right; + } + + if (!edge && block->separator) { + if (focused) { + cairo_set_source_u32(cairo, config->colors.focused_separator); + } else { + cairo_set_source_u32(cairo, config->colors.separator); + } + if (config->sep_symbol) { + offset = pos + (block->separator_block_width - sep_width) / 2; + cairo_move_to(cairo, offset, margin); + pango_printf(cairo, config->font, 1, false, + "%s", config->sep_symbol); + } else { + cairo_set_line_width(cairo, 1); + cairo_move_to(cairo, + pos + block->separator_block_width / 2, margin); + cairo_line_to(cairo, + pos + block->separator_block_width / 2, height - margin); + cairo_stroke(cairo); + } + } return ideal_height; } static uint32_t render_status_line_i3bar(cairo_t *cairo, struct swaybar_config *config, struct status_line *status, - bool focused, uint32_t width, uint32_t height) { - // TODO - return 0; + bool focused, double *x, uint32_t width, uint32_t height) { + struct i3bar_block *block; + uint32_t max_height = 0; + bool edge = true; + wl_list_for_each_reverse(block, &status->blocks, link) { + uint32_t h = render_status_block(cairo, config, + block, x, height, focused, edge); + max_height = h > max_height ? h : max_height; + edge = false; + } + return max_height; } static uint32_t render_status_line(cairo_t *cairo, struct swaybar_config *config, struct status_line *status, - bool focused, uint32_t width, uint32_t height) { + bool focused, double *x, uint32_t width, uint32_t height) { switch (status->protocol) { + case PROTOCOL_ERROR: + return render_status_line_error(cairo, + config, status->text, x, width, height); case PROTOCOL_TEXT: return render_status_line_text(cairo, - config, status, focused, width, height); + config, status->text, focused, x, width, height); case PROTOCOL_I3BAR: return render_status_line_i3bar(cairo, - config, status, focused, width, height); - default: + config, status, focused, x, width, height); + case PROTOCOL_UNDEF: return 0; } + return 0; } static uint32_t render_binding_mode_indicator(cairo_t *cairo, @@ -211,9 +389,10 @@ static uint32_t render_to_cairo(cairo_t *cairo, cairo, config, config->mode, x, output->height); max_height = h > max_height ? h : max_height; } + x = output->width; if (bar->status) { uint32_t h = render_status_line(cairo, config, bar->status, - output->focused, output->width, output->height); + output->focused, &x, output->width, output->height); max_height = h > max_height ? h : max_height; } diff --git a/swaybar/status_line.c b/swaybar/status_line.c index c94ac6d4e..cc7e217f0 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -17,13 +17,13 @@ void status_error(struct status_line *status, const char *text) { status->text = text; } -bool handle_status_readable(struct status_line *status) { +bool status_handle_readable(struct status_line *status) { char *line; switch (status->protocol) { case PROTOCOL_ERROR: return false; case PROTOCOL_I3BAR: - if (i3bar_readable(status) > 0) { + if (i3bar_handle_readable(status) > 0) { return true; } break; @@ -66,6 +66,7 @@ bool handle_status_readable(struct status_line *status) { status->protocol = PROTOCOL_I3BAR; free(status->text_state.buffer); + wl_list_init(&status->blocks); status->i3bar_state.buffer_size = 4096; status->i3bar_state.buffer = malloc(status->i3bar_state.buffer_size); From 0cbd2a4f492b758f495af9f3ec4899dffe8d57d4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 14:58:30 -0400 Subject: [PATCH 363/522] Send click events for i3bar blocks --- include/swaybar/status_line.h | 8 ++++--- swaybar/i3bar.c | 22 ++++++++++++++++++ swaybar/render.c | 42 +++++++++++++++++++++++++---------- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 038985a36..3538f49ce 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -67,9 +67,11 @@ struct status_line { }; struct status_line *status_line_init(char *cmd); -void status_line_free(struct status_line *status); -bool status_handle_readable(struct status_line *status); -bool i3bar_handle_readable(struct status_line *status); void status_error(struct status_line *status, const char *text); +bool status_handle_readable(struct status_line *status); +void status_line_free(struct status_line *status); +bool i3bar_handle_readable(struct status_line *status); +void i3bar_block_send_click(struct status_line *status, + struct i3bar_block *block, int x, int y, uint32_t button); #endif diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 41b711649..5e98c4aa8 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -186,3 +186,25 @@ bool i3bar_handle_readable(struct status_line *status) { state->buffer_index = cur - state->buffer; return redraw; } + +void i3bar_block_send_click(struct status_line *status, + struct i3bar_block *block, int x, int y, uint32_t button) { + wlr_log(L_DEBUG, "block %s clicked", block->name ? block->name : "(nil)"); + if (!block->name || !status->i3bar_state.click_events) { + return; + } + + struct json_object *event_json = json_object_new_object(); + json_object_object_add(event_json, "name", + json_object_new_string(block->name)); + if (block->instance) { + json_object_object_add(event_json, "instance", + json_object_new_string(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)); + dprintf(status->write_fd, "%s\n", json_object_to_json_string(event_json)); + json_object_put(event_json); +} diff --git a/swaybar/render.c b/swaybar/render.c index 3ad6d5d71..a5039a2e5 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -89,9 +89,17 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, } } +static void block_hotspot_callback(struct swaybar_output *output, + int x, int y, uint32_t button, void *data) { + struct i3bar_block *block = data; + struct status_line *status = output->bar->status; + i3bar_block_send_click(status, block, x, y, button); +} + static uint32_t render_status_block(cairo_t *cairo, - struct swaybar_config *config, struct i3bar_block *block, - double *x, uint32_t height, bool focused, bool edge) { + struct swaybar_config *config, struct swaybar_output *output, + struct i3bar_block *block, double *x, + uint32_t height, bool focused, bool edge) { static const int margin = 3; if (!block->full_text || !*block->full_text) { return 0; @@ -139,7 +147,15 @@ static uint32_t render_status_block(cairo_t *cairo, *x -= margin; } - // TODO: Create hotspot here + struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); + hotspot->x = *x; + hotspot->y = 0; + hotspot->width = width; + hotspot->height = height; + hotspot->callback = block_hotspot_callback; + hotspot->destroy = free; + hotspot->data = block; + wl_list_insert(&output->hotspots, &hotspot->link); double pos = *x; if (block->background) { @@ -208,13 +224,14 @@ static uint32_t render_status_block(cairo_t *cairo, } static uint32_t render_status_line_i3bar(cairo_t *cairo, - struct swaybar_config *config, struct status_line *status, - bool focused, double *x, uint32_t width, uint32_t height) { + struct swaybar_config *config, struct swaybar_output *output, + struct status_line *status, bool focused, + double *x, uint32_t width, uint32_t height) { struct i3bar_block *block; uint32_t max_height = 0; bool edge = true; wl_list_for_each_reverse(block, &status->blocks, link) { - uint32_t h = render_status_block(cairo, config, + uint32_t h = render_status_block(cairo, config, output, block, x, height, focused, edge); max_height = h > max_height ? h : max_height; edge = false; @@ -223,8 +240,9 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, } static uint32_t render_status_line(cairo_t *cairo, - struct swaybar_config *config, struct status_line *status, - bool focused, double *x, uint32_t width, uint32_t height) { + struct swaybar_config *config, struct swaybar_output *output, + struct status_line *status, bool focused, + double *x, uint32_t width, uint32_t height) { switch (status->protocol) { case PROTOCOL_ERROR: return render_status_line_error(cairo, @@ -233,8 +251,8 @@ static uint32_t render_status_line(cairo_t *cairo, return render_status_line_text(cairo, config, status->text, focused, x, width, height); case PROTOCOL_I3BAR: - return render_status_line_i3bar(cairo, - config, status, focused, x, width, height); + return render_status_line_i3bar(cairo, config, output, status, + focused, x, width, height); case PROTOCOL_UNDEF: return 0; } @@ -344,8 +362,8 @@ static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; hotspot->y = 0; - hotspot->height = height; hotspot->width = width; + hotspot->height = height; hotspot->callback = workspace_hotspot_callback; hotspot->destroy = free; hotspot->data = strdup(name); @@ -391,7 +409,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, } x = output->width; if (bar->status) { - uint32_t h = render_status_line(cairo, config, bar->status, + uint32_t h = render_status_line(cairo, config, output, bar->status, output->focused, &x, output->width, output->height); max_height = h > max_height ? h : max_height; } From b2d871cfe215a82266d01847f4787bbcf8c721c9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 21:21:26 -0400 Subject: [PATCH 364/522] Partially implement move command Works: - move [container|window] to workspace - Note, this should be able to move C_CONTAINER but this is untested - move [workspace] to output [left|right|up|down|] Not implemented yet: - move [left|right|up|down] - move scratchpad - move position --- include/sway/output.h | 2 + include/sway/tree/container.h | 5 + include/sway/tree/layout.h | 12 ++- sway/commands.c | 1 + sway/commands/focus.c | 7 +- sway/commands/move.c | 181 ++++++++++++++++++++++++++++++++++ sway/desktop/output.c | 9 +- sway/input/keyboard.c | 4 +- sway/meson.build | 1 + sway/tree/container.c | 18 ++++ sway/tree/layout.c | 58 ++++++----- sway/tree/output.c | 11 +++ 12 files changed, 268 insertions(+), 41 deletions(-) create mode 100644 sway/commands/move.c diff --git a/include/sway/output.h b/include/sway/output.h index b4980cd8d..b343ecffc 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -36,4 +36,6 @@ void output_damage_whole(struct sway_output *output); void output_damage_whole_view(struct sway_output *output, struct sway_view *view); +struct sway_container *output_by_name(const char *name); + #endif diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 6aa66da02..aff2e58e8 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -84,9 +84,14 @@ struct sway_container { struct { struct wl_signal destroy; + // Raised after the tree updates, but before arrange_windows + // Passed the previous parent + struct wl_signal reparent; } events; }; +const char *container_type_to_str(enum sway_container_type type); + // TODO only one container create function and pass the type? struct sway_container *container_output_create( struct sway_output *sway_output); diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 0a904c4b5..e1034657f 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -11,9 +11,6 @@ enum movement_direction { MOVE_DOWN, MOVE_PARENT, MOVE_CHILD, - MOVE_NEXT, - MOVE_PREV, - MOVE_FIRST }; struct sway_container; @@ -32,7 +29,8 @@ struct sway_root { void layout_init(void); -void container_add_child(struct sway_container *parent, struct sway_container *child); +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); @@ -44,7 +42,11 @@ struct sway_container *container_reap_empty(struct sway_container *container); void container_move_to(struct sway_container* container, struct sway_container* destination); -enum sway_container_layout container_get_default_layout(struct sway_container *output); +void container_move(struct sway_container *container, + enum movement_direction dir, int move_amt); + +enum sway_container_layout container_get_default_layout( + struct sway_container *output); void container_sort_workspaces(struct sway_container *output); diff --git a/sway/commands.c b/sway/commands.c index 905442208..b6af3d1a3 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -162,6 +162,7 @@ static struct cmd_handler command_handlers[] = { { "focus", cmd_focus }, { "kill", cmd_kill }, { "layout", cmd_layout }, + { "move", cmd_move }, { "reload", cmd_reload }, }; diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 64f079f4e..0a521b9e6 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -20,10 +20,6 @@ static bool parse_movement_direction(const char *name, *out = MOVE_PARENT; } else if (strcasecmp(name, "child") == 0) { *out = MOVE_CHILD; - } else if (strcasecmp(name, "next") == 0) { - *out = MOVE_NEXT; - } else if (strcasecmp(name, "prev") == 0) { - *out = MOVE_PREV; } else { return false; } @@ -51,7 +47,8 @@ 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); + 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/move.c b/sway/commands/move.c new file mode 100644 index 000000000..222ef3148 --- /dev/null +++ b/sway/commands/move.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include "sway/commands.h" +#include "sway/input/seat.h" +#include "sway/output.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" +#include "sway/tree/workspace.h" +#include "stringop.h" +#include "list.h" + +static const char* expected_syntax = + "Expected 'move <[px] px>' or " + "'move to workspace ' or " + "'move to output ' or " + "'move position mouse'"; + +static struct sway_container *output_in_direction(const char *direction, + struct wlr_output *reference, int ref_ox, int ref_oy) { + int ref_lx = ref_ox + reference->lx, + ref_ly = ref_oy + reference->ly; + struct { + char *name; + enum wlr_direction direction; + } names[] = { + { "up", WLR_DIRECTION_UP }, + { "down", WLR_DIRECTION_DOWN }, + { "left", WLR_DIRECTION_LEFT }, + { "right", WLR_DIRECTION_RIGHT }, + }; + for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); ++i) { + if (strcasecmp(names[i].name, direction) == 0) { + struct wlr_output *adjacent = wlr_output_layout_adjacent_output( + root_container.sway_root->output_layout, + names[i].direction, reference, ref_lx, ref_ly); + if (adjacent) { + struct sway_output *sway_output = adjacent->data; + return sway_output->swayc; + } + break; + } + } + return output_by_name(direction); +} + +static struct cmd_results *cmd_move_container(struct sway_container *current, + int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "move container/window", + EXPECTED_AT_LEAST, 4))) { + return error; + } else if (strcasecmp(argv[1], "to") == 0 + && strcasecmp(argv[2], "workspace") == 0) { + // move container to workspace x + if (current->type == C_WORKSPACE) { + // TODO: Wrap children in a container and move that + return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); + } else if (current->type != C_CONTAINER && current->type != C_VIEW) { + return cmd_results_new(CMD_FAILURE, "move", + "Can only move containers and views."); + } + struct sway_container *ws; + const char *num_name = NULL; + char *ws_name = NULL; + if (argc == 5 && strcasecmp(argv[3], "number") == 0) { + // move "container to workspace number x" + num_name = argv[4]; + ws = workspace_by_number(num_name); + } else { + ws_name = join_args(argv + 3, argc - 3); + ws = workspace_by_name(ws_name); + } + if (!ws) { + ws = workspace_create(ws_name ? ws_name : num_name); + } + free(ws_name); + struct sway_container *old_parent = current->parent; + struct sway_container *focus = sway_seat_get_focus_inactive( + config->handler_context.seat, ws); + container_move_to(current, focus); + sway_seat_set_focus(config->handler_context.seat, old_parent); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } else if (strcasecmp(argv[1], "to") == 0 + && strcasecmp(argv[2], "output") == 0) { + if (current->type == C_WORKSPACE) { + // TODO: Wrap children in a container and move that + return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); + } else if (current->type != C_CONTAINER + && current->type != C_VIEW) { + return cmd_results_new(CMD_FAILURE, "move", + "Can only move containers and views."); + } + struct sway_container *source = container_parent(current, C_OUTPUT); + struct sway_container *destination = output_in_direction(argv[3], + source->sway_output->wlr_output, current->x, current->y); + if (!destination) { + return cmd_results_new(CMD_FAILURE, "move workspace", + "Can't find output with name/direction '%s'", argv[3]); + } + struct sway_container *focus = sway_seat_get_focus_inactive( + config->handler_context.seat, destination); + if (!focus) { + // We've never been to this output before + focus = destination->children->items[0]; + } + container_move_to(current, focus); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + return cmd_results_new(CMD_INVALID, "move", expected_syntax); +} + +static struct cmd_results *cmd_move_workspace(struct sway_container *current, + int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) { + return error; + } else if (strcasecmp(argv[1], "to") != 0 + || strcasecmp(argv[2], "output") != 0) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + struct sway_container *source = container_parent(current, C_OUTPUT); + int center_x = current->width / 2 + current->x, + center_y = current->height / 2 + current->y; + struct sway_container *destination = output_in_direction(argv[3], + source->sway_output->wlr_output, center_x, center_y); + if (!destination) { + return cmd_results_new(CMD_FAILURE, "move workspace", + "Can't find output with name/direction '%s'", argv[3]); + } + if (current->type != C_WORKSPACE) { + current = container_parent(current, C_WORKSPACE); + } + container_move_to(current, destination); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *cmd_move(int argc, char **argv) { + struct cmd_results *error = NULL; + int move_amt = 10; + if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { + return error; + } + struct sway_container *current = config->handler_context.current_container; + + if (argc == 2 || (argc == 3 && strcasecmp(argv[2], "px") == 0)) { + char *inv; + move_amt = (int)strtol(argv[1], &inv, 10); + if (*inv != '\0' && strcasecmp(inv, "px") != 0) { + move_amt = 10; + } + } + + if (strcasecmp(argv[0], "left") == 0) { + container_move(current, MOVE_LEFT, move_amt); + } else if (strcasecmp(argv[0], "right") == 0) { + container_move(current, MOVE_RIGHT, move_amt); + } else if (strcasecmp(argv[0], "up") == 0) { + container_move(current, MOVE_UP, move_amt); + } else if (strcasecmp(argv[0], "down") == 0) { + container_move(current, MOVE_DOWN, move_amt); + } else if (strcasecmp(argv[0], "container") == 0 + || strcasecmp(argv[0], "window") == 0) { + return cmd_move_container(current, argc, argv); + } else if (strcasecmp(argv[0], "workspace") == 0) { + return cmd_move_workspace(current, argc, argv); + } else if (strcasecmp(argv[0], "scratchpad") == 0 + || (strcasecmp(argv[0], "to") == 0 + && strcasecmp(argv[1], "scratchpad") == 0)) { + // TODO: scratchpad + return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); + } else if (strcasecmp(argv[0], "position") == 0) { + // TODO: floating + return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); + } else { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0d706c528..c42658181 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -229,9 +229,12 @@ static void render_output(struct sway_output *output, struct timespec *when, struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *focus = sway_seat_get_focus_inactive(seat, output->swayc); - struct sway_container *workspace = (focus->type == C_WORKSPACE ? - focus : - container_parent(focus, C_WORKSPACE)); + if (!focus) { + // We've never been to this output before + focus = output->swayc->children->items[0]; + } + struct sway_container *workspace = focus->type == C_WORKSPACE ? + focus : container_parent(focus, C_WORKSPACE); struct render_data rdata = { .output = output, diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 996850525..8d22b684d 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -97,8 +97,8 @@ static void keyboard_execute_command(struct sway_keyboard *keyboard, config->handler_context.seat = keyboard->seat_device->sway_seat; struct cmd_results *results = execute_command(binding->command, NULL); if (results->status != CMD_SUCCESS) { - wlr_log(L_DEBUG, "could not run command for binding: %s", - binding->command); + wlr_log(L_DEBUG, "could not run command for binding: %s (%s)", + binding->command, results->error); } free_cmd_results(results); } diff --git a/sway/meson.build b/sway/meson.build index 0cc620ea8..38945b4ca 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -19,6 +19,7 @@ sway_sources = files( 'commands/input.c', 'commands/layout.c', 'commands/mode.c', + 'commands/move.c', 'commands/seat.c', 'commands/seat/attach.c', 'commands/seat/fallback.c', diff --git a/sway/tree/container.c b/sway/tree/container.c index 746dbf1f9..21fe3fb02 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -33,6 +33,23 @@ static list_t *get_bfs_queue() { return bfs_queue; } +const char *container_type_to_str(enum sway_container_type type) { + switch (type) { + case C_ROOT: + return "C_ROOT"; + case C_OUTPUT: + return "C_OUTPUT"; + case C_WORKSPACE: + return "C_WORKSPACE"; + case C_CONTAINER: + return "C_CONTAINER"; + case C_VIEW: + return "C_VIEW"; + default: + return "C_UNKNOWN"; + } +} + 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"); @@ -54,6 +71,7 @@ static struct sway_container *container_create(enum sway_container_type type) { } wl_signal_init(&c->events.destroy); + wl_signal_init(&c->events.reparent); return c; } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce0682dc9..a8941a40f 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -106,8 +106,10 @@ struct sway_container *container_reap_empty(struct sway_container *container) { if (!sway_assert(container, "reaping null container")) { return NULL; } - wlr_log(L_DEBUG, "reaping %p %s", container, container->name); - while (container != &root_container && container->children->length == 0) { + wlr_log(L_DEBUG, "Reaping %p %s '%s'", container, + container_type_to_str(container->type), container->name); + while (container->type != C_ROOT && container->type != C_OUTPUT + && container->children->length == 0) { if (container->type == C_WORKSPACE) { if (!workspace_is_visible(container)) { struct sway_container *parent = container->parent; @@ -138,22 +140,46 @@ struct sway_container *container_remove_child(struct sway_container *child) { return container_reap_empty(parent); } -void container_move_to(struct sway_container* container, - struct sway_container* destination) { +void container_move_to(struct sway_container *container, + struct sway_container *destination) { if (container == destination || container_has_anscestor(container, destination)) { return; } struct sway_container *old_parent = container_remove_child(container); container->width = container->height = 0; - struct sway_container *new_parent = - container_add_sibling(destination, container); + struct sway_container *new_parent; + if (destination->type == C_VIEW) { + new_parent = container_add_sibling(destination, container); + } else { + new_parent = destination; + container_add_child(destination, container); + } + wl_signal_emit(&container->events.reparent, old_parent); + if (container->type == C_WORKSPACE) { + struct sway_seat *seat = sway_input_manager_get_default_seat( + input_manager); + if (old_parent->children->length == 0) { + char *ws_name = workspace_next_name(old_parent->name); + struct sway_container *ws = + container_workspace_create(old_parent, ws_name); + free(ws_name); + sway_seat_set_focus(seat, ws); + } + container_sort_workspaces(new_parent); + sway_seat_set_focus(seat, new_parent); + } if (old_parent) { arrange_windows(old_parent, -1, -1); } arrange_windows(new_parent, -1, -1); } +void container_move(struct sway_container *container, + enum movement_direction dir, int move_amt) { + // TODO +} + enum sway_container_layout container_get_default_layout( struct sway_container *output) { if (config->default_layout != L_NONE) { @@ -521,26 +547,6 @@ static struct sway_container *get_swayc_in_direction_under( } } - if (dir == MOVE_PREV || dir == MOVE_NEXT) { - int focused_idx = index_child(container); - if (focused_idx == -1) { - return NULL; - } else { - int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) % - parent->children->length; - if (desired < 0) { - desired += parent->children->length; - } - return parent->children->items[desired]; - } - } - - // If moving to an adjacent output we need a starting position (since this - // output might border to multiple outputs). - //struct wlc_point abs_pos; - //get_layout_center_position(container, &abs_pos); - - // TODO WLR fullscreen /* if (container->type == C_VIEW && swayc_is_fullscreen(container)) { diff --git a/sway/tree/output.c b/sway/tree/output.c index 7248fd006..2331dc2b6 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -1,3 +1,4 @@ +#include #include "sway/tree/container.h" #include "sway/tree/layout.h" #include "sway/output.h" @@ -37,3 +38,13 @@ struct sway_container *container_output_destroy(struct sway_container *output) { container_destroy(output); return &root_container; } + +struct sway_container *output_by_name(const char *name) { + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *output = root_container.children->items[i]; + if (strcasecmp(output->name, name) == 0){ + return output; + } + } + return NULL; +} From a82c107c7613548a3ae0e75bb951ba57b7d2f22b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 11:44:42 -0400 Subject: [PATCH 365/522] 80col --- sway/commands.c | 14 ++++++------ sway/commands/seat.c | 11 +++++++--- sway/input/input-manager.c | 45 +++++++++++++++++++++++++------------- sway/input/seat.c | 18 ++++++++++----- 4 files changed, 57 insertions(+), 31 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index dc6c867f5..9e83a4011 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -75,20 +75,20 @@ void apply_input_config(struct input_config *input) { input_manager_apply_input_config(input_manager, input); } -void apply_seat_config(struct seat_config *seat) { +void apply_seat_config(struct seat_config *seat_config) { int i; - i = list_seq_find(config->seat_configs, seat_name_cmp, seat->name); + i = list_seq_find(config->seat_configs, seat_name_cmp, seat_config->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; + merge_seat_config(sc, seat_config); + free_seat_config(seat_config); + seat_config = sc; } else { - list_add(config->seat_configs, seat); + list_add(config->seat_configs, seat_config); } - input_manager_apply_seat_config(input_manager, seat); + input_manager_apply_seat_config(input_manager, seat_config); } /* Keep alphabetized */ diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 450796163..819b769cd 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -14,7 +14,8 @@ struct cmd_results *cmd_seat(int argc, char **argv) { 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"); + 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); @@ -28,7 +29,8 @@ struct cmd_results *cmd_seat(int argc, char **argv) { 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"); + return cmd_results_new(CMD_FAILURE, NULL, + "Couldn't allocate config"); } } @@ -41,7 +43,10 @@ struct cmd_results *cmd_seat(int argc, char **argv) { } 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]); + res = + cmd_results_new(CMD_INVALID, + "seat ", "Unknown command %s", + argv[1]); } if (!has_context) { diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index d9d20200f..34d5b4cf7 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -92,7 +92,8 @@ static bool input_has_seat_configuration(struct sway_input_manager *input) { return false; } -static void input_manager_libinput_config_pointer(struct sway_input_device *input_device) { +static void input_manager_libinput_config_pointer( + struct sway_input_device *input_device) { struct wlr_input_device *wlr_device = input_device->wlr_device; struct input_config *ic = input_device->config; struct libinput_device *libinput_device; @@ -102,22 +103,27 @@ static void input_manager_libinput_config_pointer(struct sway_input_device *inpu } libinput_device = wlr_libinput_get_device_handle(wlr_device); - wlr_log(L_DEBUG, "input_manager_libinput_config_pointer(%s)", ic->identifier); + wlr_log(L_DEBUG, "input_manager_libinput_config_pointer(%s)", + ic->identifier); if (ic->accel_profile != INT_MIN) { wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", ic->identifier, ic->accel_profile); - libinput_device_config_accel_set_profile(libinput_device, ic->accel_profile); + libinput_device_config_accel_set_profile(libinput_device, + ic->accel_profile); } if (ic->click_method != INT_MIN) { wlr_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", ic->identifier, ic->click_method); - libinput_device_config_click_set_method(libinput_device, ic->click_method); + libinput_device_config_click_set_method(libinput_device, + ic->click_method); } if (ic->drag_lock != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", + wlr_log(L_DEBUG, + "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", ic->identifier, ic->click_method); - libinput_device_config_tap_set_drag_lock_enabled(libinput_device, ic->drag_lock); + libinput_device_config_tap_set_drag_lock_enabled(libinput_device, + ic->drag_lock); } if (ic->dwt != INT_MIN) { wlr_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", @@ -125,34 +131,43 @@ static void input_manager_libinput_config_pointer(struct sway_input_device *inpu libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); } if (ic->left_handed != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)", + wlr_log(L_DEBUG, + "libinput_config_pointer(%s) left_handed_set_enabled(%d)", ic->identifier, ic->left_handed); - libinput_device_config_left_handed_set(libinput_device, ic->left_handed); + libinput_device_config_left_handed_set(libinput_device, + ic->left_handed); } if (ic->middle_emulation != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", + wlr_log(L_DEBUG, + "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", ic->identifier, ic->middle_emulation); - libinput_device_config_middle_emulation_set_enabled(libinput_device, ic->middle_emulation); + libinput_device_config_middle_emulation_set_enabled(libinput_device, + ic->middle_emulation); } if (ic->natural_scroll != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", + wlr_log(L_DEBUG, + "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", ic->identifier, ic->natural_scroll); - libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, ic->natural_scroll); + libinput_device_config_scroll_set_natural_scroll_enabled( + libinput_device, ic->natural_scroll); } if (ic->pointer_accel != FLT_MIN) { wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", ic->identifier, ic->pointer_accel); - libinput_device_config_accel_set_speed(libinput_device, ic->pointer_accel); + libinput_device_config_accel_set_speed(libinput_device, + ic->pointer_accel); } if (ic->scroll_method != INT_MIN) { wlr_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", ic->identifier, ic->scroll_method); - libinput_device_config_scroll_set_method(libinput_device, ic->scroll_method); + libinput_device_config_scroll_set_method(libinput_device, + ic->scroll_method); } if (ic->send_events != INT_MIN) { wlr_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", ic->identifier, ic->send_events); - libinput_device_config_send_events_set_mode(libinput_device, ic->send_events); + libinput_device_config_send_events_set_mode(libinput_device, + ic->send_events); } if (ic->tap != INT_MIN) { wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", diff --git a/sway/input/seat.c b/sway/input/seat.c index 91a9e32bb..38b617b79 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -49,7 +49,8 @@ static void handle_seat_container_destroy(struct wl_listener *listener, if (is_focus) { // pick next focus seat_set_focus(seat, NULL); - struct sway_container *next = seat_get_focus_inactive(seat, con->parent); + struct sway_container *next = + seat_get_focus_inactive(seat, con->parent); if (next == NULL) { next = con->parent; } @@ -133,7 +134,8 @@ struct sway_seat *seat_create(struct sway_input_manager *input, // init the focus stack wl_list_init(&seat->focus_stack); - container_for_each_descendant_dfs(&root_container, collect_focus_iter, seat); + container_for_each_descendant_dfs(&root_container, + collect_focus_iter, seat); wl_signal_add(&root_container.sway_root->events.new_container, &seat->new_container); @@ -165,7 +167,8 @@ static void seat_configure_keyboard(struct sway_seat *seat, if (!seat_device->keyboard) { sway_keyboard_create(seat, seat_device); } - struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard; + struct wlr_keyboard *wlr_keyboard = + seat_device->input_device->wlr_device->keyboard; sway_keyboard_configure(seat_device->keyboard); wlr_seat_set_keyboard(seat->wlr_seat, seat_device->input_device->wlr_device); @@ -275,7 +278,8 @@ void 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]; + struct sway_container *output_container = + root_container.children->items[i]; struct wlr_output *output = output_container->sway_output->wlr_output; bool result = @@ -379,7 +383,8 @@ void seat_set_focus(struct sway_seat *seat, seat_set_focus_warp(seat, container, true); } -struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { +struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, + struct sway_container *container) { struct sway_seat_container *current = NULL; struct sway_container *parent = NULL; wl_list_for_each(current, &seat->focus_stack, link) { @@ -409,7 +414,8 @@ struct sway_container *seat_get_focus(struct sway_seat *seat) { struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, enum sway_container_type type) { - struct sway_container *focus = seat_get_focus_inactive(seat, &root_container); + struct sway_container *focus = + seat_get_focus_inactive(seat, &root_container); if (focus->type == type) { return focus; } From c507727ad240b978c6e09e3aa9238080ca9a1c81 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 11:53:56 -0400 Subject: [PATCH 366/522] Fix use-after-free with block hotspots --- common/pango.c | 9 ++++++++- sway/tree/layout.c | 4 ++-- swaybar/i3bar.c | 4 +--- swaybar/render.c | 5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/common/pango.c b/common/pango.c index 2ae7883c0..658d2876e 100644 --- a/common/pango.c +++ b/common/pango.c @@ -6,6 +6,7 @@ #include #include #include +#include "log.h" PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text, int32_t scale, bool markup) { @@ -13,7 +14,13 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, PangoAttrList *attrs; if (markup) { char *buf; - pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, NULL); + GError *error = NULL; + if (!sway_assert(pango_parse_markup( + text, -1, 0, &attrs, &buf, NULL, &error), + "pango_parse_markup '%s' -> error %s", text, + error ? error->message : NULL)) { + return NULL; + } pango_layout_set_markup(layout, buf, -1); free(buf); } else { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce0682dc9..e83636609 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -248,8 +248,8 @@ void arrange_windows(struct sway_container *container, 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); - container->width = area->width; - container->height = area->height; + container->width = width = area->width; + container->height = height = area->height; container->x = x = area->x; container->y = y = area->y; wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 5e98c4aa8..46459e248 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -30,9 +30,7 @@ static bool i3bar_parse_json(struct status_line *status, const char *text) { status_error(status, "[failed to parse i3bar json]"); return false; } - if (json_object_array_length(results) < 1) { - return true; - } + wlr_log(L_DEBUG, "Got i3bar json: '%s'", text); for (size_t 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; diff --git a/swaybar/render.c b/swaybar/render.c index a5039a2e5..a62e1d010 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -153,7 +153,7 @@ static uint32_t render_status_block(cairo_t *cairo, hotspot->width = width; hotspot->height = height; hotspot->callback = block_hotspot_callback; - hotspot->destroy = free; + hotspot->destroy = NULL; hotspot->data = block; wl_list_insert(&output->hotspots, &hotspot->link); @@ -227,9 +227,9 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct status_line *status, bool focused, double *x, uint32_t width, uint32_t height) { - struct i3bar_block *block; uint32_t max_height = 0; bool edge = true; + struct i3bar_block *block; wl_list_for_each_reverse(block, &status->blocks, link) { uint32_t h = render_status_block(cairo, config, output, block, x, height, focused, edge); @@ -376,6 +376,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, struct swaybar_output *output) { struct swaybar_config *config = bar->config; + wlr_log(L_DEBUG, "output %p", output); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); if (output->focused) { From e3689dd5a93b4f4ae62637a2b81797335aafdcaf Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 11:57:06 -0400 Subject: [PATCH 367/522] Fixes regarding @emersion's feedback --- sway/commands/move.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index 222ef3148..ab959b770 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -106,7 +106,9 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, // We've never been to this output before focus = destination->children->items[0]; } + struct sway_container *old_parent = current->parent; container_move_to(current, focus); + sway_seat_set_focus(config->handler_context.seat, old_parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } return cmd_results_new(CMD_INVALID, "move", expected_syntax); @@ -149,7 +151,8 @@ struct cmd_results *cmd_move(int argc, char **argv) { char *inv; move_amt = (int)strtol(argv[1], &inv, 10); if (*inv != '\0' && strcasecmp(inv, "px") != 0) { - move_amt = 10; + return cmd_results_new(CMD_FAILURE, "move", + "Invalid distance specified"); } } From 35445b40a273ca1548915e1f17097a45aebbd44c Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 12:16:00 -0400 Subject: [PATCH 368/522] 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(-) diff --git a/include/sway/config.h b/include/sway/config.h index 03b51948c..91f772b5b 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 3a1cf350c..5c3c2c4f8 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 38b617b79..27636c1ec 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; From 22287b42bf323457d779b1023764ade83313b199 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 13:19:58 -0400 Subject: [PATCH 369/522] dont copy input config --- include/sway/input/input-manager.h | 8 ++++++-- sway/input/input-manager.c | 28 +++++++++++++--------------- sway/input/keyboard.c | 2 +- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 8515c7385..8e39a4a7a 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -14,7 +14,6 @@ extern struct sway_input_manager *input_manager; struct sway_input_device { char *identifier; struct wlr_input_device *wlr_device; - struct input_config *config; struct wl_list link; struct wl_listener device_destroy; }; @@ -49,7 +48,12 @@ struct sway_seat *input_manager_get_default_seat( struct sway_seat *input_manager_get_seat(struct sway_input_manager *input, const char *seat_name); -/** Gets the last seat the user interacted with */ +/** + * Gets the last seat the user interacted with + */ struct sway_seat *input_manager_current_seat(struct sway_input_manager *input); +struct input_config *input_device_get_config(struct sway_input_device *device); + + #endif diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 34d5b4cf7..34aed1154 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -95,7 +95,7 @@ static bool input_has_seat_configuration(struct sway_input_manager *input) { static void input_manager_libinput_config_pointer( struct sway_input_device *input_device) { struct wlr_input_device *wlr_device = input_device->wlr_device; - struct input_config *ic = input_device->config; + struct input_config *ic = input_device_get_config(input_device); struct libinput_device *libinput_device; if (!ic || !wlr_input_device_is_libinput(wlr_device)) { @@ -196,7 +196,6 @@ static void handle_device_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&input_device->link); wl_list_remove(&input_device->device_destroy.link); - free_input_config(input_device->config); free(input_device->identifier); free(input_device); } @@ -219,16 +218,6 @@ static void handle_new_input(struct wl_listener *listener, void *data) { wlr_log(L_DEBUG, "adding device: '%s'", input_device->identifier); - // 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, input_device->identifier) == 0) { - free_input_config(input_device->config); - input_device->config = copy_input_config(input_config); - break; - } - } - if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { input_manager_libinput_config_pointer(input_device); } @@ -320,9 +309,6 @@ void 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) { - free_input_config(input_device->config); - input_device->config = copy_input_config(input_config); - if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { input_manager_libinput_config_pointer(input_device); } @@ -410,3 +396,15 @@ struct sway_seat *input_manager_get_default_seat( } return seat; } + +struct input_config *input_device_get_config(struct sway_input_device *device) { + struct input_config *input_config = NULL; + for (int i = 0; i < config->input_configs->length; ++i) { + input_config = config->input_configs->items[i]; + if (strcmp(input_config->identifier, device->identifier) == 0) { + return input_config; + } + } + + return NULL; +} diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 996850525..410686529 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -428,7 +428,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { struct xkb_rule_names rules; memset(&rules, 0, sizeof(rules)); struct input_config *input_config = - keyboard->seat_device->input_device->config; + input_device_get_config(keyboard->seat_device->input_device); struct wlr_input_device *wlr_device = keyboard->seat_device->input_device->wlr_device; From ef50d84be1180a7ddd73e1273ebb77503b3f36c4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 13:53:40 -0400 Subject: [PATCH 370/522] Render blocks the correct order --- swaybar/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaybar/render.c b/swaybar/render.c index a62e1d010..6f3b07889 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -230,7 +230,7 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, uint32_t max_height = 0; bool edge = true; struct i3bar_block *block; - wl_list_for_each_reverse(block, &status->blocks, link) { + wl_list_for_each(block, &status->blocks, link) { uint32_t h = render_status_block(cairo, config, output, block, x, height, focused, edge); max_height = h > max_height ? h : max_height; From c7a6524954578977dd8f806713a258a0947a4951 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 13:56:35 -0400 Subject: [PATCH 371/522] fix segfault --- sway/input/input-manager.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 34aed1154..c3507f651 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -230,11 +230,10 @@ static void handle_new_input(struct wl_listener *listener, void *data) { return; } - struct seat_config *seat_config = seat_get_config(seat); - bool added = false; wl_list_for_each(seat, &input->seats, link) { - bool has_attachment = config && + struct seat_config *seat_config = seat_get_config(seat); + bool has_attachment = seat_config && (seat_config_get_attachment(seat_config, input_device->identifier) || seat_config_get_attachment(seat_config, "*")); @@ -246,6 +245,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { if (!added) { wl_list_for_each(seat, &input->seats, link) { + struct seat_config *seat_config = seat_get_config(seat); if (seat_config && seat_config->fallback == 1) { seat_add_device(seat, input_device); added = true; From 357a4401fa117416f3182a5f91d27b52b114f3ee Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 14:15:40 -0400 Subject: [PATCH 372/522] address feedback --- sway/commands/split.c | 1 + sway/input/seat.c | 1 - sway/tree/container.c | 2 +- sway/tree/layout.c | 5 ++--- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sway/commands/split.c b/sway/commands/split.c index 6df20e88d..fe4013e91 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -76,6 +76,7 @@ struct cmd_results *cmd_split(int argc, char **argv) { strcasecmp(argv[0], "toggle") == 0) { struct sway_container *focused = config->handler_context.current_container; + if (focused->parent->layout == L_VERT) { _do_split(argc - 1, argv + 1, L_HORIZ); } else { diff --git a/sway/input/seat.c b/sway/input/seat.c index a1b1caa84..1fd204d43 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -92,7 +92,6 @@ static void handle_seat_container_destroy(struct wl_listener *listener, struct sway_container *parent = con->parent; struct sway_container *focus = sway_seat_get_focus(seat); - // TODO handle workspace switch in the seat? bool set_focus = focus != NULL && (focus == con || container_has_child(con, focus)) && diff --git a/sway/tree/container.c b/sway/tree/container.c index 41ba973f1..9205d9299 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -424,7 +424,7 @@ bool container_has_anscestor(struct sway_container *descendant, return false; } -bool find_child_func(struct sway_container *con, void *data) { +static bool find_child_func(struct sway_container *con, void *data) { struct sway_container *child = data; return con == child; } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 83e4fe37f..e13c2ac4b 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -101,8 +101,6 @@ void container_add_child(struct sway_container *parent, parent, parent->type, parent->width, parent->height); list_add(parent->children, child); child->parent = parent; - // TODO: set focus for this container? - sway_input_manager_set_focus(input_manager, child); } struct sway_container *container_reap_empty(struct sway_container *container) { @@ -632,7 +630,8 @@ struct sway_container *container_get_in_direction( wrap_candidate = parent->children->items[0]; } if (config->force_focus_wrapping) { - return sway_seat_get_focus_by_type(seat, wrap_candidate, C_VIEW); + return sway_seat_get_focus_by_type(seat, + wrap_candidate, C_VIEW); } } } else { From 2f64ce86c47efb2ee4c0e3a3c2b31307d21404d9 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 2 Apr 2018 14:35:43 -0400 Subject: [PATCH 373/522] Xwayland unmanaged views aren't views anymore --- include/sway/tree/container.h | 4 ++- include/sway/tree/layout.h | 2 +- include/sway/tree/view.h | 10 +++++--- sway/desktop/output.c | 14 +++++------ sway/desktop/xwayland.c | 47 ++++++++++++++++++++++++++++------- sway/input/cursor.c | 11 ++++---- sway/tree/layout.c | 2 +- sway/tree/view.c | 36 +++------------------------ 8 files changed, 67 insertions(+), 59 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index d707df17e..423c0a22b 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -70,7 +70,9 @@ struct sway_container { enum sway_container_layout prev_layout; enum sway_container_layout workspace_layout; - // in output-local coordinates + // For C_ROOT, this has no meaning + // For C_OUTPUT, this is the output position in layout coordinates + // For other types, this is the position in output-local coordinates double x, y; // does not include borders or gaps. double width, height; diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 0a904c4b5..fecf1582a 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -23,7 +23,7 @@ struct sway_root { struct wl_listener output_layout_change; - struct wl_list unmanaged_views; // sway_view::unmanaged_view_link + struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link struct { struct wl_signal new_container; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 4e753b2a1..4b84205ed 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -39,6 +39,13 @@ struct sway_xwayland_surface { int pending_width, pending_height; }; +struct sway_xwayland_unmanaged { + struct wlr_xwayland_surface *wlr_xwayland_surface; + struct wl_list link; + + struct wl_listener destroy; +}; + struct sway_wl_shell_surface { struct sway_view *view; @@ -127,9 +134,6 @@ void view_damage_from(struct sway_view *view); void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); -void view_map_unmanaged(struct sway_view *view, - struct wlr_surface *wlr_surface); - void view_unmap(struct sway_view *view); void view_update_position(struct sway_view *view, double ox, double oy); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6c97ac37c..352f4af33 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -257,15 +257,15 @@ static void render_output(struct sway_output *output, struct timespec *when, container_descendants(workspace, C_VIEW, render_view, &rdata); // render unmanaged views on top - struct sway_view *view; - wl_list_for_each(view, &root_container.sway_root->unmanaged_views, - unmanaged_view_link) { - if (view->type != SWAY_XWAYLAND_VIEW) { + struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; + struct sway_xwayland_unmanaged *sway_surface; + wl_list_for_each(sway_surface, unmanaged, link) { + struct wlr_xwayland_surface *xsurface = + sway_surface->wlr_xwayland_surface; + if (xsurface->surface == NULL) { continue; } - struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - const struct wlr_box view_box = { .x = xsurface->x, .y = xsurface->y, @@ -277,7 +277,7 @@ static void render_output(struct sway_output *output, struct timespec *when, continue; } - render_surface(view->surface, wlr_output, &output->last_frame, + render_surface(xsurface->surface, wlr_output, &output->last_frame, view_box.x - output_box->x, view_box.y - output_box->y, 0); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 39076fabd..bfef68cf3 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -14,6 +14,33 @@ #include "sway/input/input-manager.h" #include "log.h" +static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *sway_surface = + wl_container_of(listener, sway_surface, destroy); + wl_list_remove(&sway_surface->destroy.link); + wl_list_remove(&sway_surface->link); + free(sway_surface); +} + +static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { + struct sway_xwayland_unmanaged *sway_surface = + calloc(1, sizeof(struct sway_xwayland_unmanaged)); + if (!sway_assert(sway_surface, "Failed to allocate surface")) { + return; + } + + sway_surface->wlr_xwayland_surface = xsurface; + + wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); + sway_surface->destroy.notify = unmanaged_handle_destroy; + + wl_list_insert(&root_container.sway_root->xwayland_unmanaged, + &sway_surface->link); + + // TODO: damage tracking +} + + static bool assert_xwayland(struct sway_view *view) { return sway_assert(view->type == SWAY_XWAYLAND_VIEW, "Expected xwayland view!"); @@ -121,13 +148,8 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_view *view = sway_surface->view; // put it back into the tree - if (wlr_xwayland_surface_is_unmanaged(xsurface) || - xsurface->override_redirect) { - view_map_unmanaged(view, xsurface->surface); - } else { - wlr_xwayland_surface_set_maximized(xsurface, true); - view_map(view, xsurface->surface); - } + wlr_xwayland_surface_set_maximized(xsurface, true); + view_map(view, xsurface->surface); } static void handle_request_configure(struct wl_listener *listener, void *data) { @@ -147,12 +169,19 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { listener, server, xwayland_surface); struct wlr_xwayland_surface *xsurface = data; + if (wlr_xwayland_surface_is_unmanaged(xsurface) || + xsurface->override_redirect) { + wlr_log(L_DEBUG, "New xwayland unmanaged surface"); + create_unmanaged(xsurface); + return; + } + wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", - xsurface->title, xsurface->class); + xsurface->title, xsurface->class); struct sway_xwayland_surface *sway_surface = calloc(1, sizeof(struct sway_xwayland_surface)); - if (!sway_assert(sway_surface, "Failed to allocate surface!")) { + if (!sway_assert(sway_surface, "Failed to allocate surface")) { return; } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d608a9cf0..77ab9e311 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -47,14 +47,15 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output, static struct sway_container *container_at_cursor(struct sway_cursor *cursor, struct wlr_surface **surface, double *sx, double *sy) { // check for unmanaged views first - struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; - struct sway_view *view; - wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) { - if (view->type != SWAY_XWAYLAND_VIEW) { + struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; + struct sway_xwayland_unmanaged *sway_surface; + wl_list_for_each_reverse(sway_surface, unmanaged, link) { + struct wlr_xwayland_surface *xsurface = + sway_surface->wlr_xwayland_surface; + if (xsurface->surface == NULL) { continue; } - struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_box box = { .x = xsurface->x, .y = xsurface->y, diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 3fec02a1c..122ea494e 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -57,7 +57,7 @@ void layout_init(void) { root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); root_container.sway_root->output_layout = wlr_output_layout_create(); - wl_list_init(&root_container.sway_root->unmanaged_views); + wl_list_init(&root_container.sway_root->xwayland_unmanaged); wl_signal_init(&root_container.sway_root->events.new_container); root_container.sway_root->output_layout_change.notify = diff --git a/sway/tree/view.c b/sway/tree/view.c index 73e3d4452..8f044621f 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -15,7 +15,6 @@ struct sway_view *view_create(enum sway_view_type type, } view->type = type; view->impl = impl; - wl_list_init(&view->unmanaged_view_link); return view; } @@ -27,10 +26,8 @@ void view_destroy(struct sway_view *view) { if (view->surface != NULL) { view_unmap(view); } - if (view->swayc != NULL) { - container_view_destroy(view->swayc); - } + container_view_destroy(view->swayc); free(view); } @@ -106,15 +103,10 @@ void view_damage_from(struct sway_view *view) { } static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { - struct sway_container *cont = container_parent(view->swayc, C_OUTPUT); + struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - struct wlr_output_layout *output_layout = - root_container.sway_root->output_layout; - struct wlr_box *output_box = wlr_output_layout_get_box(output_layout, - cont->sway_output->wlr_output); - - box->x = output_box->x + view->swayc->x; - box->y = output_box->y + view->swayc->y; + box->x = output->x + view->swayc->x; + box->y = output->y + view->swayc->y; box->width = view->width; box->height = view->height; } @@ -161,23 +153,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { view_update_outputs(view, NULL); } -void view_map_unmanaged(struct sway_view *view, - struct wlr_surface *wlr_surface) { - if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { - return; - } - - view->surface = wlr_surface; - view->swayc = NULL; - - wl_list_insert(&root_container.sway_root->unmanaged_views, - &view->unmanaged_view_link); - - view_damage_whole(view); - // TODO: make this work for unmanaged views - //view_update_outputs(view, NULL); -} - void view_unmap(struct sway_view *view) { if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) { return; @@ -185,9 +160,6 @@ void view_unmap(struct sway_view *view) { view_damage_whole(view); - wl_list_remove(&view->unmanaged_view_link); - wl_list_init(&view->unmanaged_view_link); - container_view_destroy(view->swayc); view->swayc = NULL; From d070244362f7d34bc15418154e52f8c968fbad41 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 15:40:40 -0400 Subject: [PATCH 374/522] fix workspace splits --- sway/commands/split.c | 25 ++----------------------- sway/tree/layout.c | 38 +++++++++++++++++++++----------------- 2 files changed, 23 insertions(+), 40 deletions(-) diff --git a/sway/commands/split.c b/sway/commands/split.c index fe4013e91..ca116aef9 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -25,29 +25,8 @@ static struct cmd_results *_do_split(int argc, char **argv, int layout) { } struct sway_container *focused = config->handler_context.current_container; - - // TODO floating: dont split - - /* Case that focus is on an workspace with 0/1 children.change its layout */ - if (focused->type == C_WORKSPACE && focused->children->length <= 1) { - wlr_log(L_DEBUG, "changing workspace layout"); - container_set_layout(focused, layout); - } else if (focused->type != C_WORKSPACE && - focused->parent->children->length == 1) { - /* Case of no siblings. change parent layout */ - wlr_log(L_DEBUG, "changing container layout"); - container_set_layout(focused->parent, layout); - } else { - // regular case where new split container is build around focused - // container or in case of workspace, container inherits its children - wlr_log(L_DEBUG, - "Adding new container around current focused container"); - wlr_log(L_INFO, "FOCUSED SIZE: %.f %.f", - focused->width, focused->height); - - struct sway_container *parent = container_split(focused, layout); - arrange_windows(parent, -1, -1); - } + struct sway_container *parent = container_split(focused, layout); + arrange_windows(parent, -1, -1); // TODO borders: update borders diff --git a/sway/tree/layout.c b/sway/tree/layout.c index e13c2ac4b..bea15f8aa 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -405,7 +405,12 @@ void apply_vert_layout(struct sway_container *container, wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); - view_set_position(child->sway_view, x, child_y); + if (child->type == C_VIEW) { + view_set_position(child->sway_view, x, child_y); + } else { + child->x = x; + child->y = child_y; + } if (i == end - 1) { double remaining_height = y + height - child_y; @@ -691,34 +696,33 @@ struct sway_container *container_split(struct sway_container *child, wlr_log(L_DEBUG, "creating container %p around %p", cont, child); cont->prev_layout = L_NONE; - cont->layout = layout; cont->width = child->width; cont->height = child->height; cont->x = child->x; cont->y = child->y; - /* Container inherits all of workspaces children, layout and whatnot */ if (child->type == C_WORKSPACE) { + struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); struct sway_container *workspace = child; - // reorder focus - int i; - for (i = 0; i < workspace->children->length; ++i) { - ((struct sway_container *)workspace->children->items[i])->parent = - cont; + bool set_focus = (sway_seat_get_focus(seat) == workspace); + + while (workspace->children->length) { + struct sway_container *ws_child = workspace->children->items[0]; + container_remove_child(ws_child); + container_add_child(cont, ws_child); } - // Swap children - list_t *tmp_list = workspace->children; - workspace->children = cont->children; - cont->children = tmp_list; - // add container to workspace chidren container_add_child(workspace, cont); - // give them proper layouts - cont->layout = workspace->workspace_layout; - cont->prev_layout = workspace->prev_layout; - } else { // Or is built around container + container_set_layout(workspace, layout); + + if (set_focus) { + sway_seat_set_focus(seat, cont); + } + } else { + cont->layout = layout; container_replace_child(child, cont); container_add_child(cont, child); } + return cont; } From d4d9f7a48a2c2c295e599e867e40aa85f9f02df8 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 2 Apr 2018 15:43:04 -0400 Subject: [PATCH 375/522] protocols: remove xdg-shell XML file --- protocols/xdg-shell.xml | 430 ---------------------------------------- 1 file changed, 430 deletions(-) delete mode 100644 protocols/xdg-shell.xml diff --git a/protocols/xdg-shell.xml b/protocols/xdg-shell.xml deleted file mode 100644 index 7bf4ae3a3..000000000 --- a/protocols/xdg-shell.xml +++ /dev/null @@ -1,430 +0,0 @@ - - - - - Copyright © 2008-2013 Kristian Høgsberg - Copyright © 2013 Rafael Antognolli - Copyright © 2013 Jasper St. Pierre - Copyright © 2010-2013 Intel Corporation - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - This interface is implemented by servers that provide - desktop-style user interfaces. - - It allows clients to associate a xdg_surface with - a basic surface. - - - - - The 'current' member of this enum gives the version of the - protocol. Implementations can compare this to the version - they implement using static_assert to ensure the protocol and - implementation versions match. - - - - - - - - - - - Negotiate the unstable version of the interface. This - mechanism is in place to ensure client and server agree on the - unstable versions of the protocol that they speak or exit - cleanly if they don't agree. This request will go away once - the xdg-shell protocol is stable. - - - - - - - Create a shell surface for an existing surface. - - This request gives the surface the role of xdg_surface. If the - surface already has another role, it raises a protocol error. - - Only one shell or popup surface can be associated with a given - surface. - - - - - - - - Create a popup surface for an existing surface. - - This request gives the surface the role of xdg_popup. If the - surface already has another role, it raises a protocol error. - - Only one shell or popup surface can be associated with a given - surface. - - - - - - - - - - - - - - The ping event asks the client if it's still alive. Pass the - serial specified in the event back to the compositor by sending - a "pong" request back with the specified serial. - - Compositors can use this to determine if the client is still - alive. It's unspecified what will happen if the client doesn't - respond to the ping request, or in what timeframe. Clients should - try to respond in a reasonable amount of time. - - - - - - - A client must respond to a ping event with a pong request or - the client may be deemed unresponsive. - - - - - - - - - An interface that may be implemented by a wl_surface, for - implementations that provide a desktop-style user interface. - - It provides requests to treat surfaces like windows, allowing to set - properties like maximized, fullscreen, minimized, and to move and resize - them, and associate metadata like title and app id. - - On the server side the object is automatically destroyed when - the related wl_surface is destroyed. On client side, - xdg_surface.destroy() must be called before destroying - the wl_surface object. - - - - - The xdg_surface interface is removed from the wl_surface object - that was turned into a xdg_surface with - xdg_shell.get_xdg_surface request. The xdg_surface properties, - like maximized and fullscreen, are lost. The wl_surface loses - its role as a xdg_surface. The wl_surface is unmapped. - - - - - - Child surfaces are stacked above their parents, and will be - unmapped if the parent is unmapped too. They should not appear - on task bars and alt+tab. - - - - - - - Set a short title for the surface. - - This string may be used to identify the surface in a task bar, - window list, or other user interface elements provided by the - compositor. - - The string must be encoded in UTF-8. - - - - - - - Set an id for the surface. - - The app id identifies the general class of applications to which - the surface belongs. - - It should be the ID that appears in the new desktop entry - specification, the interface name. - - - - - - - Clients implementing client-side decorations might want to show - a context menu when right-clicking on the decorations, giving the - user a menu that they can use to maximize or minimize the window. - - This request asks the compositor to pop up such a window menu at - the given position, relative to the parent surface. There are - no guarantees as to what the window menu contains. - - Your surface must have focus on the seat passed in to pop up the - window menu. - - - - - - - - - - - Start a pointer-driven move of the surface. - - This request must be used in response to a button press event. - The server may ignore move requests depending on the state of - the surface (e.g. fullscreen or maximized). - - - - - - - - These values are used to indicate which edge of a surface - is being dragged in a resize operation. The server may - use this information to adapt its behavior, e.g. choose - an appropriate cursor image. - - - - - - - - - - - - - - - Start a pointer-driven resizing of the surface. - - This request must be used in response to a button press event. - The server may ignore resize requests depending on the state of - the surface (e.g. fullscreen or maximized). - - - - - - - - - The different state values used on the surface. This is designed for - state values like maximized, fullscreen. It is paired with the - configure event to ensure that both the client and the compositor - setting the state can be synchronized. - - States set in this way are double-buffered. They will get applied on - the next commit. - - Desktop environments may extend this enum by taking up a range of - values and documenting the range they chose in this description. - They are not required to document the values for the range that they - chose. Ideally, any good extensions from a desktop environment should - make its way into standardization into this enum. - - The current reserved ranges are: - - 0x0000 - 0x0FFF: xdg-shell core values, documented below. - 0x1000 - 0x1FFF: GNOME - - - - The surface is maximized. The window geometry specified in the configure - event must be obeyed by the client. - - - - - The surface is fullscreen. The window geometry specified in the configure - event must be obeyed by the client. - - - - - The surface is being resized. The window geometry specified in the - configure event is a maximum; the client cannot resize beyond it. - Clients that have aspect ratio or cell sizing configuration can use - a smaller size, however. - - - - - Client window decorations should be painted as if the window is - active. Do not assume this means that the window actually has - keyboard or pointer focus. - - - - - - - The configure event asks the client to resize its surface. - - The width and height arguments specify a hint to the window - about how its surface should be resized in window geometry - coordinates. The states listed in the event specify how the - width/height arguments should be interpreted. - - A client should arrange a new surface, and then send a - ack_configure request with the serial sent in this configure - event before attaching a new surface. - - If the client receives multiple configure events before it - can respond to one, it is free to discard all but the last - event it received. - - - - - - - - - - - When a configure event is received, a client should then ack it - using the ack_configure request to ensure that the compositor - knows the client has seen the event. - - By this point, the state is confirmed, and the next attach should - contain the buffer drawn for the configure event you are acking. - - - - - - - The window geometry of a window is its "visible bounds" from the - user's perspective. Client-side decorations often have invisible - portions like drop-shadows which should be ignored for the - purposes of aligning, placing and constraining windows. - - The default value is the full bounds of the surface, including any - subsurfaces. Once the window geometry of the surface is set once, - it is not possible to unset it, and it will remain the same until - set_window_geometry is called again, even if a new subsurface or - buffer is attached. - - If responding to a configure event, the window geometry in here - must respect the sizing negotiations specified by the states in - the configure event. - - - - - - - - - - - - - Make the surface fullscreen. - - You can specify an output that you would prefer to be fullscreen. - If this value is NULL, it's up to the compositor to choose which - display will be used to map this surface. - - - - - - - - - - The close event is sent by the compositor when the user - wants the surface to be closed. This should be equivalent to - the user clicking the close button in client-side decorations, - if your application has any... - - This is only a request that the user intends to close your - window. The client may choose to ignore this request, or show - a dialog to ask the user to save their data... - - - - - - - An interface that may be implemented by a wl_surface, for - implementations that provide a desktop-style popups/menus. A popup - surface is a transient surface with an added pointer grab. - - An existing implicit grab will be changed to owner-events mode, - and the popup grab will continue after the implicit grab ends - (i.e. releasing the mouse button does not cause the popup to be - unmapped). - - The popup grab continues until the window is destroyed or a mouse - button is pressed in any other clients window. A click in any of - the clients surfaces is reported as normal, however, clicks in - other clients surfaces will be discarded and trigger the callback. - - The x and y arguments specify the locations of the upper left - corner of the surface relative to the upper left corner of the - parent surface, in surface local coordinates. - - xdg_popup surfaces are always transient for another surface. - - - - - The xdg_surface interface is removed from the wl_surface object - that was turned into a xdg_surface with - xdg_shell.get_xdg_surface request. The xdg_surface properties, - like maximized and fullscreen, are lost. The wl_surface loses - its role as a xdg_surface. The wl_surface is unmapped. - - - - - - The popup_done event is sent out when a popup grab is broken, - that is, when the users clicks a surface that doesn't belong - to the client owning the popup surface. - - - - - - From bddd1b31c6d6dfdbe1111b531d730f35ac8e8487 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 2 Apr 2018 15:47:50 -0400 Subject: [PATCH 376/522] protocols: remove unused XML files --- protocols/desktop-shell.xml | 138 -------------------------------- protocols/gamma-control.xml | 57 ------------- protocols/server-decoration.xml | 94 ---------------------- protocols/swaylock.xml | 18 ----- 4 files changed, 307 deletions(-) delete mode 100644 protocols/desktop-shell.xml delete mode 100644 protocols/gamma-control.xml delete mode 100644 protocols/server-decoration.xml delete mode 100644 protocols/swaylock.xml diff --git a/protocols/desktop-shell.xml b/protocols/desktop-shell.xml deleted file mode 100644 index 581f0c5d3..000000000 --- a/protocols/desktop-shell.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - - - Traditional user interfaces can rely on this interface to define the - foundations of typical desktops. Currently it's possible to set up - background, panels and locking surfaces. - - - - - - - - - - - - - - - - - - - - - The surface set by this request will receive a fake - pointer.enter event during grabs at position 0, 0 and is - expected to set an appropriate cursor image as described by - the grab_cursor event sent just before the enter event. - - - - - - - - - - - - - - - Tell the client we want it to create and set the lock surface, which is - a GUI asking the user to unlock the screen. The lock surface is - announced with 'set_lock_surface'. Whether or not the client actually - implements locking, it MUST send 'unlock' request to let the normal - desktop resume. - - - - - - This event will be sent immediately before a fake enter event on the - grab surface. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Tell the server, that enough desktop elements have been drawn - to make the desktop look ready for use. During start-up, the - server can wait for this request with a black screen before - starting to fade in the desktop, for instance. If the client - parts of a desktop take a long time to initialize, we avoid - showing temporary garbage. - - - - - - - - - - - - - - - - - - - Tell the shell which side of the screen the panel is - located. This is so that new windows do not overlap the panel - and maximized windows maximize properly. - - - - - - - - - Only one client can bind this interface at a time. - - - - - A screensaver surface is normally hidden, and only visible after an - idle timeout. - - - - - - - - diff --git a/protocols/gamma-control.xml b/protocols/gamma-control.xml deleted file mode 100644 index e6e332651..000000000 --- a/protocols/gamma-control.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - Copyright © 2015 Giulio camuffo - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/protocols/server-decoration.xml b/protocols/server-decoration.xml deleted file mode 100644 index 8bc106c7c..000000000 --- a/protocols/server-decoration.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - . - ]]> - - - This interface allows to coordinate whether the server should create - a server-side window decoration around a wl_surface representing a - shell surface (wl_shell_surface or similar). By announcing support - for this interface the server indicates that it supports server - side decorations. - - - - When a client creates a server-side decoration object it indicates - that it supports the protocol. The client is supposed to tell the - server whether it wants server-side decorations or will provide - client-side decorations. - - If the client does not create a server-side decoration object for - a surface the server interprets this as lack of support for this - protocol and considers it as client-side decorated. Nevertheless a - client-side decorated surface should use this protocol to indicate - to the server that it does not want a server-side deco. - - - - - - - - - - - - - This event is emitted directly after binding the interface. It contains - the default mode for the decoration. When a new server decoration object - is created this new object will be in the default mode until the first - request_mode is requested. - - The server may change the default mode at any time. - - - - - - - - - - - - - - - - - - - - - This event is emitted directly after the decoration is created and - represents the base decoration policy by the server. E.g. a server - which wants all surfaces to be client-side decorated will send Client, - a server which wants server-side decoration will send Server. - - The client can request a different mode through the decoration request. - The server will acknowledge this by another event with the same mode. So - even if a server prefers server-side decoration it's possible to force a - client-side decoration. - - The server may emit this event at any time. In this case the client can - again request a different mode. It's the responsibility of the server to - prevent a feedback loop. - - - - - diff --git a/protocols/swaylock.xml b/protocols/swaylock.xml deleted file mode 100644 index c7a102dd7..000000000 --- a/protocols/swaylock.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - The Weston desktop-shell protocol's locking functionality depends more - on the behavior of the compositor than of a screen locking client, so - another protocol is necessary. - - - - - - - - - - - From 32ef182f474dbb40c4bedb69256ca6ec8bd31039 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 20:12:18 -0400 Subject: [PATCH 377/522] cleanup split command handlers --- sway/commands/split.c | 65 ++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/sway/commands/split.c b/sway/commands/split.c index ca116aef9..ab8565a95 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -8,58 +8,33 @@ #include "sway/input/seat.h" #include "log.h" -static struct cmd_results *_do_split(int argc, char **argv, int layout) { - char *name = layout == L_VERT ? "splitv" : - layout == L_HORIZ ? "splith" : "split"; - struct cmd_results *error = NULL; - if (config->reading) { - return cmd_results_new(CMD_FAILURE, name, - "Can't be used in config file."); - } - if (!config->active) { - return cmd_results_new(CMD_FAILURE, name, - "Can only be used when sway is running."); - } - if ((error = checkarg(argc, name, EXPECTED_EQUAL_TO, 0))) { - return error; - } - - struct sway_container *focused = config->handler_context.current_container; - struct sway_container *parent = container_split(focused, layout); +static struct cmd_results *do_split(int layout) { + struct sway_container *con = config->handler_context.current_container; + struct sway_container *parent = container_split(con, layout); arrange_windows(parent, -1, -1); - // TODO borders: update borders - return cmd_results_new(CMD_SUCCESS, NULL, NULL); } struct cmd_results *cmd_split(int argc, char **argv) { struct cmd_results *error = NULL; - if (config->reading) { - return cmd_results_new(CMD_FAILURE, "split", - "Can't be used in config file."); - } - if (!config->active) { - return cmd_results_new(CMD_FAILURE, "split", - "Can only be used when sway is running."); - } if ((error = checkarg(argc, "split", EXPECTED_EQUAL_TO, 1))) { return error; } if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { - _do_split(argc - 1, argv + 1, L_VERT); + do_split(L_VERT); } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { - _do_split(argc - 1, argv + 1, L_HORIZ); + do_split(L_HORIZ); } else if (strcasecmp(argv[0], "t") == 0 || strcasecmp(argv[0], "toggle") == 0) { struct sway_container *focused = config->handler_context.current_container; if (focused->parent->layout == L_VERT) { - _do_split(argc - 1, argv + 1, L_HORIZ); + do_split(L_HORIZ); } else { - _do_split(argc - 1, argv + 1, L_VERT); + do_split(L_VERT); } } else { error = cmd_results_new(CMD_FAILURE, "split", @@ -70,18 +45,32 @@ struct cmd_results *cmd_split(int argc, char **argv) { } struct cmd_results *cmd_splitv(int argc, char **argv) { - return _do_split(argc, argv, L_VERT); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "splitv", EXPECTED_EQUAL_TO, 0))) { + return error; + } + return do_split(L_VERT); } struct cmd_results *cmd_splith(int argc, char **argv) { - return _do_split(argc, argv, L_HORIZ); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "splitv", EXPECTED_EQUAL_TO, 0))) { + return error; + } + return do_split(L_HORIZ); } struct cmd_results *cmd_splitt(int argc, char **argv) { - struct sway_container *focused = config->handler_context.current_container; - if (focused->parent->layout == L_VERT) { - return _do_split(argc, argv, L_HORIZ); + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "splitv", EXPECTED_EQUAL_TO, 0))) { + return error; + } + + struct sway_container *con = config->handler_context.current_container; + + if (con->parent->layout == L_VERT) { + return do_split(L_HORIZ); } else { - return _do_split(argc, argv, L_VERT); + return do_split(L_VERT); } } From 623a08e14fa1434afe5cd0aa0c1b0f5789baa12d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 18:47:40 -0400 Subject: [PATCH 378/522] Identify topmost interactive layer post-arrange --- sway/desktop/layer_shell.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index c18f51c71..a187432bd 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -187,6 +187,28 @@ void arrange_layers(struct sway_output *output) { &usable_area, false); arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &usable_area, false); + + // Find topmost keyboard interactive layer, if such a layer exists + uint32_t layers_above_shell[] = { + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, + ZWLR_LAYER_SHELL_V1_LAYER_TOP, + }; + size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]); + struct sway_layer_surface *layer, *topmost = NULL; + for (size_t i = 0; i < nlayers; ++i) { + wl_list_for_each_reverse(layer, + &output->layers[layers_above_shell[i]], link) { + if (layer->layer_surface->current.keyboard_interactive) { + topmost = layer; + break; + } + } + if (topmost != NULL) { + break; + } + } + + wlr_log(L_DEBUG, "topmost layer: %p", topmost); } static void handle_output_destroy(struct wl_listener *listener, void *data) { From 2c165e1288cbb60f5e677595e35f58a9c56c7010 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 21:01:33 -0400 Subject: [PATCH 379/522] fix more close segfaults --- include/sway/tree/container.h | 2 ++ sway/commands/kill.c | 5 +---- sway/tree/container.c | 37 ++++++++++++++++++++++++++++++++++- sway/tree/layout.c | 2 +- sway/tree/view.c | 2 +- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 464f80c44..5d15f12b4 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -134,6 +134,8 @@ struct sway_container *container_workspace_destroy(struct sway_container *contai struct sway_container *container_output_destroy(struct sway_container *container); struct sway_container *container_view_destroy(struct sway_container *container); +struct sway_container *container_close(struct sway_container *container); + // TODO move to layout.c struct sway_container *container_set_layout(struct sway_container *container, enum sway_container_layout layout); diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 46d6e98e6..811c3e6b4 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -19,11 +19,8 @@ struct cmd_results *cmd_kill(int argc, char **argv) { "Can only kill views and containers with this command"); break; case C_CONTAINER: - con = container_destroy(con); - arrange_windows(con, -1, -1); - break; case C_VIEW: - view_close(con->sway_view); + container_close(con); break; } diff --git a/sway/tree/container.c b/sway/tree/container.c index 4db93ce87..8688edd6a 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -112,10 +112,45 @@ static struct sway_container *_container_destroy(struct sway_container *cont) { struct sway_container *container_destroy(struct sway_container *cont) { struct sway_container *parent = _container_destroy(cont); parent = container_reap_empty(parent); - arrange_windows(&root_container, -1, -1); return parent; } +static void container_close_func(struct sway_container *container, void *data) { + if (container->type == C_VIEW) { + view_close(container->sway_view); + } +} + +struct sway_container *container_close(struct sway_container *con) { + if (!sway_assert(con != NULL, "container_close called with a NULL container")) { + return NULL; + } + + switch (con->type) { + case C_TYPES: + wlr_log(L_ERROR, "tried to close an invalid container"); + break; + case C_ROOT: + wlr_log(L_ERROR, "tried to close the root container"); + break; + case C_OUTPUT: + container_output_destroy(con); + break; + case C_WORKSPACE: + container_workspace_destroy(con); + break; + case C_CONTAINER: + container_for_each_descendant_dfs(con, container_close_func, NULL); + break; + case C_VIEW: + view_close(con->sway_view); + break; + + } + + return con->parent; +} + struct sway_container *container_output_create( struct sway_output *sway_output) { struct wlr_box size; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 95a84d120..b0ce4aaf9 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -110,7 +110,7 @@ struct sway_container *container_reap_empty(struct sway_container *container) { wlr_log(L_DEBUG, "Reaping %p %s '%s'", container, container_type_to_str(container->type), container->name); while (container->type != C_ROOT && container->type != C_OUTPUT - && container->children->length == 0) { + && container->children && container->children->length == 0) { if (container->type == C_WORKSPACE) { if (!workspace_is_visible(container)) { struct sway_container *parent = container->parent; diff --git a/sway/tree/view.c b/sway/tree/view.c index 09c804e41..4e695b5fa 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -84,7 +84,7 @@ struct sway_container *container_view_destroy(struct sway_container *view) { } wlr_log(L_DEBUG, "Destroying view '%s'", view->name); struct sway_container *parent = container_destroy(view); - arrange_windows(parent, -1, -1); + arrange_windows(&root_container, -1, -1); return parent; } From 56078edd65d05c1db1aa5d6e72134499e907063d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 21:07:46 -0400 Subject: [PATCH 380/522] Give exclusive focus to layers above shell layer --- include/sway/input/seat.h | 7 +++++++ sway/desktop/layer_shell.c | 7 ++++++- sway/input/seat.c | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index c780a52b6..137fcd229 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -1,6 +1,7 @@ #ifndef _SWAY_INPUT_SEAT_H #define _SWAY_INPUT_SEAT_H +#include #include #include "sway/input/input-manager.h" @@ -28,6 +29,9 @@ struct sway_seat { bool has_focus; struct wl_list focus_stack; // list of containers in focus order + // If the focused layer is set, views cannot receive keyboard focus + struct wlr_layer_surface *focused_layer; + struct wl_listener focus_destroy; struct wl_listener new_container; @@ -57,6 +61,9 @@ void seat_set_focus(struct sway_seat *seat, struct sway_container *container); void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp); +void seat_set_focus_layer(struct sway_seat *seat, + struct wlr_layer_surface *layer); + struct sway_container *seat_get_focus(struct sway_seat *seat); /** diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index a187432bd..3c7b45f72 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -7,6 +7,8 @@ #include #include #include +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/layers.h" #include "sway/output.h" #include "sway/server.h" @@ -208,7 +210,10 @@ void arrange_layers(struct sway_output *output) { } } - wlr_log(L_DEBUG, "topmost layer: %p", topmost); + struct sway_seat *seat; + wl_list_for_each(seat, &input_manager->seats, link) { + seat_set_focus_layer(seat, topmost ? topmost->layer_surface : NULL); + } } static void handle_output_destroy(struct wl_listener *listener, void *data) { diff --git a/sway/input/seat.c b/sway/input/seat.c index c41f7b2e8..cf519a824 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -352,8 +352,11 @@ void seat_configure_xcursor(struct sway_seat *seat) { void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { - struct sway_container *last_focus = seat_get_focus(seat); + if (seat->focused_layer) { + return; + } + struct sway_container *last_focus = seat_get_focus(seat); if (container && last_focus == container) { return; } @@ -419,6 +422,37 @@ void seat_set_focus(struct sway_seat *seat, seat_set_focus_warp(seat, container, true); } +void seat_set_focus_layer(struct sway_seat *seat, + struct wlr_layer_surface *layer) { + if (!layer) { + seat->focused_layer = NULL; + return; + } + if (seat->focused_layer == layer) { + return; + } + if (seat->has_focus) { + struct sway_container *focus = seat_get_focus(seat); + if (focus->type == C_VIEW) { + wlr_seat_keyboard_clear_focus(seat->wlr_seat); + view_set_activated(focus->sway_view, false); + } + } + if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { + seat->focused_layer = layer; + } + struct wlr_keyboard *keyboard = + wlr_seat_get_keyboard(seat->wlr_seat); + if (keyboard) { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, + layer->surface, keyboard->keycodes, + keyboard->num_keycodes, &keyboard->modifiers); + } else { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, + layer->surface, NULL, 0, NULL); + } +} + struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { return seat_get_focus_by_type(seat, container, C_TYPES); From 0bf3b88019b038f7465b5e333742baacfe0a9eed Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 21:17:16 -0400 Subject: [PATCH 381/522] Give layer shells under the shell layer focus --- sway/input/cursor.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 97b4473c4..9229e92d1 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -180,13 +180,18 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { double sx, sy; struct sway_container *cont = container_at_cursor(cursor, &surface, &sx, &sy); + if (surface && wlr_surface_is_layer_surface(surface)) { + struct wlr_layer_surface *layer = + wlr_layer_surface_from_wlr_surface(surface); + if (layer->current.keyboard_interactive) { + seat_set_focus_layer(cursor->seat, layer); + return; + } + } // 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) { From 2992b72d61933568476e2bf4baf573e714f9ed40 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 22:37:21 -0400 Subject: [PATCH 382/522] change reap container approach --- include/sway/tree/container.h | 4 +-- include/sway/tree/layout.h | 4 ++- sway/tree/container.c | 54 ++++++++++++++++++++++++++++++++--- sway/tree/layout.c | 29 ++----------------- sway/tree/view.c | 10 +++---- 5 files changed, 63 insertions(+), 38 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 5d15f12b4..1286316a5 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -128,11 +128,11 @@ struct sway_container *container_view_create( struct sway_container *sibling, struct sway_view *sway_view); // TODO don't return the parent on destroy -struct sway_container *container_destroy(struct sway_container *container); +void container_destroy(struct sway_container *container); struct sway_container *container_workspace_destroy(struct sway_container *container); struct sway_container *container_output_destroy(struct sway_container *container); -struct sway_container *container_view_destroy(struct sway_container *container); +void container_view_destroy(struct sway_container *container); struct sway_container *container_close(struct sway_container *container); diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 8badb2449..9d33d5616 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -41,7 +41,9 @@ struct sway_container *container_add_sibling(struct sway_container *parent, struct sway_container *container_remove_child(struct sway_container *child); // TODO PRIVATE in tree.h -struct sway_container *container_reap_empty(struct sway_container *container); + +struct sway_container *container_replace_child(struct sway_container *child, + struct sway_container *new_child); // TODO move to tree.h void container_move_to(struct sway_container* container, diff --git a/sway/tree/container.c b/sway/tree/container.c index 8688edd6a..686a52c73 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -109,12 +110,55 @@ static struct sway_container *_container_destroy(struct sway_container *cont) { return parent; } -struct sway_container *container_destroy(struct sway_container *cont) { - struct sway_container *parent = _container_destroy(cont); - parent = container_reap_empty(parent); +static void reap_empty_func(struct sway_container *con, void *data) { + switch (con->type) { + case C_TYPES: + case C_ROOT: + case C_OUTPUT: + // dont reap these + break; + case C_WORKSPACE: + if (!workspace_is_visible(con) && con->children->length == 0) { + container_workspace_destroy(con); + } + break; + case C_CONTAINER: + if (con->children->length == 0) { + _container_destroy(con); + } else if (con->children->length == 1) { + struct sway_container *only_child = con->children->items[0]; + if (only_child->type == C_CONTAINER) { + container_remove_child(only_child); + container_replace_child(con, only_child); + _container_destroy(con); + } + } + case C_VIEW: + break; + } +} + +struct sway_container *container_reap_empty(struct sway_container *container) { + struct sway_container *parent = container->parent; + + container_for_each_descendant_dfs(container, reap_empty_func, NULL); + return parent; } +void container_destroy(struct sway_container *cont) { + if (cont == NULL) { + return; + } + + if (cont->children != NULL && cont->children->length) { + assert(false && "dont destroy containers with children"); + } + + _container_destroy(cont); + container_reap_empty(&root_container); +} + static void container_close_func(struct sway_container *container, void *data) { if (container->type == C_VIEW) { view_close(container->sway_view); @@ -126,6 +170,8 @@ struct sway_container *container_close(struct sway_container *con) { return NULL; } + struct sway_container *parent = con->parent; + switch (con->type) { case C_TYPES: wlr_log(L_ERROR, "tried to close an invalid container"); @@ -148,7 +194,7 @@ struct sway_container *container_close(struct sway_container *con) { } - return con->parent; + return parent; } struct sway_container *container_output_create( diff --git a/sway/tree/layout.c b/sway/tree/layout.c index b0ce4aaf9..79470f985 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -103,32 +103,6 @@ void container_add_child(struct sway_container *parent, child->parent = parent; } -struct sway_container *container_reap_empty(struct sway_container *container) { - if (container == NULL) { - return NULL; - } - wlr_log(L_DEBUG, "Reaping %p %s '%s'", container, - container_type_to_str(container->type), container->name); - while (container->type != C_ROOT && container->type != C_OUTPUT - && container->children && container->children->length == 0) { - if (container->type == C_WORKSPACE) { - if (!workspace_is_visible(container)) { - struct sway_container *parent = container->parent; - container_workspace_destroy(container); - return parent; - } - return container; - } else if (container->type == C_CONTAINER) { - struct sway_container *parent = container->parent; - container_destroy(container); - container = parent; - } else { - container = container->parent; - } - } - return container; -} - struct sway_container *container_remove_child(struct sway_container *child) { struct sway_container *parent = child->parent; for (int i = 0; i < parent->children->length; ++i) { @@ -309,6 +283,8 @@ void arrange_windows(struct sway_container *container, container->children->length); break; case L_VERT: + assert(container); + assert(container->children); apply_vert_layout(container, x, y, width, height, 0, container->children->length); break; @@ -381,6 +357,7 @@ 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) { + assert(container); int i; double scale = 0; // Calculate total height diff --git a/sway/tree/view.c b/sway/tree/view.c index 4e695b5fa..eeadc5d83 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -78,14 +78,12 @@ void view_close(struct sway_view *view) { } } -struct sway_container *container_view_destroy(struct sway_container *view) { +void container_view_destroy(struct sway_container *view) { if (!view) { - return NULL; + return; } wlr_log(L_DEBUG, "Destroying view '%s'", view->name); - struct sway_container *parent = container_destroy(view); - arrange_windows(&root_container, -1, -1); - return parent; + container_destroy(view); } void view_damage_whole(struct sway_view *view) { @@ -164,6 +162,8 @@ void view_unmap(struct sway_view *view) { view->swayc = NULL; view->surface = NULL; + + arrange_windows(&root_container, -1, -1); } void view_update_position(struct sway_view *view, double ox, double oy) { From 20f9d49b824fdb7118eab6f559d45b95ecac9331 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 22:42:44 -0400 Subject: [PATCH 383/522] cleanup --- sway/tree/layout.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 79470f985..487f895f4 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -1,5 +1,4 @@ #define _POSIX_C_SOURCE 200809L -#include #include #include #include @@ -283,8 +282,6 @@ void arrange_windows(struct sway_container *container, container->children->length); break; case L_VERT: - assert(container); - assert(container->children); apply_vert_layout(container, x, y, width, height, 0, container->children->length); break; @@ -357,7 +354,6 @@ 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) { - assert(container); int i; double scale = 0; // Calculate total height From 33006c4e64c7f12ecb7dc199f0452712a520860b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Apr 2018 23:15:19 -0400 Subject: [PATCH 384/522] dont deallocate in container_close --- sway/tree/container.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 686a52c73..cb407f0e0 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -174,17 +174,9 @@ struct sway_container *container_close(struct sway_container *con) { switch (con->type) { case C_TYPES: - wlr_log(L_ERROR, "tried to close an invalid container"); - break; case C_ROOT: - wlr_log(L_ERROR, "tried to close the root container"); - break; case C_OUTPUT: - container_output_destroy(con); - break; case C_WORKSPACE: - container_workspace_destroy(con); - break; case C_CONTAINER: container_for_each_descendant_dfs(con, container_close_func, NULL); break; From f366ef373e3309cb973c0ae8280c1219da1724fa Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 11:17:34 -0400 Subject: [PATCH 385/522] Fix #1709 --- swaybar/i3bar.c | 5 ++++- swaybar/status_line.c | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 46459e248..ed134a016 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -203,6 +203,9 @@ void i3bar_block_send_click(struct status_line *status, 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)); - dprintf(status->write_fd, "%s\n", json_object_to_json_string(event_json)); + if (dprintf(status->write_fd, "%s\n", + json_object_to_json_string(event_json)) < 0) { + status_error(status, "[failed to write click event]"); + } json_object_put(event_json); } diff --git a/swaybar/status_line.c b/swaybar/status_line.c index cc7e217f0..8afe47073 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -59,7 +59,11 @@ bool status_handle_readable(struct status_line *status) { wlr_log(L_DEBUG, "Enabled click events."); status->i3bar_state.click_events = true; const char *events_array = "[\n"; - write(status->write_fd, events_array, strlen(events_array)); + ssize_t len = strlen(events_array); + if (write(status->write_fd, events_array, len) != len) { + status_error(status, + "[failed to write to status command]"); + } } json_object_put(proto); } From 7afbe9284ff1ca2eece6da1838061cad9ed655e0 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 11:27:27 -0400 Subject: [PATCH 386/522] rename _container_destroy to container_finish --- sway/tree/container.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index cb407f0e0..d9fc61e78 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -77,7 +77,7 @@ struct sway_container *container_create(enum sway_container_type type) { return c; } -static struct sway_container *_container_destroy(struct sway_container *cont) { +static struct sway_container *container_finish(struct sway_container *cont) { if (cont == NULL) { return NULL; } @@ -124,13 +124,13 @@ static void reap_empty_func(struct sway_container *con, void *data) { break; case C_CONTAINER: if (con->children->length == 0) { - _container_destroy(con); + container_finish(con); } else if (con->children->length == 1) { struct sway_container *only_child = con->children->items[0]; if (only_child->type == C_CONTAINER) { container_remove_child(only_child); container_replace_child(con, only_child); - _container_destroy(con); + container_finish(con); } } case C_VIEW: @@ -146,6 +146,7 @@ struct sway_container *container_reap_empty(struct sway_container *container) { return parent; } + void container_destroy(struct sway_container *cont) { if (cont == NULL) { return; @@ -155,7 +156,7 @@ void container_destroy(struct sway_container *cont) { assert(false && "dont destroy containers with children"); } - _container_destroy(cont); + container_finish(cont); container_reap_empty(&root_container); } From b4c5f79725142c78a398a22981392d645bc9d2e9 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 12:25:19 -0400 Subject: [PATCH 387/522] move view and workspace destructors to container.c --- include/sway/tree/container.h | 7 +-- sway/input/seat.c | 3 +- sway/tree/container.c | 83 +++++++++++++++++++++++++++++++---- sway/tree/view.c | 13 +----- sway/tree/workspace.c | 39 ---------------- 5 files changed, 83 insertions(+), 62 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 1286316a5..278505cef 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -128,11 +128,12 @@ struct sway_container *container_view_create( struct sway_container *sibling, struct sway_view *sway_view); // TODO don't return the parent on destroy -void container_destroy(struct sway_container *container); +struct sway_container *container_destroy(struct sway_container *container); + +// TODO make me private +struct sway_container *container_finish(struct sway_container *cont); -struct sway_container *container_workspace_destroy(struct sway_container *container); struct sway_container *container_output_destroy(struct sway_container *container); -void container_view_destroy(struct sway_container *container); struct sway_container *container_close(struct sway_container *container); diff --git a/sway/input/seat.c b/sway/input/seat.c index c41f7b2e8..d752acb83 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -381,7 +381,8 @@ void seat_set_focus_warp(struct sway_seat *seat, if (last_ws) { ipc_event_workspace(last_ws, container, "focus"); if (last_ws->children->length == 0) { - container_workspace_destroy(last_ws); + output_damage_whole(last_ws->parent->sway_output); + container_destroy(last_ws); } } struct sway_container *last_output = last_focus; diff --git a/sway/tree/container.c b/sway/tree/container.c index d9fc61e78..c1ebf4f11 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -77,7 +77,7 @@ struct sway_container *container_create(enum sway_container_type type) { return c; } -static struct sway_container *container_finish(struct sway_container *cont) { +struct sway_container *container_finish(struct sway_container *cont) { if (cont == NULL) { return NULL; } @@ -91,7 +91,7 @@ static struct sway_container *container_finish(struct sway_container *cont) { while (cont->children != NULL && cont->children->length != 0) { struct sway_container *child = cont->children->items[0]; container_remove_child(child); - container_destroy(child); + container_finish(child); } } if (cont->marks) { @@ -109,6 +109,45 @@ static struct sway_container *container_finish(struct sway_container *cont) { free(cont); return parent; } +static struct sway_container *container_workspace_destroy( + struct sway_container *workspace) { + if (!sway_assert(workspace, "cannot destroy null workspace")) { + return NULL; + } + + // Do not destroy this if it's the last workspace on this output + struct sway_container *output = container_parent(workspace, C_OUTPUT); + if (output && output->children->length == 1) { + return NULL; + } + + struct sway_container *parent = workspace->parent; + if (workspace->children->length == 0) { + // destroy the WS if there are no children (TODO check for floating) + wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); + ipc_event_workspace(workspace, NULL, "empty"); + } else { + // Move children to a different workspace on this output + struct sway_container *new_workspace = NULL; + // TODO move floating + for (int i = 0; i < output->children->length; i++) { + if (output->children->items[i] != workspace) { + new_workspace = output->children->items[i]; + break; + } + } + + wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", + workspace->name, new_workspace->name); + for (int i = 0; i < workspace->children->length; i++) { + container_move_to(workspace->children->items[i], new_workspace); + } + } + + container_finish(workspace); + return parent; +} + static void reap_empty_func(struct sway_container *con, void *data) { switch (con->type) { @@ -146,18 +185,46 @@ struct sway_container *container_reap_empty(struct sway_container *container) { return parent; } +static void container_root_finish(struct sway_container *con) { + wlr_log(L_ERROR, "TODO: destroy the root container"); +} -void container_destroy(struct sway_container *cont) { - if (cont == NULL) { - return; +struct sway_container *container_destroy(struct sway_container *con) { + if (con == NULL) { + return NULL; } - if (cont->children != NULL && cont->children->length) { - assert(false && "dont destroy containers with children"); + struct sway_container *anscestor = NULL; + + switch (con->type) { + case C_ROOT: + container_root_finish(con); + break; + case C_OUTPUT: + anscestor = container_output_destroy(con); + break; + case C_WORKSPACE: + anscestor = container_workspace_destroy(con); + break; + case C_CONTAINER: + if (con->children != NULL && con->children->length) { + assert(false && "dont destroy container containers with children"); + } + container_finish(con); + // TODO return parent to arrange maybe? + break; + case C_VIEW: + container_finish(con); + // TODO return parent to arrange maybe? + break; + case C_TYPES: + wlr_log(L_ERROR, "tried to destroy an invalid container"); + break; } - container_finish(cont); container_reap_empty(&root_container); + + return anscestor; } static void container_close_func(struct sway_container *container, void *data) { diff --git a/sway/tree/view.c b/sway/tree/view.c index eeadc5d83..c06924f51 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -27,8 +27,7 @@ void view_destroy(struct sway_view *view) { view_unmap(view); } - container_view_destroy(view->swayc); - free(view); + container_destroy(view->swayc); } const char *view_get_title(struct sway_view *view) { @@ -78,14 +77,6 @@ void view_close(struct sway_view *view) { } } -void container_view_destroy(struct sway_container *view) { - if (!view) { - return; - } - wlr_log(L_DEBUG, "Destroying view '%s'", view->name); - container_destroy(view); -} - void view_damage_whole(struct sway_view *view) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *cont = root_container.children->items[i]; @@ -158,7 +149,7 @@ void view_unmap(struct sway_view *view) { view_damage_whole(view); - container_view_destroy(view->swayc); + container_destroy(view->swayc); view->swayc = NULL; view->surface = NULL; diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 743308844..7d1800096 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -208,45 +208,6 @@ struct sway_container *workspace_create(const char *name) { return new_ws; } -struct sway_container *container_workspace_destroy( - struct sway_container *workspace) { - if (!sway_assert(workspace, "cannot destroy null workspace")) { - return NULL; - } - - // Do not destroy this if it's the last workspace on this output - struct sway_container *output = container_parent(workspace, C_OUTPUT); - if (output && output->children->length == 1) { - return NULL; - } - - struct sway_container *parent = workspace->parent; - if (workspace->children->length == 0) { - // destroy the WS if there are no children (TODO check for floating) - wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); - ipc_event_workspace(workspace, NULL, "empty"); - } else { - // Move children to a different workspace on this output - struct sway_container *new_workspace = NULL; - // TODO move floating - for (int i = 0; i < output->children->length; i++) { - if (output->children->items[i] != workspace) { - new_workspace = output->children->items[i]; - break; - } - } - - wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", - workspace->name, new_workspace->name); - for (int i = 0; i < workspace->children->length; i++) { - container_move_to(workspace->children->items[i], new_workspace); - } - } - - container_destroy(workspace); - return parent; -} - /** * Get the previous or next workspace on the specified output. Wraps around at * the end and beginning. If next is false, the previous workspace is returned, From 09d448ea2df60b7e4504b1ec4728e7f1df0244b7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 12:34:01 -0400 Subject: [PATCH 388/522] unify container destroy functions --- include/sway/tree/container.h | 2 -- sway/config/output.c | 2 +- sway/desktop/output.c | 4 ++-- sway/tree/container.c | 37 +++++++++++++++++++++++++++++++++++ sway/tree/output.c | 36 ---------------------------------- 5 files changed, 40 insertions(+), 41 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 278505cef..c6393dc01 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -133,8 +133,6 @@ struct sway_container *container_destroy(struct sway_container *container); // TODO make me private struct sway_container *container_finish(struct sway_container *cont); -struct sway_container *container_output_destroy(struct sway_container *container); - struct sway_container *container_close(struct sway_container *container); // TODO move to layout.c diff --git a/sway/config/output.c b/sway/config/output.c index b4e56efa1..c4b74ce2c 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -127,7 +127,7 @@ void apply_output_config(struct output_config *oc, struct sway_container *output if (oc && oc->enabled == 0) { wlr_output_layout_remove(root_container.sway_root->output_layout, wlr_output); - container_output_destroy(output); + container_destroy(output); return; } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 10ed1f6d7..a1f89cf9a 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -338,12 +338,12 @@ void output_damage_whole_view(struct sway_output *output, static void damage_handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, damage_destroy); - container_output_destroy(output->swayc); + container_destroy(output->swayc); } static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, destroy); - container_output_destroy(output->swayc); + container_destroy(output->swayc); } static void handle_mode(struct wl_listener *listener, void *data) { diff --git a/sway/tree/container.c b/sway/tree/container.c index c1ebf4f11..1c41bf5da 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -109,6 +109,43 @@ struct sway_container *container_finish(struct sway_container *cont) { free(cont); return parent; } + +static struct sway_container *container_output_destroy(struct sway_container *output) { + if (!sway_assert(output, "cannot destroy null 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) { + struct sway_container *child = output->children->items[0]; + container_remove_child(child); + container_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); + } + } + + wl_list_remove(&output->sway_output->destroy.link); + wl_list_remove(&output->sway_output->mode.link); + wl_list_remove(&output->sway_output->transform.link); + wl_list_remove(&output->sway_output->scale.link); + + wl_list_remove(&output->sway_output->damage_destroy.link); + wl_list_remove(&output->sway_output->damage_frame.link); + + wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); + container_finish(output); + return &root_container; +} + static struct sway_container *container_workspace_destroy( struct sway_container *workspace) { if (!sway_assert(workspace, "cannot destroy null workspace")) { diff --git a/sway/tree/output.c b/sway/tree/output.c index 0509db230..af17b8561 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -4,42 +4,6 @@ #include "sway/output.h" #include "log.h" -struct sway_container *container_output_destroy(struct sway_container *output) { - if (!sway_assert(output, "cannot destroy null 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) { - struct sway_container *child = output->children->items[0]; - container_remove_child(child); - container_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); - } - } - - wl_list_remove(&output->sway_output->destroy.link); - wl_list_remove(&output->sway_output->mode.link); - wl_list_remove(&output->sway_output->transform.link); - wl_list_remove(&output->sway_output->scale.link); - - wl_list_remove(&output->sway_output->damage_destroy.link); - wl_list_remove(&output->sway_output->damage_frame.link); - - wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); - container_destroy(output); - return &root_container; -} - struct sway_container *output_by_name(const char *name) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *output = root_container.children->items[i]; From cba258e16ac4d37841b89f2b6a38e1056acae97b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 12:39:03 -0400 Subject: [PATCH 389/522] move output code out of the tree --- sway/desktop/output.c | 11 +++++++++++ sway/meson.build | 1 - sway/tree/output.c | 15 --------------- 3 files changed, 11 insertions(+), 16 deletions(-) delete mode 100644 sway/tree/output.c diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a1f89cf9a..e60fac5fe 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,16 @@ #include "sway/tree/layout.h" #include "sway/tree/view.h" +struct sway_container *output_by_name(const char *name) { + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *output = root_container.children->items[i]; + if (strcasecmp(output->name, name) == 0){ + return output; + } + } + return NULL; +} + /** * Rotate a child's position relative to a parent. The parent size is (pw, ph), * the child position is (*sx, *sy) and its size is (sw, sh). diff --git a/sway/meson.build b/sway/meson.build index a6a633a09..87d882d27 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -86,7 +86,6 @@ sway_sources = files( 'security.c', 'tree/container.c', 'tree/layout.c', - 'tree/output.c', 'tree/view.c', 'tree/workspace.c', ) diff --git a/sway/tree/output.c b/sway/tree/output.c deleted file mode 100644 index af17b8561..000000000 --- a/sway/tree/output.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include "sway/tree/container.h" -#include "sway/tree/layout.h" -#include "sway/output.h" -#include "log.h" - -struct sway_container *output_by_name(const char *name) { - for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *output = root_container.children->items[i]; - if (strcasecmp(output->name, name) == 0){ - return output; - } - } - return NULL; -} From 5f4761c4f40f5d6ec550ccabaebe0f990b6e8bbc Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 13:08:45 -0400 Subject: [PATCH 390/522] unify workspace create functions --- include/sway/tree/workspace.h | 2 -- sway/commands/move.c | 2 +- sway/commands/workspace.c | 6 ++--- sway/tree/container.c | 47 +++++++++++++++++++++++++++++------ sway/tree/workspace.c | 33 +++--------------------- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 4e4c34505..8d49fefba 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -7,8 +7,6 @@ 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); diff --git a/sway/commands/move.c b/sway/commands/move.c index 644c622bc..7ac5f009a 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -74,7 +74,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, ws = workspace_by_name(ws_name); } if (!ws) { - ws = workspace_create(ws_name ? ws_name : num_name); + ws = container_workspace_create(NULL, ws_name ? ws_name : num_name); } free(ws_name); struct sway_container *old_parent = current->parent; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index aa4096f71..a37028030 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -61,7 +61,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (strcasecmp(argv[0], "number") == 0) { if (!(ws = workspace_by_number(argv[1]))) { char *name = join_args(argv + 1, argc - 1); - ws = workspace_create(name); + ws = container_workspace_create(NULL, name); free(name); } } else if (strcasecmp(argv[0], "next") == 0) { @@ -80,12 +80,12 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { ws = old_workspace; } else if (prev_workspace_name && !(ws = workspace_by_name(prev_workspace_name))) { - ws = workspace_create(prev_workspace_name); + ws = container_workspace_create(NULL, prev_workspace_name); } } else { char *name = join_args(argv, argc); if (!(ws = workspace_by_name(name))) { - ws = workspace_create(name); + ws = container_workspace_create(NULL, name); } free(name); } diff --git a/sway/tree/container.c b/sway/tree/container.c index 1c41bf5da..7ccd43eab 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -110,7 +110,8 @@ struct sway_container *container_finish(struct sway_container *cont) { return parent; } -static struct sway_container *container_output_destroy(struct sway_container *output) { +static struct sway_container *container_output_destroy( + struct sway_container *output) { if (!sway_assert(output, "cannot destroy null output")) { return NULL; } @@ -245,7 +246,8 @@ struct sway_container *container_destroy(struct sway_container *con) { break; case C_CONTAINER: if (con->children != NULL && con->children->length) { - assert(false && "dont destroy container containers with children"); + assert(false && + "dont destroy container containers with children"); } container_finish(con); // TODO return parent to arrange maybe? @@ -271,7 +273,8 @@ static void container_close_func(struct sway_container *container, void *data) { } struct sway_container *container_close(struct sway_container *con) { - if (!sway_assert(con != NULL, "container_close called with a NULL container")) { + if (!sway_assert(con != NULL, + "container_close called with a NULL container")) { return NULL; } @@ -359,12 +362,39 @@ 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")) { - return NULL; +static struct sway_container *workspace_get_initial_output(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) { + struct workspace_output *wso = config->workspace_outputs->items[i]; + if (strcasecmp(wso->workspace, name) == 0) { + // Find output to use if it exists + e = root_container.children->length; + for (i = 0; i < e; ++i) { + parent = root_container.children->items[i]; + if (strcmp(parent->name, wso->output) == 0) { + return parent; + } + } + break; + } } + // Otherwise put it on the focused output + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = + seat_get_focus_inactive(seat, &root_container); + parent = focus; + parent = container_parent(parent, C_OUTPUT); + return parent; +} + +struct sway_container *container_workspace_create(struct sway_container *output, + const char *name) { + if (output == NULL) { + output = workspace_get_initial_output(name); + } + wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); struct sway_container *workspace = container_create(C_WORKSPACE); @@ -380,6 +410,7 @@ struct sway_container *container_workspace_create( container_add_child(output, workspace); container_sort_workspaces(output); notify_new_container(workspace); + return workspace; } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 7d1800096..d5a164103 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -179,35 +179,6 @@ struct sway_container *workspace_by_name(const char *name) { } } -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) { - struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcasecmp(wso->workspace, name) == 0) { - // Find output to use if it exists - e = root_container.children->length; - 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); - } - } - break; - } - } - // Otherwise create a new one - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = - seat_get_focus_inactive(seat, &root_container); - parent = focus; - parent = container_parent(parent, C_OUTPUT); - struct sway_container *new_ws = container_workspace_create(parent, name); - ipc_event_workspace(NULL, new_ws, "init"); - return new_ws; -} - /** * Get the previous or next workspace on the specified output. Wraps around at * the end and beginning. If next is false, the previous workspace is returned, @@ -319,7 +290,9 @@ bool workspace_switch(struct sway_container *workspace) { && active_ws == workspace && prev_workspace_name) { struct sway_container *new_ws = workspace_by_name(prev_workspace_name); - workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); + workspace = new_ws ? + new_ws : + container_workspace_create(NULL, prev_workspace_name); } if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) From fcbcbf34adbcfbfc4107c5e0050639828265e122 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 13:10:51 -0400 Subject: [PATCH 391/522] make container_finish private --- include/sway/tree/container.h | 3 --- sway/tree/container.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index c6393dc01..88ca67e91 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -130,9 +130,6 @@ struct sway_container *container_view_create( // TODO don't return the parent on destroy struct sway_container *container_destroy(struct sway_container *container); -// TODO make me private -struct sway_container *container_finish(struct sway_container *cont); - struct sway_container *container_close(struct sway_container *container); // TODO move to layout.c diff --git a/sway/tree/container.c b/sway/tree/container.c index 7ccd43eab..7cc8caa6c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -77,7 +77,7 @@ struct sway_container *container_create(enum sway_container_type type) { return c; } -struct sway_container *container_finish(struct sway_container *cont) { +static struct sway_container *container_finish(struct sway_container *cont) { if (cont == NULL) { return NULL; } From 065887bb7b25c1cf7d39459c79387a24e600085f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 13:16:23 -0400 Subject: [PATCH 392/522] move container_set_layout to layout.h --- include/sway/tree/container.h | 4 ---- include/sway/tree/layout.h | 5 ++++- sway/tree/container.c | 13 ------------- sway/tree/layout.c | 13 +++++++++++++ 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 88ca67e91..23014dbe6 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -132,10 +132,6 @@ struct sway_container *container_destroy(struct sway_container *container); struct sway_container *container_close(struct sway_container *container); -// TODO move to layout.c -struct sway_container *container_set_layout(struct sway_container *container, - enum sway_container_layout layout); - // TODO rename to container_descendants_for_each() void container_descendants(struct sway_container *root, enum sway_container_type type, diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 9d33d5616..725422c67 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -41,10 +41,13 @@ struct sway_container *container_add_sibling(struct sway_container *parent, struct sway_container *container_remove_child(struct sway_container *child); // TODO PRIVATE in tree.h - struct sway_container *container_replace_child(struct sway_container *child, struct sway_container *new_child); +// TODO move to layout.c +struct sway_container *container_set_layout(struct sway_container *container, + enum sway_container_layout layout); + // TODO move to tree.h void container_move_to(struct sway_container* container, struct sway_container* destination); diff --git a/sway/tree/container.c b/sway/tree/container.c index 7cc8caa6c..a79bc22c4 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -441,19 +441,6 @@ struct sway_container *container_view_create(struct sway_container *sibling, return swayc; } -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_descendants(struct sway_container *root, enum sway_container_type type, void (*func)(struct sway_container *item, void *data), void *data) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 487f895f4..dfcdbb9ce 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -47,6 +47,19 @@ static void output_layout_change_notify(struct wl_listener *listener, arrange_windows(&root_container, -1, -1); } +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 layout_init(void) { root_container.id = 0; // normally assigned in new_swayc() root_container.type = C_ROOT; From 9b567fc37e83ed9f0cbb028fd801a2f2609c79dc Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 13:23:34 -0400 Subject: [PATCH 393/522] clean up container_get_default_layout --- include/sway/tree/layout.h | 3 +-- sway/commands/layout.c | 3 +-- sway/tree/container.c | 2 +- sway/tree/layout.c | 14 ++++++++++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 725422c67..12689375e 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -55,9 +55,8 @@ void container_move_to(struct sway_container* container, void container_move(struct sway_container *container, enum movement_direction dir, int move_amt); -// TODO move to output.c enum sway_container_layout container_get_default_layout( - struct sway_container *output); + struct sway_container *con); // TODO move to output.c void container_sort_workspaces(struct sway_container *output); diff --git a/sway/commands/layout.c b/sway/commands/layout.c index ebab2a48a..4c49a627f 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -28,8 +28,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if (strcasecmp(argv[0], "default") == 0) { container_set_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)); + container_set_layout(parent, container_get_default_layout(parent)); } } else { if (parent->layout != L_TABBED && parent->layout != L_STACKED) { diff --git a/sway/tree/container.c b/sway/tree/container.c index a79bc22c4..64b51db66 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -405,7 +405,7 @@ struct sway_container *container_workspace_create(struct sway_container *output, 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->workspace_layout = workspace->layout; container_add_child(output, workspace); container_sort_workspaces(output); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index dfcdbb9ce..c3cdaae0c 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -168,12 +168,22 @@ void container_move(struct sway_container *container, } enum sway_container_layout container_get_default_layout( - struct sway_container *output) { + struct sway_container *con) { + if (con->type != C_OUTPUT) { + con = container_parent(con, C_OUTPUT); + } + + if (!sway_assert(con != NULL, + "container_get_default_layout must be called on an attached " + " container below the root container")) { + return 0; + } + if (config->default_layout != L_NONE) { return config->default_layout; } else if (config->default_orientation != L_NONE) { return config->default_orientation; - } else if (output->width >= output->height) { + } else if (con->width >= con->height) { return L_HORIZ; } else { return L_VERT; From a514fee1b9ac5a3538d8605ff358593cd53e73a8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 13:24:48 -0400 Subject: [PATCH 394/522] rename workspace_get_initial_output --- sway/tree/container.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 64b51db66..f616af098 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -362,7 +362,7 @@ struct sway_container *container_output_create( return output; } -static struct sway_container *workspace_get_initial_output(const char *name) { +static struct sway_container *get_workspace_initial_output(const char *name) { struct sway_container *parent; // Search for workspace<->output pair int i, e = config->workspace_outputs->length; @@ -392,7 +392,7 @@ static struct sway_container *workspace_get_initial_output(const char *name) { struct sway_container *container_workspace_create(struct sway_container *output, const char *name) { if (output == NULL) { - output = workspace_get_initial_output(name); + output = get_workspace_initial_output(name); } wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); From 1e549230db6b088aae2733e1084c7f953ff88abd Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Tue, 3 Apr 2018 14:37:00 -0400 Subject: [PATCH 395/522] Fix name generation for workspace number --- sway/tree/workspace.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c629f1f17..d6fd7c701 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -87,6 +87,24 @@ char *workspace_next_name(const char *output_name) { continue; } + // If the command is workspace number , isolate the name + if (strncmp(_target, "number ", strlen("number ")) == 0) { + size_t length = strlen(_target) - strlen("number ") + 1; + char *temp = malloc(length); + strncpy(temp, _target + strlen("number "), length - 1); + temp[length - 1] = '\0'; + free(_target); + _target = temp; + wlr_log(L_DEBUG, "Isolated name from workspace number: '%s'", _target); + + // Make sure the workspace number doesn't already exist + if (workspace_by_number(_target)) { + free(_target); + free(dup); + continue; + } + } + // Make sure that the workspace doesn't already exist if (workspace_by_name(_target)) { free(_target); From 1382b66217bbb90326e1b3d332ddd2ec42dd1e12 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 15:23:51 -0400 Subject: [PATCH 396/522] swaybg: set an empty input region --- swaybg/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/swaybg/main.c b/swaybg/main.c index 203082f64..b21415b2a 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -43,6 +43,7 @@ struct swaybg_state { struct wl_output *output; struct wl_surface *surface; + struct wl_region *input_region; struct zwlr_layer_surface_v1 *layer_surface; bool run_display; @@ -204,6 +205,7 @@ static void layer_surface_closed(void *data, struct swaybg_state *state = data; zwlr_layer_surface_v1_destroy(state->layer_surface); wl_surface_destroy(state->surface); + wl_region_destroy(state->input_region); state->run_display = false; } @@ -289,6 +291,9 @@ int main(int argc, const char **argv) { assert(state.surface = wl_compositor_create_surface(state.compositor)); + assert(state.input_region = wl_compositor_create_region(state.compositor)); + wl_surface_set_input_region(state.surface, state.input_region); + state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( state.layer_shell, state.surface, state.output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); From 9b4f8637a93258157245700a4fd4f7e0eefc86a3 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 16:47:06 -0400 Subject: [PATCH 397/522] swaybg: add HiDPI support --- swaybg/main.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/swaybg/main.c b/swaybg/main.c index 203082f64..053225bd8 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -47,6 +47,7 @@ struct swaybg_state { bool run_display; uint32_t width, height; + int32_t scale; struct pool_buffer buffers[2]; struct pool_buffer *current_buffer; }; @@ -74,8 +75,8 @@ static void render_image(struct swaybg_state *state) { cairo_surface_t *image = state->context.image; double width = cairo_image_surface_get_width(image); double height = cairo_image_surface_get_height(image); - int wwidth = state->width; - int wheight = state->height; + int wwidth = state->width * state->scale; + int wheight = state->height * state->scale; switch (state->args->mode) { case BACKGROUND_MODE_STRETCH: @@ -135,8 +136,8 @@ static void render_image(struct swaybg_state *state) { } static void render_frame(struct swaybg_state *state) { - state->current_buffer = get_next_buffer(state->shm, - state->buffers, state->width, state->height); + state->current_buffer = get_next_buffer(state->shm, state->buffers, + state->width * state->scale, state->height * state->scale); cairo_t *cairo = state->current_buffer->cairo; switch (state->args->mode) { @@ -149,6 +150,7 @@ static void render_frame(struct swaybg_state *state) { break; } + wl_surface_set_buffer_scale(state->surface, state->scale); wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); wl_surface_damage(state->surface, 0, 0, state->width, state->height); wl_surface_commit(state->surface); @@ -212,12 +214,42 @@ struct zwlr_layer_surface_v1_listener layer_surface_listener = { .closed = layer_surface_closed, }; +static void output_geometry(void *data, struct wl_output *output, int32_t x, + int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, + const char *make, const char *model, int32_t transform) { + // Who cares +} + +static void output_mode(void *data, struct wl_output *output, uint32_t flags, + int32_t width, int32_t height, int32_t refresh) { + // Who cares +} + +static void output_done(void *data, struct wl_output *output) { + // Who cares +} + +static void output_scale(void *data, struct wl_output *output, int32_t factor) { + struct swaybg_state *state = data; + state->scale = factor; + if (state->run_display) { + render_frame(state); + } +} + +struct wl_output_listener output_listener = { + .geometry = output_geometry, + .mode = output_mode, + .done = output_done, + .scale = output_scale, +}; + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct swaybg_state *state = data; if (strcmp(interface, wl_compositor_interface.name) == 0) { state->compositor = wl_registry_bind(registry, name, - &wl_compositor_interface, 1); + &wl_compositor_interface, 3); } else if (strcmp(interface, wl_shm_interface.name) == 0) { state->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); @@ -225,7 +257,8 @@ static void handle_global(void *data, struct wl_registry *registry, static int output_idx = 0; if (output_idx == state->args->output_idx) { state->output = wl_registry_bind(registry, name, - &wl_output_interface, 1); + &wl_output_interface, 3); + wl_output_add_listener(state->output, &output_listener, state); } output_idx++; } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { @@ -287,6 +320,9 @@ int main(int argc, const char **argv) { wl_display_roundtrip(state.display); assert(state.compositor && state.layer_shell && state.output && state.shm); + // Second roundtrip to get output properties + wl_display_roundtrip(state.display); + assert(state.surface = wl_compositor_create_surface(state.compositor)); state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( From 6929124cef2af533b15e93babb98fcd2fc3df471 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 16:56:12 -0400 Subject: [PATCH 398/522] swaybg: rename w{width,height} to buffer_{width,height} --- swaybg/main.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/swaybg/main.c b/swaybg/main.c index 053225bd8..25a1d73ac 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -75,52 +75,53 @@ static void render_image(struct swaybg_state *state) { cairo_surface_t *image = state->context.image; double width = cairo_image_surface_get_width(image); double height = cairo_image_surface_get_height(image); - int wwidth = state->width * state->scale; - int wheight = state->height * state->scale; + int buffer_width = state->width * state->scale; + int buffer_height = state->height * state->scale; switch (state->args->mode) { case BACKGROUND_MODE_STRETCH: - cairo_scale(cairo, (double)wwidth / width, (double)wheight / height); + cairo_scale(cairo, (double)buffer_width / width, + (double)buffer_height / height); cairo_set_source_surface(cairo, image, 0, 0); break; case BACKGROUND_MODE_FILL: { - double window_ratio = (double)wwidth / wheight; + double window_ratio = (double)buffer_width / buffer_height; double bg_ratio = width / height; if (window_ratio > bg_ratio) { - double scale = (double)wwidth / width; + double scale = (double)buffer_width / width; cairo_scale(cairo, scale, scale); cairo_set_source_surface(cairo, image, - 0, (double)wheight / 2 / scale - height / 2); + 0, (double)buffer_height / 2 / scale - height / 2); } else { - double scale = (double)wheight / height; + double scale = (double)buffer_height / height; cairo_scale(cairo, scale, scale); cairo_set_source_surface(cairo, image, - (double)wwidth / 2 / scale - width / 2, 0); + (double)buffer_width / 2 / scale - width / 2, 0); } break; } case BACKGROUND_MODE_FIT: { - double window_ratio = (double)wwidth / wheight; + double window_ratio = (double)buffer_width / buffer_height; double bg_ratio = width / height; if (window_ratio > bg_ratio) { - double scale = (double)wheight / height; + double scale = (double)buffer_height / height; cairo_scale(cairo, scale, scale); cairo_set_source_surface(cairo, image, - (double)wwidth / 2 / scale - width / 2, 0); + (double)buffer_width / 2 / scale - width / 2, 0); } else { - double scale = (double)wwidth / width; + double scale = (double)buffer_width / width; cairo_scale(cairo, scale, scale); cairo_set_source_surface(cairo, image, - 0, (double)wheight / 2 / scale - height / 2); + 0, (double)buffer_height / 2 / scale - height / 2); } break; } case BACKGROUND_MODE_CENTER: cairo_set_source_surface(cairo, image, - (double)wwidth / 2 - width / 2, - (double)wheight / 2 - height / 2); + (double)buffer_width / 2 - width / 2, + (double)buffer_height / 2 - height / 2); break; case BACKGROUND_MODE_TILE: { cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); From eca4468c2cacd87677f7f5831d8a74f8d811d318 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 17:06:57 -0400 Subject: [PATCH 399/522] fix old todos --- include/sway/tree/container.h | 6 ------ include/sway/tree/layout.h | 9 --------- 2 files changed, 15 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 23014dbe6..f36b4bd11 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -91,12 +91,10 @@ struct sway_container { } events; }; -// TODO make private and use the container-specific create functions struct sway_container *container_create(enum sway_container_type type); const char *container_type_to_str(enum sway_container_type type); -// TODO only one container create function and pass the type? struct sway_container *container_output_create( struct sway_output *sway_output); @@ -123,16 +121,13 @@ struct sway_container *container_workspace_create(struct sway_container *output, * or a container container and are rendered in the order and structure of * how they are attached to the tree. */ -// TODO view containers should be created in a detached state. struct sway_container *container_view_create( struct sway_container *sibling, struct sway_view *sway_view); -// TODO don't return the parent on destroy struct sway_container *container_destroy(struct sway_container *container); struct sway_container *container_close(struct sway_container *container); -// TODO rename to container_descendants_for_each() void container_descendants(struct sway_container *root, enum sway_container_type type, void (*func)(struct sway_container *item, void *data), void *data); @@ -147,7 +142,6 @@ struct sway_container *container_find(struct sway_container *container, /** * Finds a parent container with the given struct sway_containerype. */ -// TODO rename to container_parent_of_type() struct sway_container *container_parent(struct sway_container *container, enum sway_container_type type); diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 12689375e..784dcc9b1 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -29,26 +29,20 @@ struct sway_root { void layout_init(void); -// TODO move to tree.h void container_add_child(struct sway_container *parent, struct sway_container *child); -// TODO move to tree.h struct sway_container *container_add_sibling(struct sway_container *parent, struct sway_container *child); -// TODO move to tree.h struct sway_container *container_remove_child(struct sway_container *child); -// TODO PRIVATE in tree.h struct sway_container *container_replace_child(struct sway_container *child, struct sway_container *new_child); -// TODO move to layout.c struct sway_container *container_set_layout(struct sway_container *container, enum sway_container_layout layout); -// TODO move to tree.h void container_move_to(struct sway_container* container, struct sway_container* destination); @@ -58,17 +52,14 @@ void container_move(struct sway_container *container, enum sway_container_layout container_get_default_layout( struct sway_container *con); -// TODO move to output.c void container_sort_workspaces(struct sway_container *output); void arrange_windows(struct sway_container *container, double width, double height); -// TODO move to container.h struct sway_container *container_get_in_direction(struct sway_container *container, struct sway_seat *seat, enum movement_direction dir); -// TODO move to tree.h struct sway_container *container_split(struct sway_container *child, enum sway_container_layout layout); From 5cd9457247146efe0bcbcae890968acb4716c667 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 18:47:04 -0400 Subject: [PATCH 400/522] Send enter event to layer shell surfaces --- sway/desktop/layer_shell.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 3c7b45f72..663ec7baf 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -278,6 +278,8 @@ static void handle_map(struct wl_listener *listener, void *data) { sway_layer, map); struct sway_output *output = sway_layer->layer_surface->output->data; wlr_output_damage_add_box(output->damage, &sway_layer->geo); + wlr_surface_send_enter(sway_layer->layer_surface->surface, + sway_layer->layer_surface->output); } static void handle_unmap(struct wl_listener *listener, void *data) { From 481a8275c178f81bb2d9927c5047e959fdbc383a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 19:23:59 -0400 Subject: [PATCH 401/522] address feedback --- sway/commands/kill.c | 14 +---- sway/desktop/output.c | 2 +- sway/tree/container.c | 135 +++++++++++++++++++++++------------------- sway/tree/layout.c | 2 +- sway/tree/view.c | 4 +- 5 files changed, 79 insertions(+), 78 deletions(-) diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 811c3e6b4..f3fa52f14 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -10,19 +10,7 @@ struct cmd_results *cmd_kill(int argc, char **argv) { struct sway_container *con = config->handler_context.current_container; - switch (con->type) { - case C_ROOT: - case C_OUTPUT: - case C_WORKSPACE: - case C_TYPES: - return cmd_results_new(CMD_INVALID, NULL, - "Can only kill views and containers with this command"); - break; - case C_CONTAINER: - case C_VIEW: - container_close(con); - break; - } + container_close(con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index e60fac5fe..de5076d8f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -25,7 +25,7 @@ struct sway_container *output_by_name(const char *name) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *output = root_container.children->items[i]; - if (strcasecmp(output->name, name) == 0){ + if (strcasecmp(output->name, name) == 0) { return output; } } diff --git a/sway/tree/container.c b/sway/tree/container.c index f616af098..77c61b3f6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -186,84 +186,97 @@ static struct sway_container *container_workspace_destroy( return parent; } - -static void reap_empty_func(struct sway_container *con, void *data) { - switch (con->type) { - case C_TYPES: - case C_ROOT: - case C_OUTPUT: - // dont reap these - break; - case C_WORKSPACE: - if (!workspace_is_visible(con) && con->children->length == 0) { - container_workspace_destroy(con); - } - break; - case C_CONTAINER: - if (con->children->length == 0) { - container_finish(con); - } else if (con->children->length == 1) { - struct sway_container *only_child = con->children->items[0]; - if (only_child->type == C_CONTAINER) { - container_remove_child(only_child); - container_replace_child(con, only_child); - container_finish(con); - } - } - case C_VIEW: - break; - } -} - -struct sway_container *container_reap_empty(struct sway_container *container) { - struct sway_container *parent = container->parent; - - container_for_each_descendant_dfs(container, reap_empty_func, NULL); - - return parent; -} - static void container_root_finish(struct sway_container *con) { wlr_log(L_ERROR, "TODO: destroy the root container"); } +static bool container_reap_empty(struct sway_container *con) { + switch (con->type) { + case C_ROOT: + case C_OUTPUT: + // dont reap these + break; + case C_WORKSPACE: + if (!workspace_is_visible(con) && con->children->length == 0) { + container_workspace_destroy(con); + return true; + } + break; + case C_CONTAINER: + if (con->children->length == 0) { + container_finish(con); + return true; + } else if (con->children->length == 1) { + struct sway_container *child = con->children->items[0]; + if (child->type == C_CONTAINER) { + container_remove_child(child); + container_replace_child(con, child); + container_finish(con); + return true; + } + } + case C_VIEW: + break; + case C_TYPES: + sway_assert(false, "container_reap_empty called on an invalid " + "container"); + break; + } + + return false; +} + struct sway_container *container_destroy(struct sway_container *con) { if (con == NULL) { return NULL; } - struct sway_container *anscestor = NULL; + struct sway_container *parent = con->parent; switch (con->type) { case C_ROOT: container_root_finish(con); break; case C_OUTPUT: - anscestor = container_output_destroy(con); + // dont try to reap the root after this + container_output_destroy(con); break; case C_WORKSPACE: - anscestor = container_workspace_destroy(con); + // dont try to reap the output after this + container_workspace_destroy(con); break; case C_CONTAINER: - if (con->children != NULL && con->children->length) { - assert(false && - "dont destroy container containers with children"); + if (con->children->length) { + for (int i = 0; i < con->children->length; ++i) { + struct sway_container *child = con->children->items[0]; + container_remove_child(child); + container_add_child(parent, child); + } + container_finish(con); } container_finish(con); - // TODO return parent to arrange maybe? break; case C_VIEW: container_finish(con); - // TODO return parent to arrange maybe? break; case C_TYPES: - wlr_log(L_ERROR, "tried to destroy an invalid container"); + wlr_log(L_ERROR, "container_destroy called on an invalid " + "container"); break; } - container_reap_empty(&root_container); + struct sway_container *tmp = parent; + while (parent) { + tmp = parent->parent; - return anscestor; + if (!container_reap_empty(parent)) { + break; + } + + parent = tmp; + } + + return tmp; } static void container_close_func(struct sway_container *container, void *data) { @@ -274,23 +287,23 @@ static void container_close_func(struct sway_container *container, void *data) { struct sway_container *container_close(struct sway_container *con) { if (!sway_assert(con != NULL, - "container_close called with a NULL container")) { + "container_close called with a NULL container")) { return NULL; } struct sway_container *parent = con->parent; switch (con->type) { - case C_TYPES: - case C_ROOT: - case C_OUTPUT: - case C_WORKSPACE: - case C_CONTAINER: - container_for_each_descendant_dfs(con, container_close_func, NULL); - break; - case C_VIEW: - view_close(con->sway_view); - break; + case C_TYPES: + case C_ROOT: + case C_OUTPUT: + case C_WORKSPACE: + case C_CONTAINER: + container_for_each_descendant_dfs(con, container_close_func, NULL); + break; + case C_VIEW: + view_close(con->sway_view); + break; } @@ -365,8 +378,8 @@ struct sway_container *container_output_create( static struct sway_container *get_workspace_initial_output(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) { + int e = config->workspace_outputs->length; + for (int i = 0; i < config->workspace_outputs->length; ++i) { struct workspace_output *wso = config->workspace_outputs->items[i]; if (strcasecmp(wso->workspace, name) == 0) { // Find output to use if it exists diff --git a/sway/tree/layout.c b/sway/tree/layout.c index c3cdaae0c..3cbbf3b41 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -174,7 +174,7 @@ enum sway_container_layout container_get_default_layout( } if (!sway_assert(con != NULL, - "container_get_default_layout must be called on an attached " + "container_get_default_layout must be called on an attached" " container below the root container")) { return 0; } diff --git a/sway/tree/view.c b/sway/tree/view.c index c06924f51..aa010a403 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -149,12 +149,12 @@ void view_unmap(struct sway_view *view) { view_damage_whole(view); - container_destroy(view->swayc); + struct sway_container *parent = container_destroy(view->swayc); view->swayc = NULL; view->surface = NULL; - arrange_windows(&root_container, -1, -1); + arrange_windows(parent, -1, -1); } void view_update_position(struct sway_view *view, double ox, double oy) { From 035a88e0dc325e8225478632b3d4b02a72fcf29a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 19:32:09 -0400 Subject: [PATCH 402/522] rename container_finish to _container_destroy --- sway/tree/container.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 77c61b3f6..2fd030673 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -77,21 +77,21 @@ struct sway_container *container_create(enum sway_container_type type) { return c; } -static struct sway_container *container_finish(struct sway_container *cont) { +static void _container_destroy(struct sway_container *cont) { if (cont == NULL) { - return NULL; + return; } wl_signal_emit(&cont->events.destroy, cont); struct sway_container *parent = cont->parent; - if (cont->children != NULL) { + if (cont->children != NULL && cont->children->length) { // remove children until there are no more, container_destroy calls // container_remove_child, which removes child from this container - while (cont->children != NULL && cont->children->length != 0) { + while (cont->children != NULL) { struct sway_container *child = cont->children->items[0]; container_remove_child(child); - container_finish(child); + _container_destroy(child); } } if (cont->marks) { @@ -107,7 +107,6 @@ static struct sway_container *container_finish(struct sway_container *cont) { list_free(cont->children); cont->children = NULL; free(cont); - return parent; } static struct sway_container *container_output_destroy( @@ -143,7 +142,7 @@ static struct sway_container *container_output_destroy( wl_list_remove(&output->sway_output->damage_frame.link); wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); - container_finish(output); + _container_destroy(output); return &root_container; } @@ -182,7 +181,7 @@ static struct sway_container *container_workspace_destroy( } } - container_finish(workspace); + _container_destroy(workspace); return parent; } @@ -204,14 +203,14 @@ static bool container_reap_empty(struct sway_container *con) { break; case C_CONTAINER: if (con->children->length == 0) { - container_finish(con); + _container_destroy(con); return true; } else if (con->children->length == 1) { struct sway_container *child = con->children->items[0]; if (child->type == C_CONTAINER) { container_remove_child(child); container_replace_child(con, child); - container_finish(con); + _container_destroy(con); return true; } } @@ -252,12 +251,12 @@ struct sway_container *container_destroy(struct sway_container *con) { container_remove_child(child); container_add_child(parent, child); } - container_finish(con); + _container_destroy(con); } - container_finish(con); + _container_destroy(con); break; case C_VIEW: - container_finish(con); + _container_destroy(con); break; case C_TYPES: wlr_log(L_ERROR, "container_destroy called on an invalid " From c0554d23d3d89b92b6a871807771b2c2e1f29f61 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 19:34:56 -0400 Subject: [PATCH 403/522] Fix rendering with multiple outputs --- sway/desktop/output.c | 40 ++++++++++++++++++---------------------- sway/tree/layout.c | 16 ++++++++++------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 10ed1f6d7..4b407f412 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -46,10 +46,7 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, */ static bool surface_intersect_output(struct wlr_surface *surface, struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, - double lx, double ly, float rotation, struct wlr_box *box) { - double ox = lx, oy = ly; - wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); - + double ox, double oy, float rotation, struct wlr_box *box) { if (box != NULL) { box->x = ox * wlr_output->scale; box->y = oy * wlr_output->scale; @@ -58,7 +55,7 @@ static bool surface_intersect_output(struct wlr_surface *surface, } struct wlr_box layout_box = { - .x = lx, .y = ly, + .x = wlr_output->lx + ox, .y = wlr_output->ly + oy, .width = surface->current->width, .height = surface->current->height, }; wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); @@ -67,7 +64,7 @@ static bool surface_intersect_output(struct wlr_surface *surface, static void render_surface(struct wlr_surface *surface, struct wlr_output *wlr_output, struct timespec *when, - double lx, double ly, float rotation) { + double ox, double oy, float rotation) { struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); @@ -79,7 +76,7 @@ static void render_surface(struct wlr_surface *surface, struct wlr_box box; bool intersects = surface_intersect_output(surface, layout, wlr_output, - lx, ly, rotation, &box); + ox, oy, rotation, &box); if (intersects) { float matrix[9]; enum wl_output_transform transform = @@ -102,7 +99,7 @@ static void render_surface(struct wlr_surface *surface, surface->current->width, surface->current->height, rotation); render_surface(subsurface->surface, wlr_output, when, - lx + sx, ly + sy, rotation); + ox + sx, oy + sy, rotation); } } @@ -200,9 +197,7 @@ static void render_view(struct sway_container *view, void *data) { } } -static void render_layer(struct sway_output *output, - const struct wlr_box *output_layout_box, - struct timespec *when, +static void render_layer(struct sway_output *output, struct timespec *when, struct wl_list *layer) { struct sway_layer_surface *sway_layer; wl_list_for_each(sway_layer, layer, link) { @@ -234,14 +229,15 @@ static void render_output(struct sway_output *output, struct timespec *when, float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; wlr_renderer_clear(renderer, clear_color); - struct wlr_output_layout *layout = root_container.sway_root->output_layout; + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; const struct wlr_box *output_box = - wlr_output_layout_get_box(layout, wlr_output); + wlr_output_layout_get_box(output_layout, wlr_output); - render_layer(output, output_box, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - render_layer(output, output_box, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + render_layer(output, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); + render_layer(output, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *focus = @@ -251,7 +247,7 @@ static void render_output(struct sway_output *output, struct timespec *when, focus = output->swayc->children->items[0]; } struct sway_container *workspace = focus->type == C_WORKSPACE ? - focus : container_parent(focus, C_WORKSPACE); + focus : container_parent(focus, C_WORKSPACE); struct render_data rdata = { .output = output, @@ -285,10 +281,10 @@ static void render_output(struct sway_output *output, struct timespec *when, } // TODO: Consider revising this when fullscreen windows are supported - render_layer(output, output_box, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); - render_layer(output, output_box, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); + render_layer(output, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); + render_layer(output, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); renderer_end: wlr_renderer_end(renderer); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 95a84d120..617350d90 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -19,10 +19,14 @@ struct sway_container root_container; -static void output_layout_change_notify(struct wl_listener *listener, +static void output_layout_handle_change(struct wl_listener *listener, void *data) { - struct wlr_box *layout_box = wlr_output_layout_get_box( - root_container.sway_root->output_layout, NULL); + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; + const struct wlr_box *layout_box = + wlr_output_layout_get_box(output_layout, NULL); + root_container.x = layout_box->x; + root_container.y = layout_box->y; root_container.width = layout_box->width; root_container.height = layout_box->height; @@ -34,8 +38,8 @@ static void output_layout_change_notify(struct wl_listener *listener, } struct sway_output *output = output_container->sway_output; - struct wlr_box *output_box = wlr_output_layout_get_box( - root_container.sway_root->output_layout, output->wlr_output); + const struct wlr_box *output_box = + wlr_output_layout_get_box(output_layout, output->wlr_output); if (!output_box) { continue; } @@ -62,7 +66,7 @@ void layout_init(void) { wl_signal_init(&root_container.sway_root->events.new_container); root_container.sway_root->output_layout_change.notify = - output_layout_change_notify; + output_layout_handle_change; wl_signal_add(&root_container.sway_root->output_layout->events.change, &root_container.sway_root->output_layout_change); } From 97b171649dd0f387ecd471dc75feda6307e7dbe3 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 19:36:57 -0400 Subject: [PATCH 404/522] move output damage to workspace destructor --- sway/input/seat.c | 1 - sway/tree/container.c | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index d752acb83..c326f176b 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -381,7 +381,6 @@ void seat_set_focus_warp(struct sway_seat *seat, if (last_ws) { ipc_event_workspace(last_ws, container, "focus"); if (last_ws->children->length == 0) { - output_damage_whole(last_ws->parent->sway_output); container_destroy(last_ws); } } diff --git a/sway/tree/container.c b/sway/tree/container.c index 2fd030673..fdbb29228 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -182,6 +182,9 @@ static struct sway_container *container_workspace_destroy( } _container_destroy(workspace); + + output_damage_whole(output->sway_output); + return parent; } From a001890fb8a9fc8c7f0b8eac03ca5912be2de479 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 19:52:17 -0400 Subject: [PATCH 405/522] move workspace create to workspace.c --- include/sway/tree/container.h | 8 +++-- sway/commands/move.c | 2 +- sway/commands/workspace.c | 6 ++-- sway/desktop/output.c | 2 +- sway/tree/container.c | 62 +++-------------------------------- sway/tree/layout.c | 2 +- sway/tree/workspace.c | 54 +++++++++++++++++++++++++++++- 7 files changed, 69 insertions(+), 67 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index f36b4bd11..277165ea8 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -95,7 +95,7 @@ struct sway_container *container_create(enum sway_container_type type); const char *container_type_to_str(enum sway_container_type type); -struct sway_container *container_output_create( +struct sway_container *output_create( struct sway_output *sway_output); /** @@ -108,13 +108,13 @@ struct sway_container *container_container_create(); * Create a new output. Outputs are children of the root container and have no * order in the tree structure. */ -struct sway_container *container_output_create(struct sway_output *sway_output); +struct sway_container *output_create(struct sway_output *sway_output); /** * Create a new workspace container. Workspaces are children of an output * container and are ordered alphabetically by name. */ -struct sway_container *container_workspace_create(struct sway_container *output, const char *name); +struct sway_container *workspace_create(struct sway_container *output, const char *name); /* * Create a new view container. A view can be a child of a workspace container @@ -178,4 +178,6 @@ bool container_has_anscestor(struct sway_container *container, bool container_has_child(struct sway_container *con, struct sway_container *child); +void container_create_notify(struct sway_container *container); + #endif diff --git a/sway/commands/move.c b/sway/commands/move.c index 7ac5f009a..c954ab94e 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -74,7 +74,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, ws = workspace_by_name(ws_name); } if (!ws) { - ws = container_workspace_create(NULL, ws_name ? ws_name : num_name); + ws = workspace_create(NULL, ws_name ? ws_name : num_name); } free(ws_name); struct sway_container *old_parent = current->parent; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index a37028030..958b32227 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -61,7 +61,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (strcasecmp(argv[0], "number") == 0) { if (!(ws = workspace_by_number(argv[1]))) { char *name = join_args(argv + 1, argc - 1); - ws = container_workspace_create(NULL, name); + ws = workspace_create(NULL, name); free(name); } } else if (strcasecmp(argv[0], "next") == 0) { @@ -80,12 +80,12 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { ws = old_workspace; } else if (prev_workspace_name && !(ws = workspace_by_name(prev_workspace_name))) { - ws = container_workspace_create(NULL, prev_workspace_name); + ws = workspace_create(NULL, prev_workspace_name); } } else { char *name = join_args(argv, argc); if (!(ws = workspace_by_name(name))) { - ws = container_workspace_create(NULL, name); + ws = workspace_create(NULL, name); } free(name); } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index de5076d8f..96f23291d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -396,7 +396,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->damage = wlr_output_damage_create(wlr_output); - output->swayc = container_output_create(output); + output->swayc = output_create(output); if (!output->swayc) { free(output); return; diff --git a/sway/tree/container.c b/sway/tree/container.c index fdbb29228..8ed30b447 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -51,7 +51,7 @@ const char *container_type_to_str(enum sway_container_type type) { } } -static void notify_new_container(struct sway_container *container) { +void container_create_notify(struct sway_container *container) { wl_signal_emit(&root_container.sway_root->events.new_container, container); ipc_event_window(container, "new"); } @@ -312,7 +312,7 @@ struct sway_container *container_close(struct sway_container *con) { return parent; } -struct sway_container *container_output_create( +struct sway_container *output_create( struct sway_output *sway_output) { struct wlr_box size; wlr_output_effective_resolution(sway_output->wlr_output, &size.width, @@ -363,7 +363,7 @@ struct sway_container *container_output_create( // 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); + struct sway_container *ws = 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) { @@ -373,62 +373,10 @@ struct sway_container *container_output_create( } free(ws_name); - notify_new_container(output); + container_create_notify(output); return output; } -static struct sway_container *get_workspace_initial_output(const char *name) { - struct sway_container *parent; - // Search for workspace<->output pair - int e = config->workspace_outputs->length; - for (int i = 0; i < config->workspace_outputs->length; ++i) { - struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcasecmp(wso->workspace, name) == 0) { - // Find output to use if it exists - e = root_container.children->length; - for (i = 0; i < e; ++i) { - parent = root_container.children->items[i]; - if (strcmp(parent->name, wso->output) == 0) { - return parent; - } - } - break; - } - } - // Otherwise put it on the focused output - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = - seat_get_focus_inactive(seat, &root_container); - parent = focus; - parent = container_parent(parent, C_OUTPUT); - return parent; -} - -struct sway_container *container_workspace_create(struct sway_container *output, - const char *name) { - if (output == NULL) { - output = get_workspace_initial_output(name); - } - - wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); - struct sway_container *workspace = container_create(C_WORKSPACE); - - workspace->x = output->x; - workspace->y = output->y; - workspace->width = output->width; - 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 = workspace->layout; - - container_add_child(output, workspace); - container_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, @@ -452,7 +400,7 @@ struct sway_container *container_view_create(struct sway_container *sibling, // Regular case, create as sibling of current container container_add_sibling(sibling, swayc); } - notify_new_container(swayc); + container_create_notify(swayc); return swayc; } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 3cbbf3b41..a46359bdf 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -149,7 +149,7 @@ void container_move_to(struct sway_container *container, if (old_parent->children->length == 0) { char *ws_name = workspace_next_name(old_parent->name); struct sway_container *ws = - container_workspace_create(old_parent, ws_name); + workspace_create(old_parent, ws_name); free(ws_name); seat_set_focus(seat, ws); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index d5a164103..6ba3d9732 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -14,6 +14,58 @@ #include "log.h" #include "util.h" +static struct sway_container *get_workspace_initial_output(const char *name) { + struct sway_container *parent; + // Search for workspace<->output pair + int e = config->workspace_outputs->length; + for (int i = 0; i < config->workspace_outputs->length; ++i) { + struct workspace_output *wso = config->workspace_outputs->items[i]; + if (strcasecmp(wso->workspace, name) == 0) { + // Find output to use if it exists + e = root_container.children->length; + for (i = 0; i < e; ++i) { + parent = root_container.children->items[i]; + if (strcmp(parent->name, wso->output) == 0) { + return parent; + } + } + break; + } + } + // Otherwise put it on the focused output + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = + seat_get_focus_inactive(seat, &root_container); + parent = focus; + parent = container_parent(parent, C_OUTPUT); + return parent; +} + +struct sway_container *workspace_create(struct sway_container *output, + const char *name) { + if (output == NULL) { + output = get_workspace_initial_output(name); + } + + wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); + struct sway_container *workspace = container_create(C_WORKSPACE); + + workspace->x = output->x; + workspace->y = output->y; + workspace->width = output->width; + 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 = workspace->layout; + + container_add_child(output, workspace); + container_sort_workspaces(output); + container_create_notify(workspace); + + return workspace; +} + char *prev_workspace_name = NULL; struct workspace_by_number_data { int len; @@ -292,7 +344,7 @@ bool workspace_switch(struct sway_container *workspace) { struct sway_container *new_ws = workspace_by_name(prev_workspace_name); workspace = new_ws ? new_ws : - container_workspace_create(NULL, prev_workspace_name); + workspace_create(NULL, prev_workspace_name); } if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) From fa004dd0d78b922b75a6cc9c970824d18aa4e4aa Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 20:00:09 -0400 Subject: [PATCH 406/522] move output create to its own file --- include/sway/tree/output.h | 0 sway/meson.build | 1 + sway/tree/container.c | 66 ---------------------------------- sway/tree/output.c | 73 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 66 deletions(-) create mode 100644 include/sway/tree/output.h create mode 100644 sway/tree/output.c diff --git a/include/sway/tree/output.h b/include/sway/tree/output.h new file mode 100644 index 000000000..e69de29bb diff --git a/sway/meson.build b/sway/meson.build index 87d882d27..91aab0a0b 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -88,6 +88,7 @@ sway_sources = files( 'tree/layout.c', 'tree/view.c', 'tree/workspace.c', + 'tree/output.c', ) sway_deps = [ diff --git a/sway/tree/container.c b/sway/tree/container.c index 8ed30b447..7f55ad904 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -7,7 +7,6 @@ #include #include #include -#include "log.h" #include "sway/config.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -312,71 +311,6 @@ struct sway_container *container_close(struct sway_container *con) { return parent; } -struct 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); - - 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 || - strcasecmp(identifier, cur->name) == 0) { - wlr_log(L_DEBUG, "Matched output config for %s", name); - oc = cur; - } - if (strcasecmp("*", cur->name) == 0) { - wlr_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; - } - - struct sway_container *output = container_create(C_OUTPUT); - output->sway_output = sway_output; - output->name = strdup(name); - if (output->name == NULL) { - container_destroy(output); - return NULL; - } - - apply_output_config(oc, output); - container_add_child(&root_container, output); - load_swaybars(); - - // Create workspace - char *ws_name = workspace_next_name(output->name); - wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); - struct sway_container *ws = 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) { - if (!seat->has_focus) { - seat_set_focus(seat, ws); - } - } - - free(ws_name); - container_create_notify(output); - return output; -} - struct sway_container *container_view_create(struct sway_container *sibling, struct sway_view *sway_view) { if (!sway_assert(sibling, diff --git a/sway/tree/output.c b/sway/tree/output.c new file mode 100644 index 000000000..6c7044a2c --- /dev/null +++ b/sway/tree/output.c @@ -0,0 +1,73 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include "sway/output.h" +#include "sway/tree/output.h" +#include "sway/tree/workspace.h" +#include "log.h" + +struct 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); + + 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 || + strcasecmp(identifier, cur->name) == 0) { + wlr_log(L_DEBUG, "Matched output config for %s", name); + oc = cur; + } + if (strcasecmp("*", cur->name) == 0) { + wlr_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; + } + + struct sway_container *output = container_create(C_OUTPUT); + output->sway_output = sway_output; + output->name = strdup(name); + if (output->name == NULL) { + container_destroy(output); + return NULL; + } + + apply_output_config(oc, output); + container_add_child(&root_container, output); + load_swaybars(); + + // Create workspace + char *ws_name = workspace_next_name(output->name); + wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); + struct sway_container *ws = 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) { + if (!seat->has_focus) { + seat_set_focus(seat, ws); + } + } + + free(ws_name); + container_create_notify(output); + return output; +} + From f3ef1da750d8da4b68869fa98fb8eceb8dda9858 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 21:06:13 -0400 Subject: [PATCH 407/522] Fix wrong output container coordinates --- sway/config/output.c | 12 ++++++------ sway/tree/container.c | 5 ++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index b4e56efa1..6d832cbcb 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -123,11 +123,13 @@ void terminate_swaybg(pid_t pid) { void apply_output_config(struct output_config *oc, struct sway_container *output) { assert(output->type == C_OUTPUT); + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; 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); + wlr_output_layout_remove(output_layout, wlr_output); return; } @@ -148,11 +150,9 @@ void apply_output_config(struct output_config *oc, struct sway_container *output // Find position for it if (oc && (oc->x != -1 || oc->y != -1)) { wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); - wlr_output_layout_add(root_container.sway_root->output_layout, - wlr_output, oc->x, oc->y); + wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); } else { - wlr_output_layout_add_auto(root_container.sway_root->output_layout, - wlr_output); + wlr_output_layout_add_auto(output_layout, wlr_output); } if (!oc || !oc->background) { diff --git a/sway/tree/container.c b/sway/tree/container.c index 4db93ce87..c686401c8 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -160,8 +160,11 @@ struct sway_container *container_output_create( return NULL; } - apply_output_config(oc, output); + // Insert the child before applying config so that the container coordinates + // get updated container_add_child(&root_container, output); + apply_output_config(oc, output); + load_swaybars(); // Create workspace From 260595076977729bcaf9aadcfbbc8c5f269c6387 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 21:06:28 -0400 Subject: [PATCH 408/522] Add hidpi support to swaybar --- include/swaybar/bar.h | 1 + swaybar/bar.c | 73 +++++++++++++++--- swaybar/render.c | 168 +++++++++++++++++++++++++++--------------- 3 files changed, 173 insertions(+), 69 deletions(-) diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 74292519f..503b961c1 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -58,6 +58,7 @@ struct swaybar_output { bool focused; uint32_t width, height; + int32_t scale; struct pool_buffer buffers[2]; struct pool_buffer *current_buffer; }; diff --git a/swaybar/bar.c b/swaybar/bar.c index fb4170954..cf812a608 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -69,11 +69,19 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, break; } } + int max_scale = 1; + struct swaybar_output *_output; + wl_list_for_each(_output, &bar->outputs, link) { + if (_output->scale > max_scale) { + max_scale = _output->scale; + } + } + wl_surface_set_buffer_scale(pointer->cursor_surface, max_scale); wl_surface_attach(pointer->cursor_surface, wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, - pointer->cursor_image->hotspot_x, - pointer->cursor_image->hotspot_y); + pointer->cursor_image->hotspot_x / max_scale, + pointer->cursor_image->hotspot_y / max_scale); wl_surface_commit(pointer->cursor_surface); } @@ -103,10 +111,12 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } struct swaybar_hotspot *hotspot; wl_list_for_each(hotspot, &output->hotspots, link) { - if (pointer->x >= hotspot->x - && pointer->y >= hotspot->y - && pointer->x < hotspot->x + hotspot->width - && pointer->y < hotspot->y + hotspot->height) { + double x = pointer->x * output->scale; + double y = pointer->y * output->scale; + if (x >= hotspot->x + && y >= hotspot->y + && x < hotspot->x + hotspot->width + && y < hotspot->y + hotspot->height) { hotspot->callback(output, pointer->x, pointer->y, button, hotspot->data); } @@ -197,12 +207,43 @@ const struct wl_seat_listener seat_listener = { .name = seat_handle_name, }; +static void output_geometry(void *data, struct wl_output *output, int32_t x, + int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, + const char *make, const char *model, int32_t transform) { + // Who cares +} + +static void output_mode(void *data, struct wl_output *output, uint32_t flags, + int32_t width, int32_t height, int32_t refresh) { + // Who cares +} + +static void output_done(void *data, struct wl_output *output) { + // Who cares +} + +static void output_scale(void *data, struct wl_output *wl_output, + int32_t factor) { + struct swaybar_output *output = data; + output->scale = factor; + if (output->surface) { + render_frame(output->bar, output); + } +} + +struct wl_output_listener output_listener = { + .geometry = output_geometry, + .mode = output_mode, + .done = output_done, + .scale = output_scale, +}; + 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); + &wl_compositor_interface, 3); } else if (strcmp(interface, wl_seat_interface.name) == 0) { bar->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); @@ -216,7 +257,9 @@ static void handle_global(void *data, struct wl_registry *registry, calloc(1, sizeof(struct swaybar_output)); output->bar = bar; output->output = wl_registry_bind(registry, name, - &wl_output_interface, 1); + &wl_output_interface, 3); + wl_output_add_listener(output->output, &output_listener, output); + output->scale = 1; output->index = index++; wl_list_init(&output->workspaces); wl_list_init(&output->hotspots); @@ -262,9 +305,20 @@ void bar_setup(struct swaybar *bar, wl_registry_add_listener(registry, ®istry_listener, bar); wl_display_roundtrip(bar->display); assert(bar->compositor && bar->layer_shell && bar->shm); + wl_display_roundtrip(bar->display); + struct swaybar_pointer *pointer = &bar->pointer; - assert(pointer->cursor_theme = wl_cursor_theme_load(NULL, 16, bar->shm)); + int max_scale = 1; + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + if (output->scale > max_scale) { + max_scale = output->scale; + } + } + + assert(pointer->cursor_theme = wl_cursor_theme_load( + NULL, 16 * (max_scale * 2), bar->shm)); struct wl_cursor *cursor; assert(cursor = wl_cursor_theme_get_cursor( pointer->cursor_theme, "left_ptr")); @@ -273,7 +327,6 @@ void bar_setup(struct swaybar *bar, wl_compositor_create_surface(bar->compositor)); // 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) { struct config_output *coutput; wl_list_for_each(coutput, &bar->config->outputs, link) { diff --git a/swaybar/render.c b/swaybar/render.c index 6f3b07889..bf144d5c3 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -14,55 +14,73 @@ #include "swaybar/status_line.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -static const int ws_horizontal_padding = 5; -static const double ws_vertical_padding = 1.5; -static const double border_width = 1; +static const int WS_HORIZONTAL_PADDING = 5; +static const double WS_VERTICAL_PADDING = 1.5; +static const double BORDER_WIDTH = 1; static uint32_t render_status_line_error(cairo_t *cairo, - struct swaybar_config *config, const char *error, - double *x, uint32_t width, uint32_t height) { + struct swaybar_output *output, struct swaybar_config *config, + const char *error, double *x, uint32_t width, uint32_t height) { if (!error) { return 0; } + + height *= output->scale; + cairo_set_source_u32(cairo, 0xFF0000FF); - static const int margin = 3; + + int margin = 3 * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + int text_width, text_height; get_text_size(cairo, config->font, - &text_width, &text_height, 1, false, "%s", error); + &text_width, &text_height, output->scale, false, "%s", error); + uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } *x -= text_width + margin; + double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, false, "%s", error); + pango_printf(cairo, config->font, output->scale, false, "%s", error); *x -= margin; - return ideal_height; + return ideal_height / output->scale; } static uint32_t render_status_line_text(cairo_t *cairo, - struct swaybar_config *config, const char *text, - bool focused, double *x, uint32_t width, uint32_t height) { + struct swaybar_output *output, struct swaybar_config *config, + const char *text, bool focused, double *x, + uint32_t width, uint32_t height) { if (!text) { return 0; } + + height *= output->scale; + cairo_set_source_u32(cairo, focused ? config->colors.focused_statusline : config->colors.statusline); - static const int margin = 3; + int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, config->pango_markup, "%s", text); + output->scale, config->pango_markup, "%s", text); + + int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + int margin = 3 * output->scale; + uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } + *x -= text_width + margin; double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text); + pango_printf(cairo, config->font, output->scale, + config->pango_markup, "%s", text); *x -= margin; - return ideal_height; + return ideal_height / output->scale; } static void render_sharp_line(cairo_t *cairo, uint32_t color, @@ -100,22 +118,28 @@ static uint32_t render_status_block(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct i3bar_block *block, double *x, uint32_t height, bool focused, bool edge) { - static const int margin = 3; if (!block->full_text || !*block->full_text) { return 0; } + height *= output->scale; + int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, block->markup, "%s", block->full_text); + output->scale, block->markup, "%s", block->full_text); + + int margin = 3 * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING * 2; + int width = text_width; if (width < block->min_width) { width = block->min_width; } + double block_width = width; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } *x -= width; @@ -133,10 +157,10 @@ static uint32_t render_status_block(cairo_t *cairo, if (config->sep_symbol) { int _height; get_text_size(cairo, config->font, &sep_width, &_height, - 1, false, "%s", config->sep_symbol); + output->scale, false, "%s", config->sep_symbol); uint32_t _ideal_height = _height + ws_vertical_padding * 2; - if (height < _ideal_height) { - return _height; + if (height < _ideal_height / output->scale) { + return _height / output->scale; } if (sep_width > block->separator_block_width) { block->separator_block_width = sep_width + margin * 2; @@ -160,22 +184,26 @@ static uint32_t render_status_block(cairo_t *cairo, double pos = *x; if (block->background) { cairo_set_source_u32(cairo, block->background); - cairo_rectangle(cairo, pos - 0.5, 1, block_width, height); + cairo_rectangle(cairo, pos - 0.5 * output->scale, + output->scale, block_width, height); cairo_fill(cairo); } if (block->border && block->border_top > 0) { render_sharp_line(cairo, block->border, - pos - 0.5, 1, block_width, block->border_top); + pos - 0.5 * output->scale, output->scale, + block_width, block->border_top); } if (block->border && block->border_bottom > 0) { render_sharp_line(cairo, block->border, - pos - 0.5, height - 1 - block->border_bottom, + pos - 0.5 * output->scale, + height - output->scale - block->border_bottom, block_width, block->border_bottom); } if (block->border != 0 && block->border_left > 0) { render_sharp_line(cairo, block->border, - pos - 0.5, 1, block->border_left, height); + pos - 0.5 * output->scale, output->scale, + block->border_left, height); pos += block->border_left + margin; } @@ -190,13 +218,15 @@ static uint32_t render_status_block(cairo_t *cairo, cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); uint32_t color = block->color ? *block->color : config->colors.statusline; cairo_set_source_u32(cairo, color); - pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text); + pango_printf(cairo, config->font, output->scale, + block->markup, "%s", block->full_text); pos += width; if (block->border && block->border_right > 0) { pos += margin; render_sharp_line(cairo, block->border, - pos - 0.5, 1, block->border_right, height); + pos - 0.5 * output->scale, output->scale, + block->border_right, height); pos += block->border_right; } @@ -209,7 +239,7 @@ static uint32_t render_status_block(cairo_t *cairo, if (config->sep_symbol) { offset = pos + (block->separator_block_width - sep_width) / 2; cairo_move_to(cairo, offset, margin); - pango_printf(cairo, config->font, 1, false, + pango_printf(cairo, config->font, output->scale, false, "%s", config->sep_symbol); } else { cairo_set_line_width(cairo, 1); @@ -220,7 +250,7 @@ static uint32_t render_status_block(cairo_t *cairo, cairo_stroke(cairo); } } - return ideal_height; + return ideal_height / output->scale; } static uint32_t render_status_line_i3bar(cairo_t *cairo, @@ -246,10 +276,10 @@ static uint32_t render_status_line(cairo_t *cairo, switch (status->protocol) { case PROTOCOL_ERROR: return render_status_line_error(cairo, - config, status->text, x, width, height); + output, config, status->text, x, width, height); case PROTOCOL_TEXT: return render_status_line_text(cairo, - config, status->text, focused, x, width, height); + output, config, status->text, focused, x, width, height); case PROTOCOL_I3BAR: return render_status_line_i3bar(cairo, config, output, status, focused, x, width, height); @@ -260,15 +290,23 @@ static uint32_t render_status_line(cairo_t *cairo, } static uint32_t render_binding_mode_indicator(cairo_t *cairo, - struct swaybar_config *config, const char *mode, double x, - uint32_t height) { + struct swaybar_output *output, struct swaybar_config *config, + const char *mode, double x, uint32_t height) { + + height *= output->scale; + int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, true, "%s", mode); + output->scale, true, "%s", mode); + + int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; + int border_width = BORDER_WIDTH * output->scale; + uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; @@ -289,8 +327,8 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, config->colors.binding_mode.text); cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, true, "%s", mode); - return ideal_height; + pango_printf(cairo, config->font, output->scale, true, "%s", mode); + return ideal_height / output->scale; } static const char *strip_workspace_number(const char *ws_name) { @@ -330,14 +368,22 @@ static uint32_t render_workspace_button(cairo_t *cairo, box_colors = config->colors.inactive_workspace; } + height *= output->scale; + int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, true, "%s", name); + output->scale, true, "%s", name); + + int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; + int border_width = BORDER_WIDTH * output->scale; + uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } + uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; cairo_set_source_u32(cairo, box_colors.background); @@ -357,7 +403,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, box_colors.text); cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, true, "%s", name); + pango_printf(cairo, config->font, output->scale, true, "%s", name); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; @@ -370,7 +416,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, wl_list_insert(&output->hotspots, &hotspot->link); *x += width; - return height; + return height / output->scale; } static uint32_t render_to_cairo(cairo_t *cairo, @@ -394,7 +440,13 @@ static uint32_t render_to_cairo(cairo_t *cairo, * height is too tall, the render function should adapt its drawing to * utilize the available space. */ - double x = 0; + double x = output->width * output->scale; + if (bar->status) { + uint32_t h = render_status_line(cairo, config, output, bar->status, + output->focused, &x, output->width, output->height); + max_height = h > max_height ? h : max_height; + } + x = 0; if (config->workspace_buttons) { struct swaybar_workspace *ws; wl_list_for_each_reverse(ws, &output->workspaces, link) { @@ -404,14 +456,8 @@ static uint32_t render_to_cairo(cairo_t *cairo, } } if (config->binding_mode_indicator && config->mode) { - uint32_t h = render_binding_mode_indicator( - cairo, config, config->mode, x, output->height); - max_height = h > max_height ? h : max_height; - } - x = output->width; - if (bar->status) { - uint32_t h = render_status_line(cairo, config, output, bar->status, - output->focused, &x, output->width, output->height); + uint32_t h = render_binding_mode_indicator(cairo, + output, config, config->mode, x, output->height); max_height = h > max_height ? h : max_height; } @@ -451,7 +497,9 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { } else { // Replay recording into shm and send it off output->current_buffer = get_next_buffer(bar->shm, - output->buffers, output->width, output->height); + output->buffers, + output->width * output->scale, + output->height * output->scale); cairo_t *shm = output->current_buffer->cairo; cairo_save(shm); @@ -462,9 +510,11 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { cairo_set_source_surface(shm, recorder, 0.0, 0.0); cairo_paint(shm); + wl_surface_set_buffer_scale(output->surface, output->scale); wl_surface_attach(output->surface, output->current_buffer->buffer, 0, 0); - wl_surface_damage(output->surface, 0, 0, output->width, output->height); + wl_surface_damage(output->surface, 0, 0, + output->width, output->height); wl_surface_commit(output->surface); wl_display_roundtrip(bar->display); } From d48e7036aa04f8503737de678519cc389058b259 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 21:29:43 -0400 Subject: [PATCH 409/522] Don't use asserts with side-effects --- swaybar/bar.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/swaybar/bar.c b/swaybar/bar.c index cf812a608..b617f9aba 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -299,7 +299,8 @@ void bar_setup(struct swaybar *bar, bar->status = status_line_init(bar->config->status_command); } - assert(bar->display = wl_display_connect(NULL)); + bar->display = wl_display_connect(NULL); + assert(bar->display); struct wl_registry *registry = wl_display_get_registry(bar->display); wl_registry_add_listener(registry, ®istry_listener, bar); @@ -317,14 +318,15 @@ void bar_setup(struct swaybar *bar, } } - assert(pointer->cursor_theme = wl_cursor_theme_load( - NULL, 16 * (max_scale * 2), bar->shm)); + pointer->cursor_theme = wl_cursor_theme_load( + NULL, 16 * (max_scale * 2), bar->shm); + assert(pointer->cursor_theme); struct wl_cursor *cursor; - assert(cursor = wl_cursor_theme_get_cursor( - pointer->cursor_theme, "left_ptr")); + cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); + assert(cursor); pointer->cursor_image = cursor->images[0]; - assert(pointer->cursor_surface = - wl_compositor_create_surface(bar->compositor)); + pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); + assert(pointer->cursor_surface); // TODO: we might not necessarily be meant to do all of the outputs wl_list_for_each(output, &bar->outputs, link) { @@ -334,8 +336,8 @@ void bar_setup(struct swaybar *bar, continue; } output->name = strdup(coutput->name); - assert(output->surface = wl_compositor_create_surface( - bar->compositor)); + output->surface = wl_compositor_create_surface(bar->compositor); + assert(output->surface); output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( bar->layer_shell, output->surface, output->output, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); From c4e92c81f5ce0adbc3320c578dc926a8004d3b75 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 21:57:47 -0400 Subject: [PATCH 410/522] Adjust height calculation, naming --- swaybar/render.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index bf144d5c3..1f84fdba0 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -20,12 +20,12 @@ static const double BORDER_WIDTH = 1; static uint32_t render_status_line_error(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - const char *error, double *x, uint32_t width, uint32_t height) { + const char *error, double *x, uint32_t width, uint32_t surface_height) { if (!error) { return 0; } - height *= output->scale; + uint32_t height = surface_height * output->scale; cairo_set_source_u32(cairo, 0xFF0000FF); @@ -37,7 +37,7 @@ static uint32_t render_status_line_error(cairo_t *cairo, &text_width, &text_height, output->scale, false, "%s", error); uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } *x -= text_width + margin; @@ -52,12 +52,12 @@ static uint32_t render_status_line_error(cairo_t *cairo, static uint32_t render_status_line_text(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, const char *text, bool focused, double *x, - uint32_t width, uint32_t height) { + uint32_t width, uint32_t surface_height) { if (!text) { return 0; } - height *= output->scale; + uint32_t height = surface_height * output->scale; cairo_set_source_u32(cairo, focused ? config->colors.focused_statusline : config->colors.statusline); @@ -70,7 +70,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, int margin = 3 * output->scale; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } @@ -117,12 +117,12 @@ static void block_hotspot_callback(struct swaybar_output *output, static uint32_t render_status_block(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct i3bar_block *block, double *x, - uint32_t height, bool focused, bool edge) { + uint32_t surface_height, bool focused, bool edge) { if (!block->full_text || !*block->full_text) { return 0; } - height *= output->scale; + uint32_t height = surface_height * output->scale; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, @@ -138,7 +138,7 @@ static uint32_t render_status_block(cairo_t *cairo, double block_width = width; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } @@ -256,13 +256,13 @@ static uint32_t render_status_block(cairo_t *cairo, static uint32_t render_status_line_i3bar(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct status_line *status, bool focused, - double *x, uint32_t width, uint32_t height) { + double *x, uint32_t width, uint32_t surface_height) { uint32_t max_height = 0; bool edge = true; struct i3bar_block *block; wl_list_for_each(block, &status->blocks, link) { uint32_t h = render_status_block(cairo, config, output, - block, x, height, focused, edge); + block, x, surface_height, focused, edge); max_height = h > max_height ? h : max_height; edge = false; } @@ -272,17 +272,17 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, static uint32_t render_status_line(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct status_line *status, bool focused, - double *x, uint32_t width, uint32_t height) { + double *x, uint32_t width, uint32_t surface_height) { switch (status->protocol) { case PROTOCOL_ERROR: - return render_status_line_error(cairo, - output, config, status->text, x, width, height); + return render_status_line_error(cairo, output, config, + status->text, x, width, surface_height); case PROTOCOL_TEXT: - return render_status_line_text(cairo, - output, config, status->text, focused, x, width, height); + return render_status_line_text(cairo, output, config, + status->text, focused, x, width, surface_height); case PROTOCOL_I3BAR: - return render_status_line_i3bar(cairo, config, output, status, - focused, x, width, height); + return render_status_line_i3bar(cairo, config, output, + status, focused, x, width, surface_height); case PROTOCOL_UNDEF: return 0; } @@ -291,9 +291,9 @@ static uint32_t render_status_line(cairo_t *cairo, static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - const char *mode, double x, uint32_t height) { + const char *mode, double x, uint32_t surface_height) { - height *= output->scale; + uint32_t height = surface_height * output->scale; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, @@ -305,7 +305,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; @@ -351,7 +351,7 @@ static void workspace_hotspot_callback(struct swaybar_output *output, static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - struct swaybar_workspace *ws, double *x, uint32_t height) { + struct swaybar_workspace *ws, double *x, uint32_t surface_height) { const char *name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); @@ -368,7 +368,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, box_colors = config->colors.inactive_workspace; } - height *= output->scale; + uint32_t height = surface_height *output->scale; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, @@ -380,7 +380,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } From 38bdd4bdebc4938f25af90bc4f79e278f61808e0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 22:52:40 -0400 Subject: [PATCH 411/522] Address review feedback --- swaybar/bar.c | 2 +- swaybar/render.c | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/swaybar/bar.c b/swaybar/bar.c index b617f9aba..ea0141ccd 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -319,7 +319,7 @@ void bar_setup(struct swaybar *bar, } pointer->cursor_theme = wl_cursor_theme_load( - NULL, 16 * (max_scale * 2), bar->shm); + NULL, 24 * max_scale, bar->shm); assert(pointer->cursor_theme); struct wl_cursor *cursor; cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); diff --git a/swaybar/render.c b/swaybar/render.c index 1f84fdba0..be58301d0 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -20,7 +20,7 @@ static const double BORDER_WIDTH = 1; static uint32_t render_status_line_error(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - const char *error, double *x, uint32_t width, uint32_t surface_height) { + const char *error, double *x, uint32_t surface_height) { if (!error) { return 0; } @@ -51,8 +51,7 @@ static uint32_t render_status_line_error(cairo_t *cairo, static uint32_t render_status_line_text(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - const char *text, bool focused, double *x, - uint32_t width, uint32_t surface_height) { + const char *text, bool focused, double *x, uint32_t surface_height) { if (!text) { return 0; } @@ -159,7 +158,7 @@ static uint32_t render_status_block(cairo_t *cairo, get_text_size(cairo, config->font, &sep_width, &_height, output->scale, false, "%s", config->sep_symbol); uint32_t _ideal_height = _height + ws_vertical_padding * 2; - if (height < _ideal_height / output->scale) { + if ((uint32_t)_height < _ideal_height / output->scale) { return _height / output->scale; } if (sep_width > block->separator_block_width) { @@ -256,7 +255,7 @@ static uint32_t render_status_block(cairo_t *cairo, static uint32_t render_status_line_i3bar(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct status_line *status, bool focused, - double *x, uint32_t width, uint32_t surface_height) { + double *x, uint32_t surface_height) { uint32_t max_height = 0; bool edge = true; struct i3bar_block *block; @@ -272,17 +271,17 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, static uint32_t render_status_line(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct status_line *status, bool focused, - double *x, uint32_t width, uint32_t surface_height) { + double *x, uint32_t surface_height) { switch (status->protocol) { case PROTOCOL_ERROR: return render_status_line_error(cairo, output, config, - status->text, x, width, surface_height); + status->text, x, surface_height); case PROTOCOL_TEXT: return render_status_line_text(cairo, output, config, - status->text, focused, x, width, surface_height); + status->text, focused, x, surface_height); case PROTOCOL_I3BAR: return render_status_line_i3bar(cairo, config, output, - status, focused, x, width, surface_height); + status, focused, x, surface_height); case PROTOCOL_UNDEF: return 0; } @@ -368,7 +367,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, box_colors = config->colors.inactive_workspace; } - uint32_t height = surface_height *output->scale; + uint32_t height = surface_height * output->scale; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, @@ -442,8 +441,8 @@ static uint32_t render_to_cairo(cairo_t *cairo, */ double x = output->width * output->scale; if (bar->status) { - uint32_t h = render_status_line(cairo, config, output, bar->status, - output->focused, &x, output->width, output->height); + uint32_t h = render_status_line(cairo, config, output, + bar->status, output->focused, &x, output->height); max_height = h > max_height ? h : max_height; } x = 0; From 9d1cbd77aca72ca72eaba5056de5805b14f004c1 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 23:59:44 -0400 Subject: [PATCH 412/522] simplify container close --- sway/tree/container.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 7f55ad904..57dcb4bd6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -294,18 +294,10 @@ struct sway_container *container_close(struct sway_container *con) { struct sway_container *parent = con->parent; - switch (con->type) { - case C_TYPES: - case C_ROOT: - case C_OUTPUT: - case C_WORKSPACE: - case C_CONTAINER: - container_for_each_descendant_dfs(con, container_close_func, NULL); - break; - case C_VIEW: + if (con->type == C_VIEW) { view_close(con->sway_view); - break; - + } else { + container_for_each_descendant_dfs(con, container_close_func, NULL); } return parent; From 62c79ef4510d4687e35deab177cf5114a138261f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 4 Apr 2018 00:22:40 -0400 Subject: [PATCH 413/522] fix double free --- sway/tree/container.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 57dcb4bd6..eaf4c1174 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -253,7 +253,6 @@ struct sway_container *container_destroy(struct sway_container *con) { container_remove_child(child); container_add_child(parent, child); } - _container_destroy(con); } _container_destroy(con); break; From 76b0f3531f218551535f489f3bb51cdf38b937d6 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 4 Apr 2018 14:19:38 -0400 Subject: [PATCH 414/522] send window close event --- sway/tree/container.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index eaf4c1174..753f333cb 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -51,10 +51,16 @@ const char *container_type_to_str(enum sway_container_type type) { } void container_create_notify(struct sway_container *container) { + // TODO send ipc event type based on the container type wl_signal_emit(&root_container.sway_root->events.new_container, container); ipc_event_window(container, "new"); } +static void container_close_notify(struct sway_container *container) { + // TODO send ipc event type based on the container type + ipc_event_window(container, "close"); +} + 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; @@ -82,6 +88,7 @@ static void _container_destroy(struct sway_container *cont) { } wl_signal_emit(&cont->events.destroy, cont); + container_close_notify(cont); struct sway_container *parent = cont->parent; if (cont->children != NULL && cont->children->length) { From a28730edee1896242012f80fd0e63e7966652e02 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 21:57:13 -0400 Subject: [PATCH 415/522] Move swaybg background rendering into common/ swaylock will use it too --- common/background-image.c | 100 ++++++++++++++++++++++++++++++++ common/meson.build | 20 +++---- include/background-image.h | 19 +++++++ swaybg/main.c | 113 ++----------------------------------- 4 files changed, 133 insertions(+), 119 deletions(-) create mode 100644 common/background-image.c create mode 100644 include/background-image.h diff --git a/common/background-image.c b/common/background-image.c new file mode 100644 index 000000000..2988c2e26 --- /dev/null +++ b/common/background-image.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include "background-image.h" +#include "cairo.h" + +cairo_surface_t *load_background_image(const char *path) { + cairo_surface_t *image; +#ifdef HAVE_GDK_PIXBUF + GError *err = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); + if (!pixbuf) { + wlr_log(L_ERROR, "Failed to load background image."); + return false; + } + image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); + g_object_unref(pixbuf); +#else + image = cairo_image_surface_create_from_png(path); +#endif //HAVE_GDK_PIXBUF + if (!image) { + wlr_log(L_ERROR, "Failed to read background image."); + return NULL; + } + if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { + wlr_log(L_ERROR, "Failed to read background image: %s." +#ifndef HAVE_GDK_PIXBUF + "\nSway was compiled without gdk_pixbuf support, so only" + "\nPNG images can be loaded. This is the likely cause." +#endif //HAVE_GDK_PIXBUF + , cairo_status_to_string(cairo_surface_status(image))); + return NULL; + } + return image; +} + +void render_background_image(cairo_t *cairo, cairo_surface_t *image, + enum background_mode mode, int buffer_width, int buffer_height, + int buffer_scale) { + double width = cairo_image_surface_get_width(image); + double height = cairo_image_surface_get_height(image); + + switch (mode) { + case BACKGROUND_MODE_STRETCH: + cairo_scale(cairo, + (double)buffer_width / width, + (double)buffer_height / height); + cairo_set_source_surface(cairo, image, 0, 0); + break; + case BACKGROUND_MODE_FILL: { + double window_ratio = (double)buffer_width / buffer_height; + double bg_ratio = width / height; + + if (window_ratio > bg_ratio) { + double scale = (double)buffer_width / width; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + 0, (double)buffer_height / 2 / scale - height / 2); + } else { + double scale = (double)buffer_height / height; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + (double)buffer_width / 2 / scale - width / 2, 0); + } + break; + } + case BACKGROUND_MODE_FIT: { + double window_ratio = (double)buffer_width / buffer_height; + double bg_ratio = width / height; + + if (window_ratio > bg_ratio) { + double scale = (double)buffer_height / height; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + (double)buffer_width / 2 / scale - width / 2, 0); + } else { + double scale = (double)buffer_width / width; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + 0, (double)buffer_height / 2 / scale - height / 2); + } + break; + } + case BACKGROUND_MODE_CENTER: + cairo_set_source_surface(cairo, image, + (double)buffer_width / 2 - width / 2, + (double)buffer_height / 2 - height / 2); + break; + case BACKGROUND_MODE_TILE: { + cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); + cairo_set_source(cairo, pattern); + break; + } + case BACKGROUND_MODE_SOLID_COLOR: + assert(0); + break; + } + cairo_paint(cairo); +} diff --git a/common/meson.build b/common/meson.build index 4ad470774..851e7bbf5 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,17 +1,7 @@ -deps = [ - cairo, - pango, - pangocairo, - wlroots -] - -if gdk_pixbuf.found() - deps += [gdk_pixbuf] -endif - lib_sway_common = static_library( 'sway-common', files( + 'background-image.c', 'cairo.c', 'ipc-client.c', 'log.c', @@ -21,6 +11,12 @@ lib_sway_common = static_library( 'stringop.c', 'util.c' ), - dependencies: deps, + dependencies: [ + cairo, + gdk_pixbuf, + pango, + pangocairo, + wlroots + ], include_directories: sway_inc ) diff --git a/include/background-image.h b/include/background-image.h new file mode 100644 index 000000000..e160e63d4 --- /dev/null +++ b/include/background-image.h @@ -0,0 +1,19 @@ +#ifndef _SWAY_BACKGROUND_IMAGE_H +#define _SWAY_BACKGROUND_IMAGE_H +#include "cairo.h" + +enum background_mode { + BACKGROUND_MODE_STRETCH, + BACKGROUND_MODE_FILL, + BACKGROUND_MODE_FIT, + BACKGROUND_MODE_CENTER, + BACKGROUND_MODE_TILE, + BACKGROUND_MODE_SOLID_COLOR, +}; + +cairo_surface_t *load_background_image(const char *path); +void render_background_image(cairo_t *cairo, cairo_surface_t *image, + enum background_mode mode, int buffer_width, int buffer_height, + int buffer_scale); + +#endif diff --git a/swaybg/main.c b/swaybg/main.c index c282a7074..ffefcd089 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -7,20 +7,12 @@ #include #include #include +#include "background-image.h" #include "pool-buffer.h" #include "cairo.h" #include "util.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -enum background_mode { - BACKGROUND_MODE_STRETCH, - BACKGROUND_MODE_FILL, - BACKGROUND_MODE_FIT, - BACKGROUND_MODE_CENTER, - BACKGROUND_MODE_TILE, - BACKGROUND_MODE_SOLID_COLOR, -}; - struct swaybg_args { int output_idx; const char *path; @@ -71,85 +63,16 @@ bool is_valid_color(const char *color) { return true; } -static void render_image(struct swaybg_state *state) { - cairo_t *cairo = state->current_buffer->cairo; - cairo_surface_t *image = state->context.image; - double width = cairo_image_surface_get_width(image); - double height = cairo_image_surface_get_height(image); - int buffer_width = state->width * state->scale; - int buffer_height = state->height * state->scale; - - switch (state->args->mode) { - case BACKGROUND_MODE_STRETCH: - cairo_scale(cairo, (double)buffer_width / width, - (double)buffer_height / height); - cairo_set_source_surface(cairo, image, 0, 0); - break; - case BACKGROUND_MODE_FILL: { - double window_ratio = (double)buffer_width / buffer_height; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double)buffer_width / width; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - 0, (double)buffer_height / 2 / scale - height / 2); - } else { - double scale = (double)buffer_height / height; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 / scale - width / 2, 0); - } - break; - } - case BACKGROUND_MODE_FIT: { - double window_ratio = (double)buffer_width / buffer_height; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double)buffer_height / height; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 / scale - width / 2, 0); - } else { - double scale = (double)buffer_width / width; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - 0, (double)buffer_height / 2 / scale - height / 2); - } - break; - } - case BACKGROUND_MODE_CENTER: - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 - width / 2, - (double)buffer_height / 2 - height / 2); - break; - case BACKGROUND_MODE_TILE: { - cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - cairo_set_source(cairo, pattern); - break; - } - case BACKGROUND_MODE_SOLID_COLOR: - assert(0); - break; - } - cairo_paint(cairo); -} - static void render_frame(struct swaybg_state *state) { state->current_buffer = get_next_buffer(state->shm, state->buffers, state->width * state->scale, state->height * state->scale); cairo_t *cairo = state->current_buffer->cairo; - - switch (state->args->mode) { - case BACKGROUND_MODE_SOLID_COLOR: + if (state->args->mode == BACKGROUND_MODE_SOLID_COLOR) { cairo_set_source_u32(cairo, state->context.color); cairo_paint(cairo); - break; - default: - render_image(state); - break; + } else { + render_background_image(cairo, state->context.image, + state->args->mode, state->width, state->height, state->scale); } wl_surface_set_buffer_scale(state->surface, state->scale); @@ -163,31 +86,7 @@ static bool prepare_context(struct swaybg_state *state) { state->context.color = parse_color(state->args->path); return is_valid_color(state->args->path); } -#ifdef HAVE_GDK_PIXBUF - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(state->args->path, &err); - if (!pixbuf) { - wlr_log(L_ERROR, "Failed to load background image."); - return false; - } - state->context.image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - state->context.image = cairo_image_surface_create_from_png( - state->args->path); -#endif //HAVE_GDK_PIXBUF - if (!state->context.image) { - wlr_log(L_ERROR, "Failed to read background image."); - return false; - } - if (cairo_surface_status(state->context.image) != CAIRO_STATUS_SUCCESS) { - wlr_log(L_ERROR, "Failed to read background image: %s." -#ifndef HAVE_GDK_PIXBUF - "\nSway was compiled without gdk_pixbuf support, so only" - "\nPNG images can be loaded. This is the likely cause." -#endif //HAVE_GDK_PIXBUF - , cairo_status_to_string( - cairo_surface_status(state->context.image))); + if (!(state->context.image = load_background_image(state->args->path))) { return false; } return true; From b32bf595aeae7f8ac68354e45a80c0438374ec17 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 22:48:13 -0400 Subject: [PATCH 416/522] Initial swaylock port --- common/background-image.c | 22 +- include/background-image.h | 5 +- meson.build | 2 + swaybg/main.c | 28 +- swaylock/main.c | 1010 ++++++++++-------------------------- swaylock/meson.build | 18 + 6 files changed, 327 insertions(+), 758 deletions(-) create mode 100644 swaylock/meson.build diff --git a/common/background-image.c b/common/background-image.c index 2988c2e26..1a6c0df05 100644 --- a/common/background-image.c +++ b/common/background-image.c @@ -4,6 +4,24 @@ #include "background-image.h" #include "cairo.h" +enum background_mode parse_background_mode(const char *mode) { + if (strcmp(mode, "stretch") == 0) { + return BACKGROUND_MODE_STRETCH; + } else if (strcmp(mode, "fill") == 0) { + return BACKGROUND_MODE_FILL; + } else if (strcmp(mode, "fit") == 0) { + return BACKGROUND_MODE_FIT; + } else if (strcmp(mode, "center") == 0) { + return BACKGROUND_MODE_CENTER; + } else if (strcmp(mode, "tile") == 0) { + return BACKGROUND_MODE_TILE; + } else if (strcmp(mode, "solid_color") == 0) { + return BACKGROUND_MODE_SOLID_COLOR; + } + wlr_log(L_ERROR, "Unsupported background mode: %s", mode); + return BACKGROUND_MODE_INVALID; +} + cairo_surface_t *load_background_image(const char *path) { cairo_surface_t *image; #ifdef HAVE_GDK_PIXBUF @@ -35,8 +53,7 @@ cairo_surface_t *load_background_image(const char *path) { } void render_background_image(cairo_t *cairo, cairo_surface_t *image, - enum background_mode mode, int buffer_width, int buffer_height, - int buffer_scale) { + enum background_mode mode, int buffer_width, int buffer_height) { double width = cairo_image_surface_get_width(image); double height = cairo_image_surface_get_height(image); @@ -93,6 +110,7 @@ void render_background_image(cairo_t *cairo, cairo_surface_t *image, break; } case BACKGROUND_MODE_SOLID_COLOR: + case BACKGROUND_MODE_INVALID: assert(0); break; } diff --git a/include/background-image.h b/include/background-image.h index e160e63d4..15935ffd3 100644 --- a/include/background-image.h +++ b/include/background-image.h @@ -9,11 +9,12 @@ enum background_mode { BACKGROUND_MODE_CENTER, BACKGROUND_MODE_TILE, BACKGROUND_MODE_SOLID_COLOR, + BACKGROUND_MODE_INVALID, }; +enum background_mode parse_background_mode(const char *mode); cairo_surface_t *load_background_image(const char *path); void render_background_image(cairo_t *cairo, cairo_surface_t *image, - enum background_mode mode, int buffer_width, int buffer_height, - int buffer_scale); + enum background_mode mode, int buffer_width, int buffer_height); #endif diff --git a/meson.build b/meson.build index 01788fd9f..d02a446b5 100644 --- a/meson.build +++ b/meson.build @@ -35,6 +35,7 @@ gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false) pixman = dependency('pixman-1') libcap = dependency('libcap') libinput = dependency('libinput') +libpam = cc.find_library('libpam') math = cc.find_library('m') rt = cc.find_library('rt') git = find_program('git', required: false) @@ -105,6 +106,7 @@ subdir('swaymsg') subdir('client') subdir('swaybg') subdir('swaybar') +subdir('swaylock') config = configuration_data() config.set('sysconfdir', join_paths(prefix, sysconfdir)) diff --git a/swaybg/main.c b/swaybg/main.c index ffefcd089..679b8c205 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -64,15 +64,17 @@ bool is_valid_color(const char *color) { } static void render_frame(struct swaybg_state *state) { - state->current_buffer = get_next_buffer(state->shm, state->buffers, - state->width * state->scale, state->height * state->scale); + int buffer_width = state->width * state->scale, + buffer_height = state->height * state->scale; + state->current_buffer = get_next_buffer(state->shm, + state->buffers, buffer_width, buffer_height); cairo_t *cairo = state->current_buffer->cairo; if (state->args->mode == BACKGROUND_MODE_SOLID_COLOR) { cairo_set_source_u32(cairo, state->context.color); cairo_paint(cairo); } else { render_background_image(cairo, state->context.image, - state->args->mode, state->width, state->height, state->scale); + state->args->mode, buffer_width, buffer_height); } wl_surface_set_buffer_scale(state->surface, state->scale); @@ -193,24 +195,10 @@ int main(int argc, const char **argv) { args.output_idx = atoi(argv[1]); args.path = argv[2]; - args.mode = BACKGROUND_MODE_STRETCH; - if (strcmp(argv[3], "stretch") == 0) { - args.mode = BACKGROUND_MODE_STRETCH; - } else if (strcmp(argv[3], "fill") == 0) { - args.mode = BACKGROUND_MODE_FILL; - } else if (strcmp(argv[3], "fit") == 0) { - args.mode = BACKGROUND_MODE_FIT; - } else if (strcmp(argv[3], "center") == 0) { - args.mode = BACKGROUND_MODE_CENTER; - } else if (strcmp(argv[3], "tile") == 0) { - args.mode = BACKGROUND_MODE_TILE; - } else if (strcmp(argv[3], "solid_color") == 0) { - args.mode = BACKGROUND_MODE_SOLID_COLOR; - } else { - wlr_log(L_ERROR, "Unsupported background mode: %s", argv[3]); + args.mode = parse_background_mode(argv[3]); + if (args.mode == BACKGROUND_MODE_INVALID) { return 1; } - if (!prepare_context(&state)) { return 1; } @@ -244,10 +232,10 @@ int main(int argc, const char **argv) { zwlr_layer_surface_v1_set_exclusive_zone(state.layer_surface, -1); zwlr_layer_surface_v1_add_listener(state.layer_surface, &layer_surface_listener, &state); - state.run_display = true; wl_surface_commit(state.surface); wl_display_roundtrip(state.display); + state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { // This space intentionally left blank } diff --git a/swaylock/main.c b/swaylock/main.c index c26159519..8673694d2 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -1,387 +1,235 @@ -#define _XOPEN_SOURCE 500 -#include "wayland-swaylock-client-protocol.h" -#include -#include -#include -#include +#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include +#include +#include #include -#include "client/window.h" -#include "client/registry.h" -#include "client/cairo.h" -#include "swaylock/swaylock.h" -#include "ipc-client.h" -#include "log.h" +#include +#include +#include "background-image.h" +#include "pool-buffer.h" +#include "cairo.h" #include "util.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" -struct registry *registry; -struct render_data render_data; -struct lock_config *config; -bool show_indicator = true; +struct swaylock_args { + uint32_t color; + enum background_mode mode; + bool show_indicator; +}; -void wl_dispatch_events() { - wl_display_flush(registry->display); - if (wl_display_dispatch(registry->display) == -1) { - sway_log(L_ERROR, "failed to run wl_display_dispatch"); - exit(1); +struct swaylock_state { + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; + struct wl_list contexts; + struct swaylock_args args; + bool run_display; +}; + +struct swaylock_context { + cairo_surface_t *image; + struct swaylock_state *state; + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; + uint32_t width, height; + struct wl_list link; +}; + +static void daemonize() { + if (fork() == 0) { + int devnull = open("/dev/null", O_RDWR); + dup2(STDOUT_FILENO, devnull); + dup2(STDERR_FILENO, devnull); + chdir("/"); + } else { + exit(0); } } -void sigalarm_handler(int sig) { +static void render_frame(struct swaylock_context *context) { + struct swaylock_state *state = context->state; + context->current_buffer = get_next_buffer(state->shm, + context->buffers, context->width, context->height); + cairo_t *cairo = context->current_buffer->cairo; + if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { + cairo_set_source_u32(cairo, state->args.color); + cairo_paint(cairo); + } else { + render_background_image(cairo, context->image, + state->args.mode, context->width, context->height); + } + wl_surface_attach(context->surface, context->current_buffer->buffer, 0, 0); + wl_surface_damage(context->surface, 0, 0, context->width, context->height); + wl_surface_commit(context->surface); +} + +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t width, uint32_t height) { + struct swaylock_context *context = data; + context->width = width; + context->height = height; + zwlr_layer_surface_v1_ack_configure(surface, serial); + render_frame(context); +} + +static void layer_surface_closed(void *data, + struct zwlr_layer_surface_v1 *surface) { + struct swaylock_context *context = data; + zwlr_layer_surface_v1_destroy(context->layer_surface); + wl_surface_destroy(context->surface); + context->state->run_display = false; +} + +struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed, +}; + +static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + wl_pointer_set_cursor(wl_pointer, serial, NULL, 0, 0); +} + +static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) { + // Who cares +} + +static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { + // Who cares +} + +static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + // Who cares +} + +static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { + // Who cares +} + +static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { + // Who cares +} + +static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) { + // Who cares +} + +static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) { + // Who cares +} + +static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) { + // Who cares +} + +struct wl_pointer_listener pointer_listener = { + .enter = wl_pointer_enter, + .leave = wl_pointer_leave, + .motion = wl_pointer_motion, + .button = wl_pointer_button, + .axis = wl_pointer_axis, + .frame = wl_pointer_frame, + .axis_source = wl_pointer_axis_source, + .axis_stop = wl_pointer_axis_stop, + .axis_discrete = wl_pointer_axis_discrete, +}; + +static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) { + if ((caps & WL_SEAT_CAPABILITY_POINTER)) { + struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(pointer, &pointer_listener, NULL); + } +} + +static void seat_handle_name(void *data, struct wl_seat *wl_seat, + const char *name) { + // Who cares +} + +const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; + +static void handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + struct swaylock_state *state = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + state->compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + state->shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); + } else if (strcmp(interface, wl_seat_interface.name) == 0) { + struct wl_seat *seat = wl_registry_bind( + registry, name, &wl_seat_interface, 1); + wl_seat_add_listener(seat, &seat_listener, NULL); + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + state->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + struct swaylock_context *context = + calloc(1, sizeof(struct swaylock_context)); + context->state = state; + context->output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + wl_list_insert(&state->contexts, &context->link); + } +} + +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares +} + +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; + +static struct swaylock_state state; + +static void sigalarm_handler(int sig) { signal(SIGALRM, SIG_IGN); - // Hide typing indicator - render_data.auth_state = AUTH_STATE_IDLE; - render(&render_data, config); - wl_display_flush(registry->display); + // TODO: Hide typing indicator signal(SIGALRM, sigalarm_handler); } -void sway_terminate(int exit_code) { - int i; - for (i = 0; i < render_data.surfaces->length; ++i) { - struct window *window = render_data.surfaces->items[i]; - window_teardown(window); - } - list_free(render_data.surfaces); - if (registry) { - registry_teardown(registry); - } - exit(exit_code); -} - -char *password; -int password_size; -enum line_source line_source = LINE_SOURCE_DEFAULT; - -struct lock_config *init_config() { - struct lock_config *config = calloc(1, sizeof(struct lock_config)); - - config->font = strdup("sans-serif"); - config->colors.text = 0x000000FF; - - config->colors.line = 0x000000FF; - config->colors.separator = 0x000000FF; - - config->colors.input_cursor = 0x33DB00FF; - config->colors.backspace_cursor = 0xDB3300FF; - - config->colors.normal.inner_ring = 0x000000BF; - config->colors.normal.outer_ring = 0x337D00FF; - - config->colors.validating.inner_ring = 0x0072FFBF; - config->colors.validating.outer_ring = 0x3300FAFF; - - config->colors.invalid.inner_ring = 0xFA0000BF; - config->colors.invalid.outer_ring = 0x7D3300FF; - - config->radius = 50; - config->thickness = 10; - - return config; -} - -void free_config(struct lock_config *config) { - free(config->font); - free(config); -} - -int function_conversation(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr) { - - const char* msg_style_names[] = { - NULL, - "PAM_PROMPT_ECHO_OFF", - "PAM_PROMPT_ECHO_ON", - "PAM_ERROR_MSG", - "PAM_TEXT_INFO", - }; - - /* PAM expects an array of responses, one for each message */ - struct pam_response *pam_reply = calloc(num_msg, sizeof(struct pam_response)); - *resp = pam_reply; - - for(int i=0; imsg_style], - msg[i]->msg); - - switch (msg[i]->msg_style) { - case PAM_PROMPT_ECHO_OFF: - case PAM_PROMPT_ECHO_ON: - pam_reply[i].resp = password; - break; - - case PAM_ERROR_MSG: - case PAM_TEXT_INFO: - break; - } - } - - return PAM_SUCCESS; -} - -/** - * Note: PAM will free() 'password' during the process - */ -bool verify_password() { - struct passwd *passwd = getpwuid(getuid()); - char *username = passwd->pw_name; - - const struct pam_conv local_conversation = { function_conversation, NULL }; - pam_handle_t *local_auth_handle = NULL; - int pam_err; - if ((pam_err = pam_start("swaylock", username, &local_conversation, &local_auth_handle)) != PAM_SUCCESS) { - sway_abort("PAM returned %d\n", pam_err); - } - if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { - return false; - } - if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { - return false; - } - return true; -} - -void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) { - int redraw_screen = 0; - char *password_realloc; - int i; - - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - switch (sym) { - case XKB_KEY_KP_Enter: - case XKB_KEY_Return: - render_data.auth_state = AUTH_STATE_VALIDATING; - - render(&render_data, config); - // Make sure our render call will actually be displayed on the screen - wl_dispatch_events(); - - if (verify_password()) { - exit(0); - } - - render_data.auth_state = AUTH_STATE_INVALID; - redraw_screen = 1; - - password_size = 1024; - password = malloc(password_size); - password[0] = '\0'; - break; - case XKB_KEY_BackSpace: - i = strlen(password); - if (i > 0) { - password[i - 1] = '\0'; - render_data.auth_state = AUTH_STATE_BACKSPACE; - redraw_screen = 1; - } - break; - case XKB_KEY_Control_L: - case XKB_KEY_Control_R: - case XKB_KEY_Shift_L: - case XKB_KEY_Shift_R: - case XKB_KEY_Caps_Lock: - case XKB_KEY_Shift_Lock: - case XKB_KEY_Meta_L: - case XKB_KEY_Meta_R: - case XKB_KEY_Alt_L: - case XKB_KEY_Alt_R: - case XKB_KEY_Super_L: - case XKB_KEY_Super_R: - case XKB_KEY_Hyper_L: - case XKB_KEY_Hyper_R: - break; // don't draw screen on modifier keys - case XKB_KEY_Escape: - case XKB_KEY_u: - case XKB_KEY_U: - // clear password buffer on ctrl-u (or escape for i3lock compatibility) - if (sym == XKB_KEY_Escape || xkb_state_mod_name_is_active(registry->input->xkb.state, - XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0) { - render_data.auth_state = AUTH_STATE_BACKSPACE; - redraw_screen = 1; - - password_size = 1024; - free(password); - password = malloc(password_size); - password[0] = '\0'; - break; - } - /* fallthrough */ - default: - render_data.auth_state = AUTH_STATE_INPUT; - redraw_screen = 1; - i = strlen(password); - if (i + 1 == password_size) { - password_size += 1024; - password_realloc = realloc(password, password_size); - // reset password if realloc fails. - if (password_realloc == NULL) { - password_size = 1024; - free(password); - password = malloc(password_size); - password[0] = '\0'; - break; - } else { - password = password_realloc; - } - } - password[i] = (char)codepoint; - password[i + 1] = '\0'; - break; - } - if (redraw_screen) { - render(&render_data, config); - wl_dispatch_events(); - // Hide the indicator after a couple of seconds - alarm(5); - } - } -} - -void render_color(struct window *window, uint32_t color) { - cairo_set_source_u32(window->cairo, color); - cairo_paint(window->cairo); -} - -void render_image(struct window *window, cairo_surface_t *image, enum scaling_mode scaling_mode) { - double width = cairo_image_surface_get_width(image); - double height = cairo_image_surface_get_height(image); - int wwidth = window->width * window->scale; - int wheight = window->height * window->scale; - - switch (scaling_mode) { - case SCALING_MODE_STRETCH: - cairo_scale(window->cairo, - (double) wwidth / width, - (double) wheight / height); - cairo_set_source_surface(window->cairo, image, 0, 0); - break; - case SCALING_MODE_FILL: - { - double window_ratio = (double) wwidth / wheight; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double) wwidth / width; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - 0, - (double) wheight/2 / scale - height/2); - } else { - double scale = (double) wheight / height; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 / scale - width/2, - 0); - } - break; - } - case SCALING_MODE_FIT: - { - double window_ratio = (double) wwidth / wheight; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double) wheight / height; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 / scale - width/2, - 0); - } else { - double scale = (double) wwidth / width; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - 0, - (double) wheight/2 / scale - height/2); - } - break; - } - case SCALING_MODE_CENTER: - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 - width/2, - (double) wheight/2 - height/2); - break; - case SCALING_MODE_TILE: - { - cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - cairo_set_source(window->cairo, pattern); - break; - } - } - - cairo_paint(window->cairo); -} - -cairo_surface_t *load_image(char *image_path) { - 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_abort("Failed to load background image: %s", err->message); - } - image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - image = cairo_image_surface_create_from_png(image_path); -#endif //WITH_GDK_PIXBUF - if (!image) { - sway_abort("Failed to read background image."); - } - - return image; -} - int main(int argc, char **argv) { - const char *scaling_mode_str = "fit", *socket_path = NULL; - int i; - void *images = NULL; - config = init_config(); - - render_data.num_images = 0; - render_data.color_set = 0; - render_data.color = 0xFFFFFFFF; - render_data.auth_state = AUTH_STATE_IDLE; - - init_log(L_INFO); - // Install SIGALARM handler (for hiding the typing indicator) signal(SIGALRM, sigalarm_handler); static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"color", required_argument, NULL, 'c'}, {"image", required_argument, NULL, 'i'}, - {"scaling", required_argument, NULL, 0}, + {"scaling", required_argument, NULL, 's'}, {"tiling", no_argument, NULL, 't'}, {"version", no_argument, NULL, 'v'}, {"socket", required_argument, NULL, 'p'}, {"no-unlock-indicator", no_argument, NULL, 'u'}, {"daemonize", no_argument, NULL, 'f'}, - {"font", required_argument, NULL, 0}, - {"line-uses-ring", no_argument, NULL, 'r'}, - {"line-uses-inside", no_argument, NULL, 's'}, - {"textcolor", required_argument, NULL, 0}, - {"insidevercolor", required_argument, NULL, 0}, - {"insidewrongcolor", required_argument, NULL, 0}, - {"insidecolor", required_argument, NULL, 0}, - {"ringvercolor", required_argument, NULL, 0}, - {"ringwrongcolor", required_argument, NULL, 0}, - {"ringcolor", required_argument, NULL, 0}, - {"linecolor", required_argument, NULL, 0}, - {"separatorcolor", required_argument, NULL, 0}, - {"keyhlcolor", required_argument, NULL, 0}, - {"bshlcolor", required_argument, NULL, 0}, - {"indicator-radius", required_argument, NULL, 0}, - {"indicator-thickness", required_argument, NULL, 0}, {0, 0, 0, 0} }; @@ -390,415 +238,109 @@ int main(int argc, char **argv) { "\n" " -h, --help Show help message and quit.\n" " -c, --color Turn the screen into the given color instead of white.\n" - " --scaling Scaling mode: stretch, fill, fit, center, tile.\n" + " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" " -t, --tiling Same as --scaling=tile.\n" " -v, --version Show the version number and quit.\n" " -i, --image [:] Display the given image.\n" " -u, --no-unlock-indicator Disable the unlock indicator.\n" - " -f, --daemonize Detach from the controlling terminal.\n" - " --socket Use the specified socket.\n" - " For more information see `man swaylock`\n"; + " -f, --daemonize Detach from the controlling terminal.\n" + " --socket Use the specified socket.\n"; - - registry = registry_poll(); + struct swaylock_args args = { + .mode = BACKGROUND_MODE_SOLID_COLOR, + .color = 0xFFFFFFFF, + .show_indicator = true, + }; + state.args = args; + wlr_log_init(L_DEBUG, NULL); int c; while (1) { int option_index = 0; - c = getopt_long(argc, argv, "hc:i:srtvuf", long_options, &option_index); + c = getopt_long(argc, argv, "hc:i:s:tvuf", long_options, &option_index); if (c == -1) { break; } switch (c) { - case 'c': - { - render_data.color = parse_color(optarg); - render_data.color_set = 1; + case 'c': { + state.args.color = parse_color(optarg); + state.args.mode = BACKGROUND_MODE_SOLID_COLOR; break; } case 'i': - { - char *image_path = strchr(optarg, ':'); - if (image_path == NULL) { - if (render_data.num_images == 0) { - // Provided image without output - render_data.image = load_image(optarg); - render_data.num_images = -1; - } else { - sway_log(L_ERROR, "output must be defined for all --images or no --images"); - exit(EXIT_FAILURE); - } - } else { - // Provided image for all outputs - if (render_data.num_images == 0) { - images = calloc(registry->outputs->length, sizeof(char*) * 2); - } else if (render_data.num_images == -1) { - sway_log(L_ERROR, "output must be defined for all --images or no --images"); - exit(EXIT_FAILURE); - } - - image_path[0] = '\0'; - ((char**) images)[render_data.num_images * 2] = optarg; - ((char**) images)[render_data.num_images++ * 2 + 1] = ++image_path; + // TODO + return 1; + case 's': + state.args.mode = parse_background_mode(optarg); + if (state.args.mode == BACKGROUND_MODE_INVALID) { + return 1; } break; - } case 't': - scaling_mode_str = "tile"; - break; - case 'p': - socket_path = optarg; + // TODO break; case 'v': - fprintf(stdout, "swaylock version " SWAY_VERSION "\n"); - exit(EXIT_SUCCESS); - break; +#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE + fprintf(stdout, "swaylock version %s (%s, branch \"%s\")\n", + SWAY_GIT_VERSION, SWAY_VERSION_DATE, SWAY_GIT_BRANCH); +#else + fprintf(stdout, "version unknown\n"); +#endif + return 0; case 'u': - show_indicator = false; + state.args.show_indicator = false; break; - case 'f': { - pid_t t = fork(); - if (t == -1) { - sway_log(L_ERROR, "daemon call failed"); - exit(EXIT_FAILURE); - } else if (t > 0) { - exit(0); - } - break; - } - case 'r': - if (line_source != LINE_SOURCE_DEFAULT) { - sway_log(L_ERROR, "line source options conflict"); - exit(EXIT_FAILURE); - } - line_source = LINE_SOURCE_RING; - break; - case 's': - if (line_source != LINE_SOURCE_DEFAULT) { - sway_log(L_ERROR, "line source options conflict"); - exit(EXIT_FAILURE); - } - line_source = LINE_SOURCE_INSIDE; - break; - case 0: - if (strcmp(long_options[option_index].name, "font") == 0) { - free(config->font); - config->font = strdup(optarg); - } else if (strcmp(long_options[option_index].name, "scaling") == 0) { - scaling_mode_str = optarg; - } else if (strcmp(long_options[option_index].name, "textcolor") == 0) { - config->colors.text = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "insidevercolor") == 0) { - config->colors.validating.inner_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "insidewrongcolor") == 0) { - config->colors.invalid.inner_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "insidecolor") == 0) { - config->colors.normal.inner_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "ringvercolor") == 0) { - config->colors.validating.outer_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "ringwrongcolor") == 0) { - config->colors.invalid.outer_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "ringcolor") == 0) { - config->colors.normal.outer_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "linecolor") == 0) { - config->colors.line = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "separatorcolor") == 0) { - config->colors.separator = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "keyhlcolor") == 0) { - config->colors.input_cursor = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "bshlcolor") == 0) { - config->colors.backspace_cursor = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "indicator-radius") == 0) { - config->radius = atoi(optarg); - } else if (strcmp(long_options[option_index].name, "indicator-thickness") == 0) { - config->thickness = atoi(optarg); - } + case 'f': + daemonize(); break; default: fprintf(stderr, "%s", usage); - exit(EXIT_FAILURE); + return 1; } } - render_data.scaling_mode = SCALING_MODE_STRETCH; - if (strcmp(scaling_mode_str, "stretch") == 0) { - render_data.scaling_mode = SCALING_MODE_STRETCH; - } else if (strcmp(scaling_mode_str, "fill") == 0) { - render_data.scaling_mode = SCALING_MODE_FILL; - } else if (strcmp(scaling_mode_str, "fit") == 0) { - render_data.scaling_mode = SCALING_MODE_FIT; - } else if (strcmp(scaling_mode_str, "center") == 0) { - render_data.scaling_mode = SCALING_MODE_CENTER; - } else if (strcmp(scaling_mode_str, "tile") == 0) { - render_data.scaling_mode = SCALING_MODE_TILE; - } else { - sway_abort("Unsupported scaling mode: %s", scaling_mode_str); + wl_list_init(&state.contexts); + + assert(state.display = wl_display_connect(NULL)); + + struct wl_registry *registry = wl_display_get_registry(state.display); + wl_registry_add_listener(registry, ®istry_listener, &state); + wl_display_roundtrip(state.display); + assert(state.compositor && state.layer_shell && state.shm); + + if (wl_list_empty(&state.contexts)) { + wlr_log(L_DEBUG, "Exiting - no outputs to show on."); + return 0; } - password_size = 1024; - password = malloc(password_size); - password[0] = '\0'; - render_data.surfaces = create_list(); - if (!socket_path) { - socket_path = get_socketpath(); - if (!socket_path) { - sway_abort("Unable to retrieve socket path"); - } + struct swaylock_context *context; + wl_list_for_each(context, &state.contexts, link) { + assert(context->surface = + wl_compositor_create_surface(state.compositor)); + + context->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + state.layer_shell, context->surface, context->output, + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen"); + assert(context->layer_surface); + + zwlr_layer_surface_v1_set_size(context->layer_surface, 0, 0); + zwlr_layer_surface_v1_set_anchor(context->layer_surface, + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); + zwlr_layer_surface_v1_set_exclusive_zone(context->layer_surface, -1); + zwlr_layer_surface_v1_set_keyboard_interactivity( + context->layer_surface, true); + zwlr_layer_surface_v1_add_listener(context->layer_surface, + &layer_surface_listener, context); + wl_surface_commit(context->surface); + wl_display_roundtrip(state.display); } - if (!registry) { - sway_abort("Unable to connect to wayland compositor"); + state.run_display = true; + while (wl_display_dispatch(state.display) != -1 && state.run_display) { + // This space intentionally left blank } - - if (!registry->swaylock) { - sway_abort("swaylock requires the compositor to support the swaylock extension."); - } - - if (registry->pointer) { - // We don't want swaylock to have a pointer - wl_pointer_destroy(registry->pointer); - registry->pointer = NULL; - } - - for (i = 0; i < registry->outputs->length; ++i) { - struct output_state *output = registry->outputs->items[i]; - struct window *window = window_setup(registry, - output->width, output->height, output->scale, true); - if (!window) { - sway_abort("Failed to create surfaces."); - } - list_add(render_data.surfaces, window); - } - - registry->input->notify = notify_key; - - // Different background for the output - if (render_data.num_images >= 1) { - char **displays_paths = images; - render_data.images = calloc(registry->outputs->length, sizeof(cairo_surface_t*)); - - int socketfd = ipc_open_socket(socket_path); - uint32_t len = 0; - char *outputs = ipc_single_command(socketfd, IPC_GET_OUTPUTS, "", &len); - struct json_object *json_outputs = json_tokener_parse(outputs); - - for (i = 0; i < registry->outputs->length; ++i) { - if (displays_paths[i * 2] != NULL) { - for (int j = 0;; ++j) { - if (j >= json_object_array_length(json_outputs)) { - sway_log(L_ERROR, "%s is not an extant output", displays_paths[i * 2]); - exit(EXIT_FAILURE); - } - - struct json_object *dsp_name, *at_j = json_object_array_get_idx(json_outputs, j); - if (!json_object_object_get_ex(at_j, "name", &dsp_name)) { - sway_abort("output doesn't have a name field"); - } - if (!strcmp(displays_paths[i * 2], json_object_get_string(dsp_name))) { - render_data.images[j] = load_image(displays_paths[i * 2 + 1]); - break; - } - } - } - } - - json_object_put(json_outputs); - close(socketfd); - free(displays_paths); - } - - render(&render_data, config); - bool locked = false; - while (wl_display_dispatch(registry->display) != -1) { - if (!locked) { - for (i = 0; i < registry->outputs->length; ++i) { - struct output_state *output = registry->outputs->items[i]; - struct window *window = render_data.surfaces->items[i]; - lock_set_lock_surface(registry->swaylock, output->output, window->surface); - } - locked = true; - } - } - - // Free surfaces - if (render_data.num_images == -1) { - cairo_surface_destroy(render_data.image); - } else if (render_data.num_images >= 1) { - for (i = 0; i < registry->outputs->length; ++i) { - if (render_data.images[i] != NULL) { - cairo_surface_destroy(render_data.images[i]); - } - } - free(render_data.images); - } - - for (i = 0; i < render_data.surfaces->length; ++i) { - struct window *window = render_data.surfaces->items[i]; - window_teardown(window); - } - list_free(render_data.surfaces); - registry_teardown(registry); - - free_config(config); - return 0; } - -void render(struct render_data *render_data, struct lock_config *config) { - int i; - for (i = 0; i < render_data->surfaces->length; ++i) { - sway_log(L_DEBUG, "Render surface %d of %d", i, render_data->surfaces->length); - struct window *window = render_data->surfaces->items[i]; - if (!window_prerender(window) || !window->cairo) { - continue; - } - int wwidth = window->width * window->scale; - int wheight = window->height * window->scale; - - cairo_save(window->cairo); - cairo_set_operator(window->cairo, CAIRO_OPERATOR_CLEAR); - cairo_paint(window->cairo); - cairo_restore(window->cairo); - - // Reset the transformation matrix - cairo_identity_matrix(window->cairo); - - if (render_data->num_images == 0 || render_data->color_set) { - render_color(window, render_data->color); - } - - if (render_data->num_images == -1) { - // One background for all - render_image(window, render_data->image, render_data->scaling_mode); - } else if (render_data->num_images >= 1) { - // Different backgrounds - if (render_data->images[i] != NULL) { - render_image(window, render_data->images[i], render_data->scaling_mode); - } - } - - // Reset the transformation matrix again - cairo_identity_matrix(window->cairo); - - // Draw specific values (copied from i3) - const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; - const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; - - // Add visual indicator - if (show_indicator && render_data->auth_state != AUTH_STATE_IDLE) { - // Draw circle - cairo_set_line_width(window->cairo, config->thickness); - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, 0, 2 * M_PI); - switch (render_data->auth_state) { - case AUTH_STATE_INPUT: - case AUTH_STATE_BACKSPACE: { - cairo_set_source_u32(window->cairo, config->colors.normal.inner_ring); - cairo_fill_preserve(window->cairo); - cairo_set_source_u32(window->cairo, config->colors.normal.outer_ring); - cairo_stroke(window->cairo); - } break; - case AUTH_STATE_VALIDATING: { - cairo_set_source_u32(window->cairo, config->colors.validating.inner_ring); - cairo_fill_preserve(window->cairo); - cairo_set_source_u32(window->cairo, config->colors.validating.outer_ring); - cairo_stroke(window->cairo); - } break; - case AUTH_STATE_INVALID: { - cairo_set_source_u32(window->cairo, config->colors.invalid.inner_ring); - cairo_fill_preserve(window->cairo); - cairo_set_source_u32(window->cairo, config->colors.invalid.outer_ring); - cairo_stroke(window->cairo); - } break; - default: break; - } - - // Draw a message - char *text = NULL; - cairo_set_source_u32(window->cairo, config->colors.text); - cairo_select_font_face(window->cairo, config->font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(window->cairo, config->radius/3.0f); - switch (render_data->auth_state) { - case AUTH_STATE_VALIDATING: - text = "verifying"; - break; - case AUTH_STATE_INVALID: - text = "wrong"; - break; - default: break; - } - - if (text) { - cairo_text_extents_t extents; - double x, y; - - cairo_text_extents(window->cairo, text, &extents); - x = wwidth/2 - ((extents.width/2) + extents.x_bearing); - y = wheight/2 - ((extents.height/2) + extents.y_bearing); - - cairo_move_to(window->cairo, x, y); - cairo_show_text(window->cairo, text); - cairo_close_path(window->cairo); - cairo_new_sub_path(window->cairo); - } - - // Typing indicator: Highlight random part on keypress - if (render_data->auth_state == AUTH_STATE_INPUT || render_data->auth_state == AUTH_STATE_BACKSPACE) { - static double highlight_start = 0; - highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); - if (render_data->auth_state == AUTH_STATE_INPUT) { - cairo_set_source_u32(window->cairo, config->colors.input_cursor); - } else { - cairo_set_source_u32(window->cairo, config->colors.backspace_cursor); - } - cairo_stroke(window->cairo); - - // Draw borders - cairo_set_source_u32(window->cairo, config->colors.separator); - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); - cairo_stroke(window->cairo); - - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start + TYPE_INDICATOR_RANGE, (highlight_start + TYPE_INDICATOR_RANGE) + TYPE_INDICATOR_BORDER_THICKNESS); - cairo_stroke(window->cairo); - } - - switch(line_source) { - case LINE_SOURCE_RING: - switch(render_data->auth_state) { - case AUTH_STATE_VALIDATING: - cairo_set_source_u32(window->cairo, config->colors.validating.outer_ring); - break; - case AUTH_STATE_INVALID: - cairo_set_source_u32(window->cairo, config->colors.invalid.outer_ring); - break; - default: - cairo_set_source_u32(window->cairo, config->colors.normal.outer_ring); - } - break; - case LINE_SOURCE_INSIDE: - switch(render_data->auth_state) { - case AUTH_STATE_VALIDATING: - cairo_set_source_u32(window->cairo, config->colors.validating.inner_ring); - break; - case AUTH_STATE_INVALID: - cairo_set_source_u32(window->cairo, config->colors.invalid.inner_ring); - break; - default: - cairo_set_source_u32(window->cairo, config->colors.normal.inner_ring); - break; - } - break; - default: - cairo_set_source_u32(window->cairo, config->colors.line); - break; - } - // Draw inner + outer border of the circle - cairo_set_line_width(window->cairo, 2.0); - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius - config->thickness/2, 0, 2*M_PI); - cairo_stroke(window->cairo); - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius + config->thickness/2, 0, 2*M_PI); - cairo_stroke(window->cairo); - } - window_render(window); - } -} diff --git a/swaylock/meson.build b/swaylock/meson.build new file mode 100644 index 000000000..5b886ded6 --- /dev/null +++ b/swaylock/meson.build @@ -0,0 +1,18 @@ +executable( + 'swaylock', + 'main.c', + include_directories: [sway_inc], + dependencies: [ + cairo, + client_protos, + gdk_pixbuf, + libpam, + math, + pango, + pangocairo, + wayland_client, + wlroots, + ], + link_with: [lib_sway_common, lib_sway_client], + install: true +) From 402e1d90f01256365f589972b7b2fc4462224ed1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 22:55:30 -0400 Subject: [PATCH 417/522] Grab keyboard off of the seat --- swaylock/main.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/swaylock/main.c b/swaylock/main.c index 8673694d2..948d661be 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -93,11 +93,51 @@ static void layer_surface_closed(void *data, context->state->run_display = false; } -struct zwlr_layer_surface_v1_listener layer_surface_listener = { +static struct zwlr_layer_surface_v1_listener layer_surface_listener = { .configure = layer_surface_configure, .closed = layer_surface_closed, }; +static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, + uint32_t format, int32_t fd, uint32_t size) { + // TODO +} + +static void keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { + // Who cares +} + +static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *surface) { + // Who cares +} + +static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { + // TODO +} + +static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) { + // TODO +} + +static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, + int32_t rate, int32_t delay) { + // TODO +} + +static struct wl_keyboard_listener keyboard_listener = { + .keymap = keyboard_keymap, + .enter = keyboard_enter, + .leave = keyboard_leave, + .key = keyboard_key, + .modifiers = keyboard_modifiers, + .repeat_info = keyboard_repeat_info, +}; + static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { @@ -143,7 +183,7 @@ static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, // Who cares } -struct wl_pointer_listener pointer_listener = { +static struct wl_pointer_listener pointer_listener = { .enter = wl_pointer_enter, .leave = wl_pointer_leave, .motion = wl_pointer_motion, @@ -157,10 +197,15 @@ struct wl_pointer_listener pointer_listener = { static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { + struct swaylock_state *state = data; if ((caps & WL_SEAT_CAPABILITY_POINTER)) { struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(pointer, &pointer_listener, NULL); } + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { + struct wl_keyboard *keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(keyboard, &keyboard_listener, state); + } } static void seat_handle_name(void *data, struct wl_seat *wl_seat, @@ -185,7 +230,7 @@ static void handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, wl_seat_interface.name) == 0) { struct wl_seat *seat = wl_registry_bind( registry, name, &wl_seat_interface, 1); - wl_seat_add_listener(seat, &seat_listener, NULL); + wl_seat_add_listener(seat, &seat_listener, state); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { state->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); From 0bd40ce86bf53b4349aae1e98aae50bcd86b2505 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 23:07:43 -0400 Subject: [PATCH 418/522] Set up an XKB context for the keyboard --- swaylock/main.c | 104 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/swaylock/main.c b/swaylock/main.c index 948d661be..555b1d64e 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -8,11 +8,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "background-image.h" #include "pool-buffer.h" #include "cairo.h" @@ -25,6 +27,59 @@ struct swaylock_args { bool show_indicator; }; +enum mod_bit { + MOD_SHIFT = 1<<0, + MOD_CAPS = 1<<1, + MOD_CTRL = 1<<2, + MOD_ALT = 1<<3, + MOD_MOD2 = 1<<4, + MOD_MOD3 = 1<<5, + MOD_LOGO = 1<<6, + MOD_MOD5 = 1<<7, +}; + +enum mask { + MASK_SHIFT, + MASK_CAPS, + MASK_CTRL, + MASK_ALT, + MASK_MOD2, + MASK_MOD3, + MASK_LOGO, + MASK_MOD5, + MASK_LAST +}; + +const char *XKB_MASK_NAMES[MASK_LAST] = { + XKB_MOD_NAME_SHIFT, + XKB_MOD_NAME_CAPS, + XKB_MOD_NAME_CTRL, + XKB_MOD_NAME_ALT, + "Mod2", + "Mod3", + XKB_MOD_NAME_LOGO, + "Mod5", +}; + +const enum mod_bit XKB_MODS[MASK_LAST] = { + MOD_SHIFT, + MOD_CAPS, + MOD_CTRL, + MOD_ALT, + MOD_MOD2, + MOD_MOD3, + MOD_LOGO, + MOD_MOD5 +}; + +struct swaylock_xkb { + uint32_t modifiers; + struct xkb_state *state; + struct xkb_context *context; + struct xkb_keymap *keymap; + xkb_mod_mask_t masks[MASK_LAST]; +}; + struct swaylock_state { struct wl_display *display; struct wl_compositor *compositor; @@ -32,6 +87,7 @@ struct swaylock_state { struct wl_shm *shm; struct wl_list contexts; struct swaylock_args args; + struct swaylock_xkb xkb; bool run_display; }; @@ -100,7 +156,29 @@ static struct zwlr_layer_surface_v1_listener layer_surface_listener = { static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { - // TODO + struct swaylock_state *state = data; + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); + wlr_log(L_ERROR, "Unknown keymap format %d, aborting", format); + exit(1); + } + char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_shm == MAP_FAILED) { + close(fd); + wlr_log(L_ERROR, "Unable to initialize keymap shm, aborting"); + exit(1); + } + struct xkb_keymap *keymap = xkb_keymap_new_from_string( + state->xkb.context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, 0); + munmap(map_shm, size); + close(fd); + assert(keymap); + struct xkb_state *xkb_state = xkb_state_new(keymap); + assert(xkb_state); + xkb_keymap_unref(state->xkb.keymap); + xkb_state_unref(state->xkb.state); + state->xkb.keymap = keymap; + state->xkb.state = xkb_state; } static void keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, @@ -114,14 +192,30 @@ static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, } static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { - // TODO + uint32_t serial, uint32_t time, uint32_t key, uint32_t _key_state) { + struct swaylock_state *state = data; + enum wl_keyboard_key_state key_state = _key_state; + xkb_keysym_t sym = xkb_state_key_get_one_sym(state->xkb.state, key + 8); + uint32_t keycode = key_state == WL_KEYBOARD_KEY_STATE_PRESSED ? + key + 8 : 0; + uint32_t codepoint = xkb_state_key_get_utf32(state->xkb.state, keycode); + wlr_log(L_DEBUG, "%c %d", codepoint, sym); } static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { - // TODO + struct swaylock_state *state = data; + xkb_state_update_mask(state->xkb.state, + mods_depressed, mods_latched, mods_locked, 0, 0, group); + xkb_mod_mask_t mask = xkb_state_serialize_mods(state->xkb.state, + XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + state->xkb.modifiers = 0; + for (uint32_t i = 0; i < MASK_LAST; ++i) { + if (mask & state->xkb.masks[i]) { + state->xkb.modifiers |= XKB_MODS[i]; + } + } } static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, @@ -345,7 +439,7 @@ int main(int argc, char **argv) { } wl_list_init(&state.contexts); - + state.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(state.display = wl_display_connect(NULL)); struct wl_registry *registry = wl_display_get_registry(state.display); From 1008d4cc9105e18074f8152ec5d6679aef8ebc5f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 23:14:37 -0400 Subject: [PATCH 419/522] Split seat code into its own file --- include/swaylock/seat.h | 38 ++++++ include/swaylock/swaylock.h | 85 +++++-------- swaylock/main.c | 246 +----------------------------------- swaylock/meson.build | 6 +- swaylock/seat.c | 187 +++++++++++++++++++++++++++ 5 files changed, 262 insertions(+), 300 deletions(-) create mode 100644 include/swaylock/seat.h create mode 100644 swaylock/seat.c diff --git a/include/swaylock/seat.h b/include/swaylock/seat.h new file mode 100644 index 000000000..44bc37d55 --- /dev/null +++ b/include/swaylock/seat.h @@ -0,0 +1,38 @@ +#ifndef _SWAYLOCK_SEAT_H +#define _SWAYLOCK_SEAT_H +#include + +enum mod_bit { + MOD_SHIFT = 1<<0, + MOD_CAPS = 1<<1, + MOD_CTRL = 1<<2, + MOD_ALT = 1<<3, + MOD_MOD2 = 1<<4, + MOD_MOD3 = 1<<5, + MOD_LOGO = 1<<6, + MOD_MOD5 = 1<<7, +}; + +enum mask { + MASK_SHIFT, + MASK_CAPS, + MASK_CTRL, + MASK_ALT, + MASK_MOD2, + MASK_MOD3, + MASK_LOGO, + MASK_MOD5, + MASK_LAST +}; + +struct swaylock_xkb { + uint32_t modifiers; + struct xkb_state *state; + struct xkb_context *context; + struct xkb_keymap *keymap; + xkb_mod_mask_t masks[MASK_LAST]; +}; + +extern const struct wl_seat_listener seat_listener; + +#endif diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index eeed094e0..e2673aae1 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -1,66 +1,41 @@ #ifndef _SWAYLOCK_H #define _SWAYLOCK_H +#include +#include +#include +#include "background-image.h" +#include "cairo.h" +#include "pool-buffer.h" +#include "swaylock/seat.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" -#include "client/cairo.h" - -enum scaling_mode { - SCALING_MODE_STRETCH, - SCALING_MODE_FILL, - SCALING_MODE_FIT, - SCALING_MODE_CENTER, - SCALING_MODE_TILE, -}; - -enum auth_state { - AUTH_STATE_IDLE, - AUTH_STATE_INPUT, - AUTH_STATE_BACKSPACE, - AUTH_STATE_VALIDATING, - AUTH_STATE_INVALID, -}; - -enum line_source { - LINE_SOURCE_DEFAULT, - LINE_SOURCE_RING, - LINE_SOURCE_INSIDE, -}; - -struct render_data { - list_t *surfaces; - // Output specific images - cairo_surface_t **images; - // OR one image for all outputs: - cairo_surface_t *image; - int num_images; - int color_set; +struct swaylock_args { uint32_t color; - enum scaling_mode scaling_mode; - enum auth_state auth_state; + enum background_mode mode; + bool show_indicator; }; -struct lock_colors { - uint32_t inner_ring; - uint32_t outer_ring; +struct swaylock_state { + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; + struct wl_list contexts; + struct swaylock_args args; + struct swaylock_xkb xkb; + bool run_display; }; -struct lock_config { - char *font; - - struct { - uint32_t text; - uint32_t line; - uint32_t separator; - uint32_t input_cursor; - uint32_t backspace_cursor; - struct lock_colors normal; - struct lock_colors validating; - struct lock_colors invalid; - } colors; - - int radius; - int thickness; +struct swaylock_context { + cairo_surface_t *image; + struct swaylock_state *state; + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; + uint32_t width, height; + struct wl_list link; }; -void render(struct render_data* render_data, struct lock_config *config); - #endif diff --git a/swaylock/main.c b/swaylock/main.c index 555b1d64e..7602e47e1 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -8,101 +8,19 @@ #include #include #include -#include #include #include #include #include #include -#include +#include "swaylock/seat.h" +#include "swaylock/swaylock.h" #include "background-image.h" #include "pool-buffer.h" #include "cairo.h" #include "util.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -struct swaylock_args { - uint32_t color; - enum background_mode mode; - bool show_indicator; -}; - -enum mod_bit { - MOD_SHIFT = 1<<0, - MOD_CAPS = 1<<1, - MOD_CTRL = 1<<2, - MOD_ALT = 1<<3, - MOD_MOD2 = 1<<4, - MOD_MOD3 = 1<<5, - MOD_LOGO = 1<<6, - MOD_MOD5 = 1<<7, -}; - -enum mask { - MASK_SHIFT, - MASK_CAPS, - MASK_CTRL, - MASK_ALT, - MASK_MOD2, - MASK_MOD3, - MASK_LOGO, - MASK_MOD5, - MASK_LAST -}; - -const char *XKB_MASK_NAMES[MASK_LAST] = { - XKB_MOD_NAME_SHIFT, - XKB_MOD_NAME_CAPS, - XKB_MOD_NAME_CTRL, - XKB_MOD_NAME_ALT, - "Mod2", - "Mod3", - XKB_MOD_NAME_LOGO, - "Mod5", -}; - -const enum mod_bit XKB_MODS[MASK_LAST] = { - MOD_SHIFT, - MOD_CAPS, - MOD_CTRL, - MOD_ALT, - MOD_MOD2, - MOD_MOD3, - MOD_LOGO, - MOD_MOD5 -}; - -struct swaylock_xkb { - uint32_t modifiers; - struct xkb_state *state; - struct xkb_context *context; - struct xkb_keymap *keymap; - xkb_mod_mask_t masks[MASK_LAST]; -}; - -struct swaylock_state { - struct wl_display *display; - struct wl_compositor *compositor; - struct zwlr_layer_shell_v1 *layer_shell; - struct wl_shm *shm; - struct wl_list contexts; - struct swaylock_args args; - struct swaylock_xkb xkb; - bool run_display; -}; - -struct swaylock_context { - cairo_surface_t *image; - struct swaylock_state *state; - struct wl_output *output; - struct wl_surface *surface; - struct zwlr_layer_surface_v1 *layer_surface; - struct pool_buffer buffers[2]; - struct pool_buffer *current_buffer; - uint32_t width, height; - struct wl_list link; -}; - static void daemonize() { if (fork() == 0) { int devnull = open("/dev/null", O_RDWR); @@ -149,169 +67,11 @@ static void layer_surface_closed(void *data, context->state->run_display = false; } -static struct zwlr_layer_surface_v1_listener layer_surface_listener = { +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { .configure = layer_surface_configure, .closed = layer_surface_closed, }; -static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, - uint32_t format, int32_t fd, uint32_t size) { - struct swaylock_state *state = data; - if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { - close(fd); - wlr_log(L_ERROR, "Unknown keymap format %d, aborting", format); - exit(1); - } - char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (map_shm == MAP_FAILED) { - close(fd); - wlr_log(L_ERROR, "Unable to initialize keymap shm, aborting"); - exit(1); - } - struct xkb_keymap *keymap = xkb_keymap_new_from_string( - state->xkb.context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, 0); - munmap(map_shm, size); - close(fd); - assert(keymap); - struct xkb_state *xkb_state = xkb_state_new(keymap); - assert(xkb_state); - xkb_keymap_unref(state->xkb.keymap); - xkb_state_unref(state->xkb.state); - state->xkb.keymap = keymap; - state->xkb.state = xkb_state; -} - -static void keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { - // Who cares -} - -static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, struct wl_surface *surface) { - // Who cares -} - -static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, uint32_t time, uint32_t key, uint32_t _key_state) { - struct swaylock_state *state = data; - enum wl_keyboard_key_state key_state = _key_state; - xkb_keysym_t sym = xkb_state_key_get_one_sym(state->xkb.state, key + 8); - uint32_t keycode = key_state == WL_KEYBOARD_KEY_STATE_PRESSED ? - key + 8 : 0; - uint32_t codepoint = xkb_state_key_get_utf32(state->xkb.state, keycode); - wlr_log(L_DEBUG, "%c %d", codepoint, sym); -} - -static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, - uint32_t mods_locked, uint32_t group) { - struct swaylock_state *state = data; - xkb_state_update_mask(state->xkb.state, - mods_depressed, mods_latched, mods_locked, 0, 0, group); - xkb_mod_mask_t mask = xkb_state_serialize_mods(state->xkb.state, - XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); - state->xkb.modifiers = 0; - for (uint32_t i = 0; i < MASK_LAST; ++i) { - if (mask & state->xkb.masks[i]) { - state->xkb.modifiers |= XKB_MODS[i]; - } - } -} - -static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, - int32_t rate, int32_t delay) { - // TODO -} - -static struct wl_keyboard_listener keyboard_listener = { - .keymap = keyboard_keymap, - .enter = keyboard_enter, - .leave = keyboard_leave, - .key = keyboard_key, - .modifiers = keyboard_modifiers, - .repeat_info = keyboard_repeat_info, -}; - -static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, - uint32_t serial, struct wl_surface *surface, - wl_fixed_t surface_x, wl_fixed_t surface_y) { - wl_pointer_set_cursor(wl_pointer, serial, NULL, 0, 0); -} - -static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, - uint32_t serial, struct wl_surface *surface) { - // Who cares -} - -static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, - uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - // Who cares -} - -static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, - uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { - // Who cares -} - -static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, - uint32_t time, uint32_t axis, wl_fixed_t value) { - // Who cares -} - -static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { - // Who cares -} - -static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, - uint32_t axis_source) { - // Who cares -} - -static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, - uint32_t time, uint32_t axis) { - // Who cares -} - -static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, - uint32_t axis, int32_t discrete) { - // Who cares -} - -static struct wl_pointer_listener pointer_listener = { - .enter = wl_pointer_enter, - .leave = wl_pointer_leave, - .motion = wl_pointer_motion, - .button = wl_pointer_button, - .axis = wl_pointer_axis, - .frame = wl_pointer_frame, - .axis_source = wl_pointer_axis_source, - .axis_stop = wl_pointer_axis_stop, - .axis_discrete = wl_pointer_axis_discrete, -}; - -static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, - enum wl_seat_capability caps) { - struct swaylock_state *state = data; - if ((caps & WL_SEAT_CAPABILITY_POINTER)) { - struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(pointer, &pointer_listener, NULL); - } - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { - struct wl_keyboard *keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(keyboard, &keyboard_listener, state); - } -} - -static void seat_handle_name(void *data, struct wl_seat *wl_seat, - const char *name) { - // Who cares -} - -const struct wl_seat_listener seat_listener = { - .capabilities = seat_handle_capabilities, - .name = seat_handle_name, -}; - static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct swaylock_state *state = data; diff --git a/swaylock/meson.build b/swaylock/meson.build index 5b886ded6..2f2733f84 100644 --- a/swaylock/meson.build +++ b/swaylock/meson.build @@ -1,6 +1,8 @@ executable( - 'swaylock', - 'main.c', + 'swaylock', [ + 'main.c', + 'seat.c' + ], include_directories: [sway_inc], dependencies: [ cairo, diff --git a/swaylock/seat.c b/swaylock/seat.c new file mode 100644 index 000000000..522200f23 --- /dev/null +++ b/swaylock/seat.c @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include +#include "swaylock/swaylock.h" +#include "swaylock/seat.h" + +const char *XKB_MASK_NAMES[MASK_LAST] = { + XKB_MOD_NAME_SHIFT, + XKB_MOD_NAME_CAPS, + XKB_MOD_NAME_CTRL, + XKB_MOD_NAME_ALT, + "Mod2", + "Mod3", + XKB_MOD_NAME_LOGO, + "Mod5", +}; + +const enum mod_bit XKB_MODS[MASK_LAST] = { + MOD_SHIFT, + MOD_CAPS, + MOD_CTRL, + MOD_ALT, + MOD_MOD2, + MOD_MOD3, + MOD_LOGO, + MOD_MOD5 +}; + +static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, + uint32_t format, int32_t fd, uint32_t size) { + struct swaylock_state *state = data; + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); + wlr_log(L_ERROR, "Unknown keymap format %d, aborting", format); + exit(1); + } + char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_shm == MAP_FAILED) { + close(fd); + wlr_log(L_ERROR, "Unable to initialize keymap shm, aborting"); + exit(1); + } + struct xkb_keymap *keymap = xkb_keymap_new_from_string( + state->xkb.context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, 0); + munmap(map_shm, size); + close(fd); + assert(keymap); + struct xkb_state *xkb_state = xkb_state_new(keymap); + assert(xkb_state); + xkb_keymap_unref(state->xkb.keymap); + xkb_state_unref(state->xkb.state); + state->xkb.keymap = keymap; + state->xkb.state = xkb_state; +} + +static void keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { + // Who cares +} + +static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *surface) { + // Who cares +} + +static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t time, uint32_t key, uint32_t _key_state) { + struct swaylock_state *state = data; + enum wl_keyboard_key_state key_state = _key_state; + xkb_keysym_t sym = xkb_state_key_get_one_sym(state->xkb.state, key + 8); + uint32_t keycode = key_state == WL_KEYBOARD_KEY_STATE_PRESSED ? + key + 8 : 0; + uint32_t codepoint = xkb_state_key_get_utf32(state->xkb.state, keycode); + wlr_log(L_DEBUG, "%c %d", codepoint, sym); +} + +static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) { + struct swaylock_state *state = data; + xkb_state_update_mask(state->xkb.state, + mods_depressed, mods_latched, mods_locked, 0, 0, group); + xkb_mod_mask_t mask = xkb_state_serialize_mods(state->xkb.state, + XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + state->xkb.modifiers = 0; + for (uint32_t i = 0; i < MASK_LAST; ++i) { + if (mask & state->xkb.masks[i]) { + state->xkb.modifiers |= XKB_MODS[i]; + } + } +} + +static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, + int32_t rate, int32_t delay) { + // TODO +} + +static const struct wl_keyboard_listener keyboard_listener = { + .keymap = keyboard_keymap, + .enter = keyboard_enter, + .leave = keyboard_leave, + .key = keyboard_key, + .modifiers = keyboard_modifiers, + .repeat_info = keyboard_repeat_info, +}; + +static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + wl_pointer_set_cursor(wl_pointer, serial, NULL, 0, 0); +} + +static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) { + // Who cares +} + +static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { + // Who cares +} + +static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + // Who cares +} + +static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { + // Who cares +} + +static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { + // Who cares +} + +static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) { + // Who cares +} + +static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) { + // Who cares +} + +static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) { + // Who cares +} + +static const struct wl_pointer_listener pointer_listener = { + .enter = wl_pointer_enter, + .leave = wl_pointer_leave, + .motion = wl_pointer_motion, + .button = wl_pointer_button, + .axis = wl_pointer_axis, + .frame = wl_pointer_frame, + .axis_source = wl_pointer_axis_source, + .axis_stop = wl_pointer_axis_stop, + .axis_discrete = wl_pointer_axis_discrete, +}; + +static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) { + struct swaylock_state *state = data; + if ((caps & WL_SEAT_CAPABILITY_POINTER)) { + struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(pointer, &pointer_listener, NULL); + } + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { + struct wl_keyboard *keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(keyboard, &keyboard_listener, state); + } +} + +static void seat_handle_name(void *data, struct wl_seat *wl_seat, + const char *name) { + // Who cares +} + +const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; From 1fe3cb8965e70f8f05f28512e66d76c49453a196 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 23:43:19 -0400 Subject: [PATCH 420/522] Link swaylock to xkbcommon --- swaylock/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/swaylock/meson.build b/swaylock/meson.build index 2f2733f84..2a1f029a5 100644 --- a/swaylock/meson.build +++ b/swaylock/meson.build @@ -12,6 +12,7 @@ executable( math, pango, pangocairo, + xkbcommon, wayland_client, wlroots, ], From 066143adef7adc6e76e43e1990db2f75fe984b42 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 14:31:30 -0400 Subject: [PATCH 421/522] Add password buffer, refactor rendering/surfaces --- common/meson.build | 1 + common/unicode.c | 101 ++++++++++++++++++++++++++++++++++++ include/swaylock/swaylock.h | 15 +++++- include/unicode.h | 33 ++++++++++++ swaylock/main.c | 79 +++++++++++----------------- swaylock/meson.build | 2 + swaylock/password.c | 57 ++++++++++++++++++++ swaylock/render.c | 21 ++++++++ swaylock/seat.c | 4 +- 9 files changed, 262 insertions(+), 51 deletions(-) create mode 100644 common/unicode.c create mode 100644 include/unicode.h create mode 100644 swaylock/password.c create mode 100644 swaylock/render.c diff --git a/common/meson.build b/common/meson.build index 851e7bbf5..44a295084 100644 --- a/common/meson.build +++ b/common/meson.build @@ -9,6 +9,7 @@ lib_sway_common = static_library( 'pango.c', 'readline.c', 'stringop.c', + 'unicode.c', 'util.c' ), dependencies: [ diff --git a/common/unicode.c b/common/unicode.c new file mode 100644 index 000000000..38a9b48eb --- /dev/null +++ b/common/unicode.c @@ -0,0 +1,101 @@ +#include +#include +#include "unicode.h" + +size_t utf8_chsize(uint32_t ch) { + if (ch < 0x80) { + return 1; + } else if (ch < 0x800) { + return 2; + } else if (ch < 0x10000) { + return 3; + } + return 4; +} + +static const uint8_t masks[] = { + 0x7F, + 0x1F, + 0x0F, + 0x07, + 0x03, + 0x01 +}; + +uint32_t utf8_decode(const char **char_str) { + uint8_t **s = (uint8_t **)char_str; + + uint32_t cp = 0; + if (**s < 128) { + // shortcut + cp = **s; + ++*s; + return cp; + } + int size = utf8_size((char *)*s); + if (size == -1) { + ++*s; + return UTF8_INVALID; + } + uint8_t mask = masks[size - 1]; + cp = **s & mask; + ++*s; + while (--size) { + cp <<= 6; + cp |= **s & 0x3f; + ++*s; + } + return cp; +} + +size_t utf8_encode(char *str, uint32_t ch) { + size_t len = 0; + uint8_t first; + + if (ch < 0x80) { + first = 0; + len = 1; + } else if (ch < 0x800) { + first = 0xc0; + len = 2; + } else if (ch < 0x10000) { + first = 0xe0; + len = 3; + } else { + first = 0xf0; + len = 4; + } + + for (size_t i = len - 1; i > 0; --i) { + str[i] = (ch & 0x3f) | 0x80; + ch >>= 6; + } + + str[0] = ch | first; + return len; +} + + +static const struct { + uint8_t mask; + uint8_t result; + int octets; +} sizes[] = { + { 0x80, 0x00, 1 }, + { 0xE0, 0xC0, 2 }, + { 0xF0, 0xE0, 3 }, + { 0xF8, 0xF0, 4 }, + { 0xFC, 0xF8, 5 }, + { 0xFE, 0xF8, 6 }, + { 0x80, 0x80, -1 }, +}; + +int utf8_size(const char *s) { + uint8_t c = (uint8_t)*s; + for (size_t i = 0; i < sizeof(sizes) / 2; ++i) { + if ((c & sizes[i].mask) == sizes[i].result) { + return sizes[i].octets; + } + } + return -1; +} diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index e2673aae1..f3b0b58bb 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -15,18 +15,25 @@ struct swaylock_args { bool show_indicator; }; +struct swaylock_password { + size_t size; + size_t len; + char *buffer; +}; + struct swaylock_state { struct wl_display *display; struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; struct wl_shm *shm; - struct wl_list contexts; + struct wl_list surfaces; struct swaylock_args args; + struct swaylock_password password; struct swaylock_xkb xkb; bool run_display; }; -struct swaylock_context { +struct swaylock_surface { cairo_surface_t *image; struct swaylock_state *state; struct wl_output *output; @@ -38,4 +45,8 @@ struct swaylock_context { struct wl_list link; }; +void swaylock_handle_key(struct swaylock_state *state, + xkb_keysym_t keysym, uint32_t codepoint); +void render_frame(struct swaylock_surface *surface); + #endif diff --git a/include/unicode.h b/include/unicode.h new file mode 100644 index 000000000..e2ee9588c --- /dev/null +++ b/include/unicode.h @@ -0,0 +1,33 @@ +#ifndef _SWAY_UNICODE_H +#define _SWAY_UNICODE_H +#include +#include + +// Technically UTF-8 supports up to 6 byte codepoints, but Unicode itself +// doesn't really bother with more than 4. +#define UTF8_MAX_SIZE 4 + +#define UTF8_INVALID 0x80 + +/** + * Grabs the next UTF-8 character and advances the string pointer + */ +uint32_t utf8_decode(const char **str); + +/** + * Encodes a character as UTF-8 and returns the length of that character. + */ +size_t utf8_encode(char *str, uint32_t ch); + +/** + * Returns the size of the next UTF-8 character + */ +int utf8_size(const char *str); + +/** + * Returns the size of a UTF-8 character + */ +size_t utf8_chsize(uint32_t ch); + +#endif + diff --git a/swaylock/main.c b/swaylock/main.c index 7602e47e1..c8fdc2f44 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -32,39 +32,22 @@ static void daemonize() { } } -static void render_frame(struct swaylock_context *context) { - struct swaylock_state *state = context->state; - context->current_buffer = get_next_buffer(state->shm, - context->buffers, context->width, context->height); - cairo_t *cairo = context->current_buffer->cairo; - if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { - cairo_set_source_u32(cairo, state->args.color); - cairo_paint(cairo); - } else { - render_background_image(cairo, context->image, - state->args.mode, context->width, context->height); - } - wl_surface_attach(context->surface, context->current_buffer->buffer, 0, 0); - wl_surface_damage(context->surface, 0, 0, context->width, context->height); - wl_surface_commit(context->surface); -} - static void layer_surface_configure(void *data, - struct zwlr_layer_surface_v1 *surface, + struct zwlr_layer_surface_v1 *layer_surface, uint32_t serial, uint32_t width, uint32_t height) { - struct swaylock_context *context = data; - context->width = width; - context->height = height; - zwlr_layer_surface_v1_ack_configure(surface, serial); - render_frame(context); + struct swaylock_surface *surface = data; + surface->width = width; + surface->height = height; + zwlr_layer_surface_v1_ack_configure(layer_surface, serial); + render_frame(surface); } static void layer_surface_closed(void *data, - struct zwlr_layer_surface_v1 *surface) { - struct swaylock_context *context = data; - zwlr_layer_surface_v1_destroy(context->layer_surface); - wl_surface_destroy(context->surface); - context->state->run_display = false; + struct zwlr_layer_surface_v1 *layer_surface) { + struct swaylock_surface *surface = data; + zwlr_layer_surface_v1_destroy(surface->layer_surface); + wl_surface_destroy(surface->surface); + surface->state->run_display = false; } static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { @@ -89,12 +72,12 @@ static void handle_global(void *data, struct wl_registry *registry, state->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { - struct swaylock_context *context = - calloc(1, sizeof(struct swaylock_context)); - context->state = state; - context->output = wl_registry_bind(registry, name, + struct swaylock_surface *surface = + calloc(1, sizeof(struct swaylock_surface)); + surface->state = state; + surface->output = wl_registry_bind(registry, name, &wl_output_interface, 1); - wl_list_insert(&state->contexts, &context->link); + wl_list_insert(&state->surfaces, &surface->link); } } @@ -198,7 +181,7 @@ int main(int argc, char **argv) { } } - wl_list_init(&state.contexts); + wl_list_init(&state.surfaces); state.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(state.display = wl_display_connect(NULL)); @@ -207,33 +190,33 @@ int main(int argc, char **argv) { wl_display_roundtrip(state.display); assert(state.compositor && state.layer_shell && state.shm); - if (wl_list_empty(&state.contexts)) { + if (wl_list_empty(&state.surfaces)) { wlr_log(L_DEBUG, "Exiting - no outputs to show on."); return 0; } - struct swaylock_context *context; - wl_list_for_each(context, &state.contexts, link) { - assert(context->surface = + struct swaylock_surface *surface; + wl_list_for_each(surface, &state.surfaces, link) { + assert(surface->surface = wl_compositor_create_surface(state.compositor)); - context->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - state.layer_shell, context->surface, context->output, + surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + state.layer_shell, surface->surface, surface->output, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen"); - assert(context->layer_surface); + assert(surface->layer_surface); - zwlr_layer_surface_v1_set_size(context->layer_surface, 0, 0); - zwlr_layer_surface_v1_set_anchor(context->layer_surface, + zwlr_layer_surface_v1_set_size(surface->layer_surface, 0, 0); + zwlr_layer_surface_v1_set_anchor(surface->layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); - zwlr_layer_surface_v1_set_exclusive_zone(context->layer_surface, -1); + zwlr_layer_surface_v1_set_exclusive_zone(surface->layer_surface, -1); zwlr_layer_surface_v1_set_keyboard_interactivity( - context->layer_surface, true); - zwlr_layer_surface_v1_add_listener(context->layer_surface, - &layer_surface_listener, context); - wl_surface_commit(context->surface); + surface->layer_surface, true); + zwlr_layer_surface_v1_add_listener(surface->layer_surface, + &layer_surface_listener, surface); + wl_surface_commit(surface->surface); wl_display_roundtrip(state.display); } diff --git a/swaylock/meson.build b/swaylock/meson.build index 2a1f029a5..3cde47a44 100644 --- a/swaylock/meson.build +++ b/swaylock/meson.build @@ -1,6 +1,8 @@ executable( 'swaylock', [ 'main.c', + 'password.c', + 'render.c', 'seat.c' ], include_directories: [sway_inc], diff --git a/swaylock/password.c b/swaylock/password.c new file mode 100644 index 000000000..da67205de --- /dev/null +++ b/swaylock/password.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include "swaylock/swaylock.h" +#include "swaylock/seat.h" +#include "unicode.h" + +static void backspace(struct swaylock_password *pw) { + if (pw->len != 0) { + pw->buffer[--pw->len] = 0; + } +} + +static void append_ch(struct swaylock_password *pw, uint32_t codepoint) { + if (!pw->buffer) { + pw->size = 8; + if (!(pw->buffer = malloc(pw->size))) { + // TODO: Display error + return; + } + pw->buffer[0] = 0; + } + size_t utf8_size = utf8_chsize(codepoint); + if (pw->len + utf8_size + 1 >= pw->size) { + size_t size = pw->size * 2; + char *buffer = realloc(pw->buffer, size); + if (!buffer) { + // TODO: Display error + return; + } + pw->size = size; + pw->buffer = buffer; + } + utf8_encode(&pw->buffer[pw->len], codepoint); + pw->buffer[pw->len + utf8_size] = 0; + pw->len += utf8_size; +} + +void swaylock_handle_key(struct swaylock_state *state, + xkb_keysym_t keysym, uint32_t codepoint) { + switch (keysym) { + case XKB_KEY_KP_Enter: /* fallthrough */ + case XKB_KEY_Return: + // TODO: Attempt password + break; + case XKB_KEY_BackSpace: + backspace(&state->password); + break; + default: + if (codepoint) { + append_ch(&state->password, codepoint); + } + break; + } +} diff --git a/swaylock/render.c b/swaylock/render.c new file mode 100644 index 000000000..8fc472819 --- /dev/null +++ b/swaylock/render.c @@ -0,0 +1,21 @@ +#include +#include "cairo.h" +#include "background-image.h" +#include "swaylock/swaylock.h" + +void render_frame(struct swaylock_surface *surface) { + struct swaylock_state *state = surface->state; + surface->current_buffer = get_next_buffer(state->shm, + surface->buffers, surface->width, surface->height); + cairo_t *cairo = surface->current_buffer->cairo; + if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { + cairo_set_source_u32(cairo, state->args.color); + cairo_paint(cairo); + } else { + render_background_image(cairo, surface->image, + state->args.mode, surface->width, surface->height); + } + wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); + wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); + wl_surface_commit(surface->surface); +} diff --git a/swaylock/seat.c b/swaylock/seat.c index 522200f23..6c46bb417 100644 --- a/swaylock/seat.c +++ b/swaylock/seat.c @@ -73,7 +73,9 @@ static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t keycode = key_state == WL_KEYBOARD_KEY_STATE_PRESSED ? key + 8 : 0; uint32_t codepoint = xkb_state_key_get_utf32(state->xkb.state, keycode); - wlr_log(L_DEBUG, "%c %d", codepoint, sym); + if (key_state == WL_KEYBOARD_KEY_STATE_PRESSED) { + swaylock_handle_key(state, sym, codepoint); + } } static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, From e902de34db2354335c1cbd6baf2fcf7e82509b63 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 14:49:56 -0400 Subject: [PATCH 422/522] Verify passwords --- swaylock/password.c | 58 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/swaylock/password.c b/swaylock/password.c index da67205de..9af7fe16e 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -7,6 +9,58 @@ #include "swaylock/seat.h" #include "unicode.h" +static int function_conversation(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *data) { + struct swaylock_password *pw = data; + /* PAM expects an array of responses, one for each message */ + struct pam_response *pam_reply = calloc( + num_msg, sizeof(struct pam_response)); + *resp = pam_reply; + for (int i = 0; i < num_msg; ++i) { + switch (msg[i]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + case PAM_PROMPT_ECHO_ON: + pam_reply[i].resp = pw->buffer; + break; + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + break; + } + } + return PAM_SUCCESS; +} + +static bool attempt_password(struct swaylock_password *pw) { + struct passwd *passwd = getpwuid(getuid()); + char *username = passwd->pw_name; + const struct pam_conv local_conversation = { + function_conversation, pw + }; + pam_handle_t *local_auth_handle = NULL; + int pam_err; + if ((pam_err = pam_start("swaylock", username, + &local_conversation, &local_auth_handle)) != PAM_SUCCESS) { + wlr_log(L_ERROR, "PAM returned error %d", pam_err); + } + if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { + wlr_log(L_ERROR, "pam_authenticate failed"); + goto fail; + } + if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { + wlr_log(L_ERROR, "pam_end failed"); + goto fail; + } + // PAM freed this + pw->buffer = NULL; + pw->len = pw->size = 0; + return true; +fail: + // PAM freed this + pw->buffer = NULL; + pw->len = pw->size = 0; + return false; +} + static void backspace(struct swaylock_password *pw) { if (pw->len != 0) { pw->buffer[--pw->len] = 0; @@ -43,7 +97,9 @@ void swaylock_handle_key(struct swaylock_state *state, switch (keysym) { case XKB_KEY_KP_Enter: /* fallthrough */ case XKB_KEY_Return: - // TODO: Attempt password + if (attempt_password(&state->password)) { + exit(0); + } break; case XKB_KEY_BackSpace: backspace(&state->password); From d053acbed6fea0f73eb79ac800c1342f8afadeb8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 15:04:31 -0400 Subject: [PATCH 423/522] R E N D E R I N G --- common/background-image.c | 3 +- include/swaylock/swaylock.h | 10 +++ swaylock/main.c | 14 ++++- swaylock/password.c | 20 ++++-- swaylock/render.c | 121 +++++++++++++++++++++++++++++++++++- 5 files changed, 159 insertions(+), 9 deletions(-) diff --git a/common/background-image.c b/common/background-image.c index 1a6c0df05..e5fb4433e 100644 --- a/common/background-image.c +++ b/common/background-image.c @@ -28,7 +28,8 @@ cairo_surface_t *load_background_image(const char *path) { GError *err = NULL; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); if (!pixbuf) { - wlr_log(L_ERROR, "Failed to load background image."); + wlr_log(L_ERROR, "Failed to load background image (%s).", + err->message); return false; } image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index f3b0b58bb..ddca633d8 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -9,6 +9,14 @@ #include "swaylock/seat.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" +enum auth_state { + AUTH_STATE_IDLE, + AUTH_STATE_INPUT, + AUTH_STATE_BACKSPACE, + AUTH_STATE_VALIDATING, + AUTH_STATE_INVALID, +}; + struct swaylock_args { uint32_t color; enum background_mode mode; @@ -30,6 +38,7 @@ struct swaylock_state { struct swaylock_args args; struct swaylock_password password; struct swaylock_xkb xkb; + enum auth_state auth_state; bool run_display; }; @@ -48,5 +57,6 @@ struct swaylock_surface { void swaylock_handle_key(struct swaylock_state *state, xkb_keysym_t keysym, uint32_t codepoint); void render_frame(struct swaylock_surface *surface); +void render_frames(struct swaylock_state *state); #endif diff --git a/swaylock/main.c b/swaylock/main.c index c8fdc2f44..ce337e247 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -133,6 +133,7 @@ int main(int argc, char **argv) { .color = 0xFFFFFFFF, .show_indicator = true, }; + cairo_surface_t *background_image = NULL; state.args = args; wlr_log_init(L_DEBUG, NULL); @@ -150,8 +151,13 @@ int main(int argc, char **argv) { break; } case 'i': - // TODO - return 1; + // TODO: Multiple background images (bleh) + background_image = load_background_image(optarg); + if (!background_image) { + return 1; + } + state.args.mode = BACKGROUND_MODE_FILL; + break; case 's': state.args.mode = parse_background_mode(optarg); if (state.args.mode == BACKGROUND_MODE_INVALID) { @@ -159,7 +165,7 @@ int main(int argc, char **argv) { } break; case 't': - // TODO + state.args.mode = BACKGROUND_MODE_TILE; break; case 'v': #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE @@ -197,6 +203,8 @@ int main(int argc, char **argv) { struct swaylock_surface *surface; wl_list_for_each(surface, &state.surfaces, link) { + surface->image = background_image; + assert(surface->surface = wl_compositor_create_surface(state.compositor)); diff --git a/swaylock/password.c b/swaylock/password.c index 9af7fe16e..2bdf151fd 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -50,21 +50,23 @@ static bool attempt_password(struct swaylock_password *pw) { wlr_log(L_ERROR, "pam_end failed"); goto fail; } - // PAM freed this + // PAM frees this pw->buffer = NULL; pw->len = pw->size = 0; return true; fail: - // PAM freed this + // PAM frees this pw->buffer = NULL; pw->len = pw->size = 0; return false; } -static void backspace(struct swaylock_password *pw) { +static bool backspace(struct swaylock_password *pw) { if (pw->len != 0) { pw->buffer[--pw->len] = 0; + return true; } + return false; } static void append_ch(struct swaylock_password *pw, uint32_t codepoint) { @@ -97,17 +99,27 @@ void swaylock_handle_key(struct swaylock_state *state, switch (keysym) { case XKB_KEY_KP_Enter: /* fallthrough */ case XKB_KEY_Return: + state->auth_state = AUTH_STATE_VALIDATING; + render_frames(state); if (attempt_password(&state->password)) { exit(0); } + state->auth_state = AUTH_STATE_INVALID; + render_frames(state); break; case XKB_KEY_BackSpace: - backspace(&state->password); + if (backspace(&state->password)) { + state->auth_state = AUTH_STATE_BACKSPACE; + render_frames(state); + } break; default: if (codepoint) { append_ch(&state->password, codepoint); + state->auth_state = AUTH_STATE_INPUT; + render_frames(state); } break; } + // TODO: Expire state in a few seconds } diff --git a/swaylock/render.c b/swaylock/render.c index 8fc472819..90db71e3a 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -1,21 +1,140 @@ #include +#include #include "cairo.h" #include "background-image.h" #include "swaylock/swaylock.h" +#define M_PI 3.14159265358979323846 + void render_frame(struct swaylock_surface *surface) { struct swaylock_state *state = surface->state; surface->current_buffer = get_next_buffer(state->shm, surface->buffers, surface->width, surface->height); cairo_t *cairo = surface->current_buffer->cairo; + cairo_identity_matrix(cairo); if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { cairo_set_source_u32(cairo, state->args.color); cairo_paint(cairo); } else { + // TODO: hidpi render_background_image(cairo, surface->image, - state->args.mode, surface->width, surface->height); + state->args.mode, surface->width, surface->height, 1); } + cairo_identity_matrix(cairo); + + const int ARC_RADIUS = 50; + const int ARC_THICKNESS = 10; + const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; + const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; + if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { + // Draw circle + cairo_set_line_width(cairo, ARC_THICKNESS); + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS, 0, 2 * M_PI); + switch (state->auth_state) { + case AUTH_STATE_INPUT: + case AUTH_STATE_BACKSPACE: { + cairo_set_source_rgba(cairo, 0, 0, 0, 0.75); + cairo_fill_preserve(cairo); + cairo_set_source_rgb(cairo, 51.0 / 255, 125.0 / 255, 0); + cairo_stroke(cairo); + } break; + case AUTH_STATE_VALIDATING: { + cairo_set_source_rgba(cairo, 0, 114.0 / 255, 255.0 / 255, 0.75); + cairo_fill_preserve(cairo); + cairo_set_source_rgb(cairo, 51.0 / 255, 0, 250.0 / 255); + cairo_stroke(cairo); + } break; + case AUTH_STATE_INVALID: { + cairo_set_source_rgba(cairo, 250.0 / 255, 0, 0, 0.75); + cairo_fill_preserve(cairo); + cairo_set_source_rgb(cairo, 125.0 / 255, 51.0 / 255, 0); + cairo_stroke(cairo); + } break; + default: break; + } + + // Draw a message + char *text = NULL; + cairo_set_source_rgb(cairo, 0, 0, 0); + cairo_select_font_face(cairo, "sans-serif", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cairo, ARC_RADIUS / 3.0f); + switch (state->auth_state) { + case AUTH_STATE_VALIDATING: + text = "verifying"; + break; + case AUTH_STATE_INVALID: + text = "wrong"; + break; + default: break; + } + + if (text) { + cairo_text_extents_t extents; + double x, y; + cairo_text_extents(cairo, text, &extents); + x = (surface->width / 2) - + (extents.width / 2 + extents.x_bearing); + y = (surface->height / 2) - + (extents.height / 2 + extents.y_bearing); + + cairo_move_to(cairo, x, y); + cairo_show_text(cairo, text); + cairo_close_path(cairo); + cairo_new_sub_path(cairo); + } + + // Typing indicator: Highlight random part on keypress + if (state->auth_state == AUTH_STATE_INPUT + || state->auth_state == AUTH_STATE_BACKSPACE) { + static double highlight_start = 0; + highlight_start += + (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS, highlight_start, + highlight_start + TYPE_INDICATOR_RANGE); + if (state->auth_state == AUTH_STATE_INPUT) { + cairo_set_source_rgb(cairo, 51.0 / 255, 219.0 / 255, 0); + } else { + cairo_set_source_rgb(cairo, 219.0 / 255, 51.0 / 255, 0); + } + cairo_stroke(cairo); + + // Draw borders + cairo_set_source_rgb(cairo, 0, 0, 0); + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS, highlight_start, + highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); + cairo_stroke(cairo); + + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS, highlight_start + TYPE_INDICATOR_RANGE, + highlight_start + TYPE_INDICATOR_RANGE + + TYPE_INDICATOR_BORDER_THICKNESS); + cairo_stroke(cairo); + } + + // Draw inner + outer border of the circle + cairo_set_source_rgb(cairo, 0, 0, 0); + cairo_set_line_width(cairo, 2.0); + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS - ARC_THICKNESS / 2, 0, 2 * M_PI); + cairo_stroke(cairo); + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS + ARC_THICKNESS / 2, 0, 2 * M_PI); + cairo_stroke(cairo); + } + wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); wl_surface_commit(surface->surface); + wl_display_roundtrip(state->display); +} + +void render_frames(struct swaylock_state *state) { + struct swaylock_surface *surface; + wl_list_for_each(surface, &state->surfaces, link) { + render_frame(surface); + } } From 62a736a1961db42acefc4c5746c0f080b152f2b6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 15:33:02 -0400 Subject: [PATCH 424/522] Actually let's not do that TODO --- swaylock/main.c | 8 -------- swaylock/password.c | 1 - 2 files changed, 9 deletions(-) diff --git a/swaylock/main.c b/swaylock/main.c index ce337e247..7f502eb16 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -93,15 +93,7 @@ static const struct wl_registry_listener registry_listener = { static struct swaylock_state state; -static void sigalarm_handler(int sig) { - signal(SIGALRM, SIG_IGN); - // TODO: Hide typing indicator - signal(SIGALRM, sigalarm_handler); -} - int main(int argc, char **argv) { - signal(SIGALRM, sigalarm_handler); - static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"color", required_argument, NULL, 'c'}, diff --git a/swaylock/password.c b/swaylock/password.c index 2bdf151fd..2927a9a9d 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -121,5 +121,4 @@ void swaylock_handle_key(struct swaylock_state *state, } break; } - // TODO: Expire state in a few seconds } From 3ede718c06194651146f05de4d8889620b159f87 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 15:42:32 -0400 Subject: [PATCH 425/522] Refocus the last focused container on lock exit --- sway/input/seat.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 4a99e9eb4..a6b425989 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -424,11 +424,18 @@ void seat_set_focus(struct sway_seat *seat, void seat_set_focus_layer(struct sway_seat *seat, struct wlr_layer_surface *layer) { - if (!layer) { + if (!layer && seat->focused_layer) { seat->focused_layer = NULL; + struct sway_container *c = seat_get_focus(seat); + if (c) { + wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", c, + container_type_to_str(c->type), c->name); + // Hack to get seat to re-focus the return value of get_focus + seat_set_focus(seat, c->parent); + seat_set_focus(seat, c); + } return; - } - if (seat->focused_layer == layer) { + } else if (!layer || seat->focused_layer == layer) { return; } if (seat->has_focus) { From 06fbd51ff5563f548599615a6baf5a1854bf9983 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 16:16:42 -0400 Subject: [PATCH 426/522] Add input inhibitor to input manager --- include/sway/input/input-manager.h | 5 +++++ include/sway/input/seat.h | 3 +++ sway/input/input-manager.c | 27 +++++++++++++++++++++++++++ sway/input/seat.c | 5 +++++ 4 files changed, 40 insertions(+) diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 8e39a4a7a..89a3ac71b 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -1,6 +1,7 @@ #ifndef _SWAY_INPUT_INPUT_MANAGER_H #define _SWAY_INPUT_INPUT_MANAGER_H #include +#include #include "sway/server.h" #include "sway/config.h" #include "list.h" @@ -23,7 +24,11 @@ struct sway_input_manager { struct wl_list devices; struct wl_list seats; + struct wlr_input_inhibit_manager *inhibit; + struct wl_listener new_input; + struct wl_listener inhibit_activate; + struct wl_listener inhibit_deactivate; }; struct sway_input_manager *input_manager_create(struct sway_server *server); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 137fcd229..53031d70a 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -64,6 +64,9 @@ void seat_set_focus_warp(struct sway_seat *seat, void seat_set_focus_layer(struct sway_seat *seat, struct wlr_layer_surface *layer); +void seat_set_exclusive_client(struct sway_seat *seat, + struct wl_client *client); + struct sway_container *seat_get_focus(struct sway_seat *seat); /** diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index c3507f651..3b2d1d557 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "sway/config.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -263,6 +264,24 @@ static void handle_new_input(struct wl_listener *listener, void *data) { input_device->device_destroy.notify = handle_device_destroy; } +static void handle_inhibit_activate(struct wl_listener *listener, void *data) { + struct sway_input_manager *input_manager = wl_container_of( + listener, input_manager, inhibit_activate); + struct sway_seat *seat; + wl_list_for_each(seat, &input_manager->seats, link) { + seat_set_exclusive_client(seat, input_manager->inhibit->active_client); + } +} + +static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) { + struct sway_input_manager *input_manager = wl_container_of( + listener, input_manager, inhibit_deactivate); + struct sway_seat *seat; + wl_list_for_each(seat, &input_manager->seats, link) { + seat_set_exclusive_client(seat, NULL); + } +} + struct sway_input_manager *input_manager_create( struct sway_server *server) { struct sway_input_manager *input = @@ -281,6 +300,14 @@ struct sway_input_manager *input_manager_create( input->new_input.notify = handle_new_input; wl_signal_add(&server->backend->events.new_input, &input->new_input); + input->inhibit = wlr_input_inhibit_manager_create(server->wl_display); + input->inhibit_activate.notify = handle_inhibit_activate; + wl_signal_add(&input->inhibit->events.activate, + &input->inhibit_activate); + input->inhibit_deactivate.notify = handle_inhibit_deactivate; + wl_signal_add(&input->inhibit->events.deactivate, + &input->inhibit_deactivate); + return input; } diff --git a/sway/input/seat.c b/sway/input/seat.c index a6b425989..318fa9f6f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -460,6 +460,11 @@ void seat_set_focus_layer(struct sway_seat *seat, } } +void seat_set_exclusive_client(struct sway_seat *seat, + struct wl_client *client) { + // TODO +} + struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { return seat_get_focus_by_type(seat, container, C_TYPES); From b7e779491232b825f6edc0b199e7564e93f1e332 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 17:03:29 -0400 Subject: [PATCH 427/522] Implement input-inhibit in sway, swaylock --- include/sway/input/seat.h | 5 ++ include/swaylock/swaylock.h | 1 + protocols/meson.build | 6 +- protocols/wlr-input-inhibitor-unstable-v1.xml | 67 ++++++++++++++++++ sway/input/cursor.c | 6 +- sway/input/input-manager.c | 8 +++ sway/input/seat.c | 68 +++++++++++++++++-- swaylock/main.c | 10 +++ 8 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 protocols/wlr-input-inhibitor-unstable-v1.xml diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 53031d70a..4b0fc3c16 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -32,6 +32,9 @@ struct sway_seat { // If the focused layer is set, views cannot receive keyboard focus struct wlr_layer_surface *focused_layer; + // If exclusive_client is set, no other clients will receive input events + struct wl_client *exclusive_client; + struct wl_listener focus_destroy; struct wl_listener new_container; @@ -88,4 +91,6 @@ void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config); struct seat_config *seat_get_config(struct sway_seat *seat); +bool seat_allow_input(struct sway_seat *seat, struct wlr_surface *surface); + #endif diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index ddca633d8..06c94ead0 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -33,6 +33,7 @@ struct swaylock_state { struct wl_display *display; struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; + struct zwlr_input_inhibit_manager_v1 *input_inhibit_manager; struct wl_shm *shm; struct wl_list surfaces; struct swaylock_args args; diff --git a/protocols/meson.build b/protocols/meson.build index 0887cf866..7f83b16b6 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -22,12 +22,14 @@ wayland_scanner_server = generator( client_protocols = [ [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], - ['wlr-layer-shell-unstable-v1.xml'] + ['wlr-layer-shell-unstable-v1.xml'], + ['wlr-input-inhibitor-unstable-v1.xml'] ] server_protocols = [ [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], - ['wlr-layer-shell-unstable-v1.xml'] + ['wlr-layer-shell-unstable-v1.xml'], + ['wlr-input-inhibitor-unstable-v1.xml'] ] client_protos_src = [] diff --git a/protocols/wlr-input-inhibitor-unstable-v1.xml b/protocols/wlr-input-inhibitor-unstable-v1.xml new file mode 100644 index 000000000..b62d1bb44 --- /dev/null +++ b/protocols/wlr-input-inhibitor-unstable-v1.xml @@ -0,0 +1,67 @@ + + + + Copyright © 2018 Drew DeVault + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + Clients can use this interface to prevent input events from being sent to + any surfaces but its own, which is useful for example in lock screen + software. It is assumed that access to this interface will be locked down + to whitelisted clients by the compositor. + + + + + Activates the input inhibitor. As long as the inhibitor is active, the + compositor will not send input events to other clients. + + + + + + + + + + + + While this resource exists, input to clients other than the owner of the + inhibitor resource will not receive input events. The client that owns + this resource will receive all input events normally. The compositor will + also disable all of its own input processing (such as keyboard shortcuts) + while the inhibitor is active. + + The compositor may continue to send input events to selected clients, + such as an on-screen keyboard (via the input-method protocol). + + + + + Destroy the inhibitor and allow other clients to receive input. + + + + diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 9229e92d1..c56445ebc 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -146,8 +146,10 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, // send pointer enter/leave if (surface != NULL) { - wlr_seat_pointer_notify_enter(seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(seat, time, sx, sy); + if (seat_allow_input(cursor->seat, surface)) { + wlr_seat_pointer_notify_enter(seat, surface, sx, sy); + wlr_seat_pointer_notify_motion(seat, time, sx, sy); + } } else { wlr_seat_pointer_clear_focus(seat); } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 3b2d1d557..f71a06e49 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -279,6 +279,14 @@ static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) struct sway_seat *seat; wl_list_for_each(seat, &input_manager->seats, link) { seat_set_exclusive_client(seat, NULL); + struct sway_container *previous = seat_get_focus(seat); + if (previous) { + wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, + container_type_to_str(previous->type), previous->name); + // Hack to get seat to re-focus the return value of get_focus + seat_set_focus(seat, previous->parent); + seat_set_focus(seat, previous); + } } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 318fa9f6f..0e26dde4b 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,5 +1,7 @@ #define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 199309L #include +#include #include #include #include @@ -9,6 +11,7 @@ #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" #include "sway/ipc-server.h" +#include "sway/layers.h" #include "sway/output.h" #include "sway/tree/container.h" #include "sway/tree/view.h" @@ -350,6 +353,11 @@ void seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } +bool seat_allow_input(struct sway_seat *seat, struct wlr_surface *surface) { + struct wl_client *client = wl_resource_get_client(surface->resource); + return !seat->exclusive_client || seat->exclusive_client == client; +} + void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { if (seat->focused_layer) { @@ -371,6 +379,12 @@ void seat_set_focus_warp(struct sway_seat *seat, wl_list_remove(&seat_con->link); wl_list_insert(&seat->focus_stack, &seat_con->link); + if (container->type == C_VIEW && !seat_allow_input( + seat, container->sway_view->surface)) { + wlr_log(L_DEBUG, "Refusing to set focus, input is inhibited"); + return; + } + if (container->type == C_VIEW) { seat_send_focus(seat, container); } @@ -426,13 +440,13 @@ void seat_set_focus_layer(struct sway_seat *seat, struct wlr_layer_surface *layer) { if (!layer && seat->focused_layer) { seat->focused_layer = NULL; - struct sway_container *c = seat_get_focus(seat); - if (c) { - wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", c, - container_type_to_str(c->type), c->name); + struct sway_container *previous = seat_get_focus(seat); + if (previous) { + wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, + container_type_to_str(previous->type), previous->name); // Hack to get seat to re-focus the return value of get_focus - seat_set_focus(seat, c->parent); - seat_set_focus(seat, c); + seat_set_focus(seat, previous->parent); + seat_set_focus(seat, previous); } return; } else if (!layer || seat->focused_layer == layer) { @@ -462,7 +476,47 @@ void seat_set_focus_layer(struct sway_seat *seat, void seat_set_exclusive_client(struct sway_seat *seat, struct wl_client *client) { - // TODO + if (!client) { + seat->exclusive_client = client; + // Triggers a refocus of the topmost surface layer if necessary + // TODO: Make layer surface focus per-output based on cursor position + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *output = root_container.children->items[i]; + if (!sway_assert(output->type == C_OUTPUT, + "root container has non-output child")) { + continue; + } + arrange_layers(output->sway_output); + } + return; + } + if (seat->focused_layer) { + if (wl_resource_get_client(seat->focused_layer->resource) != client) { + seat_set_focus_layer(seat, NULL); + } + } + if (seat->has_focus) { + struct sway_container *focus = seat_get_focus(seat); + if (focus->type == C_VIEW && wl_resource_get_client( + focus->sway_view->surface->resource) != client) { + seat_set_focus(seat, NULL); + } + } + if (seat->wlr_seat->pointer_state.focused_client) { + if (seat->wlr_seat->pointer_state.focused_client->client != client) { + wlr_seat_pointer_clear_focus(seat->wlr_seat); + } + } + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + struct wlr_touch_point *point; + wl_list_for_each(point, &seat->wlr_seat->touch_state.touch_points, link) { + if (point->client->client != client) { + wlr_seat_touch_point_clear_focus(seat->wlr_seat, + now.tv_nsec / 1000, point->touch_id); + } + } + seat->exclusive_client = client; } struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, diff --git a/swaylock/main.c b/swaylock/main.c index 7f502eb16..6cd4e41d4 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -19,6 +19,7 @@ #include "pool-buffer.h" #include "cairo.h" #include "util.h" +#include "wlr-input-inhibitor-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" static void daemonize() { @@ -71,6 +72,9 @@ static void handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { state->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); + } else if (strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name) == 0) { + state->input_inhibit_manager = wl_registry_bind( + registry, name, &zwlr_input_inhibit_manager_v1_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { struct swaylock_surface *surface = calloc(1, sizeof(struct swaylock_surface)); @@ -187,6 +191,10 @@ int main(int argc, char **argv) { wl_registry_add_listener(registry, ®istry_listener, &state); wl_display_roundtrip(state.display); assert(state.compositor && state.layer_shell && state.shm); + if (!state.input_inhibit_manager) { + wlr_log(L_ERROR, "Compositor does not support the input inhibitor " + "protocol, refusing to run insecurely"); + } if (wl_list_empty(&state.surfaces)) { wlr_log(L_DEBUG, "Exiting - no outputs to show on."); @@ -220,6 +228,8 @@ int main(int argc, char **argv) { wl_display_roundtrip(state.display); } + zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); + state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { // This space intentionally left blank From 46b388995d7d50a39d13fce9417e2ad0d2cf749f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 19:15:14 -0400 Subject: [PATCH 428/522] Add hidpi support to swaylock --- include/swaylock/swaylock.h | 1 + swaylock/main.c | 35 +++++++++++++++++++++++++++++-- swaylock/render.c | 41 +++++++++++++++++++++---------------- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index 06c94ead0..173e8b125 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -52,6 +52,7 @@ struct swaylock_surface { struct pool_buffer buffers[2]; struct pool_buffer *current_buffer; uint32_t width, height; + int32_t scale; struct wl_list link; }; diff --git a/swaylock/main.c b/swaylock/main.c index 6cd4e41d4..1eda3afcd 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -56,12 +56,42 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { .closed = layer_surface_closed, }; +static void output_geometry(void *data, struct wl_output *output, int32_t x, + int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, + const char *make, const char *model, int32_t transform) { + // Who cares +} + +static void output_mode(void *data, struct wl_output *output, uint32_t flags, + int32_t width, int32_t height, int32_t refresh) { + // Who cares +} + +static void output_done(void *data, struct wl_output *output) { + // Who cares +} + +static void output_scale(void *data, struct wl_output *output, int32_t factor) { + struct swaylock_surface *surface = data; + surface->scale = factor; + if (surface->state->run_display) { + render_frames(surface->state); + } +} + +struct wl_output_listener output_listener = { + .geometry = output_geometry, + .mode = output_mode, + .done = output_done, + .scale = output_scale, +}; + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct swaylock_state *state = data; if (strcmp(interface, wl_compositor_interface.name) == 0) { state->compositor = wl_registry_bind(registry, name, - &wl_compositor_interface, 1); + &wl_compositor_interface, 3); } else if (strcmp(interface, wl_shm_interface.name) == 0) { state->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); @@ -80,7 +110,8 @@ static void handle_global(void *data, struct wl_registry *registry, calloc(1, sizeof(struct swaylock_surface)); surface->state = state; surface->output = wl_registry_bind(registry, name, - &wl_output_interface, 1); + &wl_output_interface, 3); + wl_output_add_listener(surface->output, &output_listener, surface); wl_list_insert(&state->surfaces, &surface->link); } } diff --git a/swaylock/render.c b/swaylock/render.c index 90db71e3a..2469e60b1 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -9,28 +9,32 @@ void render_frame(struct swaylock_surface *surface) { struct swaylock_state *state = surface->state; surface->current_buffer = get_next_buffer(state->shm, - surface->buffers, surface->width, surface->height); + surface->buffers, + surface->width * surface->scale, + surface->height * surface->scale); cairo_t *cairo = surface->current_buffer->cairo; cairo_identity_matrix(cairo); + + int buffer_width = surface->width * surface->scale; + int buffer_height = surface->height * surface->scale; if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { cairo_set_source_u32(cairo, state->args.color); cairo_paint(cairo); } else { - // TODO: hidpi render_background_image(cairo, surface->image, - state->args.mode, surface->width, surface->height, 1); + state->args.mode, buffer_width, buffer_height); } cairo_identity_matrix(cairo); - const int ARC_RADIUS = 50; - const int ARC_THICKNESS = 10; - const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; - const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; + int ARC_RADIUS = 50 * surface->scale; + int ARC_THICKNESS = 10 * surface->scale; + float TYPE_INDICATOR_RANGE = M_PI / 3.0f; + float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f * surface->scale; + if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { // Draw circle cairo_set_line_width(cairo, ARC_THICKNESS); - cairo_arc(cairo, surface->width / 2, surface->height / 2, - ARC_RADIUS, 0, 2 * M_PI); + cairo_arc(cairo, buffer_width / 2, buffer_height / 2, ARC_RADIUS, 0, 2 * M_PI); switch (state->auth_state) { case AUTH_STATE_INPUT: case AUTH_STATE_BACKSPACE: { @@ -74,9 +78,9 @@ void render_frame(struct swaylock_surface *surface) { cairo_text_extents_t extents; double x, y; cairo_text_extents(cairo, text, &extents); - x = (surface->width / 2) - + x = (buffer_width / 2) - (extents.width / 2 + extents.x_bearing); - y = (surface->height / 2) - + y = (buffer_height / 2) - (extents.height / 2 + extents.y_bearing); cairo_move_to(cairo, x, y); @@ -91,7 +95,7 @@ void render_frame(struct swaylock_surface *surface) { static double highlight_start = 0; highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; - cairo_arc(cairo, surface->width / 2, surface->height / 2, + cairo_arc(cairo, buffer_width / 2, buffer_height / 2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); if (state->auth_state == AUTH_STATE_INPUT) { @@ -103,12 +107,12 @@ void render_frame(struct swaylock_surface *surface) { // Draw borders cairo_set_source_rgb(cairo, 0, 0, 0); - cairo_arc(cairo, surface->width / 2, surface->height / 2, + cairo_arc(cairo, buffer_width / 2, buffer_height / 2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); cairo_stroke(cairo); - cairo_arc(cairo, surface->width / 2, surface->height / 2, + cairo_arc(cairo, buffer_width / 2, buffer_height / 2, ARC_RADIUS, highlight_start + TYPE_INDICATOR_RANGE, highlight_start + TYPE_INDICATOR_RANGE + TYPE_INDICATOR_BORDER_THICKNESS); @@ -117,17 +121,18 @@ void render_frame(struct swaylock_surface *surface) { // Draw inner + outer border of the circle cairo_set_source_rgb(cairo, 0, 0, 0); - cairo_set_line_width(cairo, 2.0); - cairo_arc(cairo, surface->width / 2, surface->height / 2, + cairo_set_line_width(cairo, 2.0 * surface->scale); + cairo_arc(cairo, buffer_width / 2, buffer_height / 2, ARC_RADIUS - ARC_THICKNESS / 2, 0, 2 * M_PI); cairo_stroke(cairo); - cairo_arc(cairo, surface->width / 2, surface->height / 2, + cairo_arc(cairo, buffer_width / 2, buffer_height / 2, ARC_RADIUS + ARC_THICKNESS / 2, 0, 2 * M_PI); cairo_stroke(cairo); } + wl_surface_set_buffer_scale(surface->surface, surface->scale); wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); - wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); + wl_surface_damage(surface->surface, 0, 0, buffer_width, buffer_height); wl_surface_commit(surface->surface); wl_display_roundtrip(state->display); } From d2d050d59cf19c583b100e6e3637ed9a06a8863f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 21:25:42 -0400 Subject: [PATCH 429/522] Address review feedback --- include/sway/input/seat.h | 2 +- sway/input/cursor.c | 2 +- sway/input/seat.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 4b0fc3c16..d1cfbe4c2 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -91,6 +91,6 @@ void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config); struct seat_config *seat_get_config(struct sway_seat *seat); -bool seat_allow_input(struct sway_seat *seat, struct wlr_surface *surface); +bool seat_is_input_allowed(struct sway_seat *seat, struct wlr_surface *surface); #endif diff --git a/sway/input/cursor.c b/sway/input/cursor.c index c56445ebc..195ddce93 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -146,7 +146,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, // send pointer enter/leave if (surface != NULL) { - if (seat_allow_input(cursor->seat, surface)) { + if (seat_is_input_allowed(cursor->seat, surface)) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); } diff --git a/sway/input/seat.c b/sway/input/seat.c index 0e26dde4b..0699324ab 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -353,7 +353,8 @@ void seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -bool seat_allow_input(struct sway_seat *seat, struct wlr_surface *surface) { +bool seat_is_input_allowed(struct sway_seat *seat, + struct wlr_surface *surface) { struct wl_client *client = wl_resource_get_client(surface->resource); return !seat->exclusive_client || seat->exclusive_client == client; } @@ -379,7 +380,7 @@ void seat_set_focus_warp(struct sway_seat *seat, wl_list_remove(&seat_con->link); wl_list_insert(&seat->focus_stack, &seat_con->link); - if (container->type == C_VIEW && !seat_allow_input( + if (container->type == C_VIEW && !seat_is_input_allowed( seat, container->sway_view->surface)) { wlr_log(L_DEBUG, "Refusing to set focus, input is inhibited"); return; From 0138f79b4aae563e1223737856ab44c8634c76b0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 22:00:29 -0400 Subject: [PATCH 430/522] Move extra roundtrip into password.c --- swaylock/password.c | 1 + swaylock/render.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/swaylock/password.c b/swaylock/password.c index 2927a9a9d..06c1180ca 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -101,6 +101,7 @@ void swaylock_handle_key(struct swaylock_state *state, case XKB_KEY_Return: state->auth_state = AUTH_STATE_VALIDATING; render_frames(state); + wl_display_roundtrip(state->display); if (attempt_password(&state->password)) { exit(0); } diff --git a/swaylock/render.c b/swaylock/render.c index 2469e60b1..79609e96f 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -134,7 +134,6 @@ void render_frame(struct swaylock_surface *surface) { wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); wl_surface_damage(surface->surface, 0, 0, buffer_width, buffer_height); wl_surface_commit(surface->surface); - wl_display_roundtrip(state->display); } void render_frames(struct swaylock_state *state) { From 218a3787d26296103225b7680bacdfd5fc6d2955 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 22:01:29 -0400 Subject: [PATCH 431/522] Import stdlib.h and define POSIX macro for rand() --- swaylock/render.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/swaylock/render.c b/swaylock/render.c index 79609e96f..cb3ed276a 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -1,5 +1,7 @@ -#include +#define _POSIX_C_SOURCE 199506L #include +#include +#include #include "cairo.h" #include "background-image.h" #include "swaylock/swaylock.h" From 053b51c3ff63147aed25400efb42c00ee3de90b9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 22:03:48 -0400 Subject: [PATCH 432/522] exit() needs stdlib.h inb4 acrisci --- swaylock/seat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/swaylock/seat.c b/swaylock/seat.c index 6c46bb417..21db7c4fb 100644 --- a/swaylock/seat.c +++ b/swaylock/seat.c @@ -1,4 +1,5 @@ #include +#include #include #include #include From 3e61718053a7e2cdd94c64f5613c6bdf28e35c8e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 4 Apr 2018 18:52:38 -0400 Subject: [PATCH 433/522] try to fix focus-inactive --- sway/input/seat.c | 22 +++++++++------------- sway/tree/container.c | 10 ++++++++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 4a99e9eb4..078cb8b8e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -467,22 +467,18 @@ struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, struct sway_container *container, enum sway_container_type type) { - struct sway_seat_container *current = NULL; - struct sway_container *parent = NULL; - wl_list_for_each(current, &seat->focus_stack, link) { - parent = current->container->parent; + if (container->type == C_VIEW || container->children->length == 0) { + return container; + } - if (current->container == container && - (type == C_TYPES || container->type == type)) { - return current->container; + struct sway_seat_container *current = NULL; + wl_list_for_each(current, &seat->focus_stack, link) { + if (type != C_TYPES && container->type != type) { + continue; } - while (parent) { - if (parent == container && (type == C_TYPES || - current->container->type == type)) { - return current->container; - } - parent = parent->parent; + if (container_has_child(container, current->container)) { + return current->container; } } diff --git a/sway/tree/container.c b/sway/tree/container.c index 753f333cb..b47a8364b 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -51,12 +51,18 @@ const char *container_type_to_str(enum sway_container_type type) { } void container_create_notify(struct sway_container *container) { + if (container->type != C_VIEW || container->type != C_CONTAINER) { + return; + } // TODO send ipc event type based on the container type wl_signal_emit(&root_container.sway_root->events.new_container, container); ipc_event_window(container, "new"); } static void container_close_notify(struct sway_container *container) { + if (container == NULL) { + return; + } // TODO send ipc event type based on the container type ipc_event_window(container, "close"); } @@ -522,8 +528,8 @@ static bool find_child_func(struct sway_container *con, void *data) { bool container_has_child(struct sway_container *con, struct sway_container *child) { - if (child == NULL || child->type == C_VIEW || - child->children->length == 0) { + if (con == NULL || con->type == C_VIEW || + con->children->length == 0) { return false; } return container_find(con, find_child_func, child); From 5d444b34f6af17894e2808c9d25948db625dabde Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 4 Apr 2018 18:52:44 -0400 Subject: [PATCH 434/522] Address review feedback from @emersion --- swaylock/main.c | 7 ++++--- swaylock/password.c | 3 ++- swaylock/render.c | 46 ++++++++++++++++++++++++--------------------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/swaylock/main.c b/swaylock/main.c index 1eda3afcd..1d5221849 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -216,7 +216,8 @@ int main(int argc, char **argv) { wl_list_init(&state.surfaces); state.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - assert(state.display = wl_display_connect(NULL)); + state.display = wl_display_connect(NULL); + assert(state.display); struct wl_registry *registry = wl_display_get_registry(state.display); wl_registry_add_listener(registry, ®istry_listener, &state); @@ -236,8 +237,8 @@ int main(int argc, char **argv) { wl_list_for_each(surface, &state.surfaces, link) { surface->image = background_image; - assert(surface->surface = - wl_compositor_create_surface(state.compositor)); + surface->surface = wl_compositor_create_surface(state.compositor); + assert(surface->surface); surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( state.layer_shell, surface->surface, surface->output, diff --git a/swaylock/password.c b/swaylock/password.c index 06c1180ca..1839f991b 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -103,7 +103,8 @@ void swaylock_handle_key(struct swaylock_state *state, render_frames(state); wl_display_roundtrip(state->display); if (attempt_password(&state->password)) { - exit(0); + state->run_display = false; + break; } state->auth_state = AUTH_STATE_INVALID; render_frames(state); diff --git a/swaylock/render.c b/swaylock/render.c index cb3ed276a..cd387be55 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -7,18 +7,22 @@ #include "swaylock/swaylock.h" #define M_PI 3.14159265358979323846 +const int ARC_RADIUS = 50; +const int ARC_THICKNESS = 10; +const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; +const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; void render_frame(struct swaylock_surface *surface) { struct swaylock_state *state = surface->state; - surface->current_buffer = get_next_buffer(state->shm, - surface->buffers, - surface->width * surface->scale, - surface->height * surface->scale); - cairo_t *cairo = surface->current_buffer->cairo; - cairo_identity_matrix(cairo); int buffer_width = surface->width * surface->scale; int buffer_height = surface->height * surface->scale; + + surface->current_buffer = get_next_buffer(state->shm, + surface->buffers, buffer_width, buffer_height); + cairo_t *cairo = surface->current_buffer->cairo; + cairo_identity_matrix(cairo); + if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { cairo_set_source_u32(cairo, state->args.color); cairo_paint(cairo); @@ -28,15 +32,15 @@ void render_frame(struct swaylock_surface *surface) { } cairo_identity_matrix(cairo); - int ARC_RADIUS = 50 * surface->scale; - int ARC_THICKNESS = 10 * surface->scale; - float TYPE_INDICATOR_RANGE = M_PI / 3.0f; - float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f * surface->scale; + int arc_radius = ARC_RADIUS * surface->scale; + int arc_thickness = ARC_THICKNESS * surface->scale; + float type_indicator_border_thickness = + TYPE_INDICATOR_BORDER_THICKNESS * surface->scale; if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { // Draw circle - cairo_set_line_width(cairo, ARC_THICKNESS); - cairo_arc(cairo, buffer_width / 2, buffer_height / 2, ARC_RADIUS, 0, 2 * M_PI); + cairo_set_line_width(cairo, arc_thickness); + cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, 0, 2 * M_PI); switch (state->auth_state) { case AUTH_STATE_INPUT: case AUTH_STATE_BACKSPACE: { @@ -65,7 +69,7 @@ void render_frame(struct swaylock_surface *surface) { cairo_set_source_rgb(cairo, 0, 0, 0); cairo_select_font_face(cairo, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cairo, ARC_RADIUS / 3.0f); + cairo_set_font_size(cairo, arc_radius / 3.0f); switch (state->auth_state) { case AUTH_STATE_VALIDATING: text = "verifying"; @@ -98,7 +102,7 @@ void render_frame(struct swaylock_surface *surface) { highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; cairo_arc(cairo, buffer_width / 2, buffer_height / 2, - ARC_RADIUS, highlight_start, + arc_radius, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); if (state->auth_state == AUTH_STATE_INPUT) { cairo_set_source_rgb(cairo, 51.0 / 255, 219.0 / 255, 0); @@ -110,14 +114,14 @@ void render_frame(struct swaylock_surface *surface) { // Draw borders cairo_set_source_rgb(cairo, 0, 0, 0); cairo_arc(cairo, buffer_width / 2, buffer_height / 2, - ARC_RADIUS, highlight_start, - highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); + arc_radius, highlight_start, + highlight_start + type_indicator_border_thickness); cairo_stroke(cairo); cairo_arc(cairo, buffer_width / 2, buffer_height / 2, - ARC_RADIUS, highlight_start + TYPE_INDICATOR_RANGE, + arc_radius, highlight_start + TYPE_INDICATOR_RANGE, highlight_start + TYPE_INDICATOR_RANGE + - TYPE_INDICATOR_BORDER_THICKNESS); + type_indicator_border_thickness); cairo_stroke(cairo); } @@ -125,16 +129,16 @@ void render_frame(struct swaylock_surface *surface) { cairo_set_source_rgb(cairo, 0, 0, 0); cairo_set_line_width(cairo, 2.0 * surface->scale); cairo_arc(cairo, buffer_width / 2, buffer_height / 2, - ARC_RADIUS - ARC_THICKNESS / 2, 0, 2 * M_PI); + arc_radius - arc_thickness / 2, 0, 2 * M_PI); cairo_stroke(cairo); cairo_arc(cairo, buffer_width / 2, buffer_height / 2, - ARC_RADIUS + ARC_THICKNESS / 2, 0, 2 * M_PI); + arc_radius + arc_thickness / 2, 0, 2 * M_PI); cairo_stroke(cairo); } wl_surface_set_buffer_scale(surface->surface, surface->scale); wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); - wl_surface_damage(surface->surface, 0, 0, buffer_width, buffer_height); + wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); wl_surface_commit(surface->surface); } From cfd806577b9ba6049cc3dec3cd78168bfb7ca4db Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 4 Apr 2018 19:37:01 -0400 Subject: [PATCH 435/522] fix sending window new event --- sway/tree/container.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index b47a8364b..92c00f837 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -51,12 +51,12 @@ const char *container_type_to_str(enum sway_container_type type) { } void container_create_notify(struct sway_container *container) { - if (container->type != C_VIEW || container->type != C_CONTAINER) { - return; - } // TODO send ipc event type based on the container type wl_signal_emit(&root_container.sway_root->events.new_container, container); - ipc_event_window(container, "new"); + + if (container->type == C_VIEW || container->type == C_CONTAINER) { + ipc_event_window(container, "new"); + } } static void container_close_notify(struct sway_container *container) { From fc9398a42e1dfc15bbb8490c049981034abb4926 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 3 Apr 2018 00:47:45 -0400 Subject: [PATCH 436/522] Implement opacity command --- include/sway/commands.h | 1 + include/sway/tree/container.h | 2 ++ sway/commands.c | 1 + sway/commands/opacity.c | 39 +++++++++++++++++++++++++++++++++++ sway/desktop/output.c | 34 ++++++++++++++++-------------- sway/meson.build | 1 + sway/sway.5.txt | 4 ++++ sway/tree/container.c | 2 ++ 8 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 sway/commands/opacity.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 66f097ea0..edb5a2135 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -123,6 +123,7 @@ sway_cmd cmd_mark; sway_cmd cmd_mode; sway_cmd cmd_mouse_warping; sway_cmd cmd_move; +sway_cmd cmd_opacity; sway_cmd cmd_new_float; sway_cmd cmd_new_window; sway_cmd cmd_no_focus; diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 277165ea8..3a3a94292 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -83,6 +83,8 @@ struct sway_container { list_t *marks; // list of char* + float alpha; + struct { struct wl_signal destroy; // Raised after the tree updates, but before arrange_windows diff --git a/sway/commands.c b/sway/commands.c index 8156a08e0..2786a8791 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -163,6 +163,7 @@ static struct cmd_handler command_handlers[] = { { "kill", cmd_kill }, { "layout", cmd_layout }, { "move", cmd_move }, + { "opacity", cmd_opacity }, { "reload", cmd_reload }, { "split", cmd_split }, { "splith", cmd_splith }, diff --git a/sway/commands/opacity.c b/sway/commands/opacity.c new file mode 100644 index 000000000..b8cd1f09a --- /dev/null +++ b/sway/commands/opacity.c @@ -0,0 +1,39 @@ +#include +#include +#include "sway/commands.h" +#include "sway/tree/view.h" +#include "log.h" + +static bool parse_opacity(const char *opacity, float *val) { + char *err; + *val = strtof(opacity, &err); + if (*val < 0 || *val > 1 || *err) { + return false; + } + return true; +} + +struct cmd_results *cmd_opacity(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "layout", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + struct sway_container *con = + config->handler_context.current_container; + + float opacity = 0.0f; + + if (!parse_opacity(argv[0], &opacity)) { + return cmd_results_new(CMD_INVALID, "opacity ", + "Invalid value (expected 0..1): %s", argv[0]); + } + + con->alpha = opacity; + + if (con->type == C_VIEW) { + view_damage_whole(con->sway_view); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 8a4fb4a2d..6cf5da48f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -75,7 +75,7 @@ static bool surface_intersect_output(struct wlr_surface *surface, static void render_surface(struct wlr_surface *surface, struct wlr_output *wlr_output, struct timespec *when, - double ox, double oy, float rotation) { + double ox, double oy, float rotation, float alpha) { struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); @@ -95,8 +95,8 @@ static void render_surface(struct wlr_surface *surface, wlr_matrix_project_box(matrix, &box, transform, rotation, wlr_output->transform_matrix); - // TODO: configurable alpha - wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f); + wlr_render_texture_with_matrix(renderer, surface->texture, + matrix, alpha); wlr_surface_send_frame_done(surface, when); } @@ -110,13 +110,13 @@ static void render_surface(struct wlr_surface *surface, surface->current->width, surface->current->height, rotation); render_surface(subsurface->surface, wlr_output, when, - ox + sx, oy + sy, rotation); + ox + sx, oy + sy, rotation, alpha); } } static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, struct wlr_output *wlr_output, struct timespec *when, double base_x, - double base_y, float rotation) { + double base_y, float rotation, float alpha) { double width = surface->surface->current->width; double height = surface->surface->current->height; @@ -136,19 +136,19 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, width, height, rotation); render_surface(popup->surface, wlr_output, when, - base_x + popup_sx, base_y + popup_sy, rotation); + base_x + popup_sx, base_y + popup_sy, rotation, alpha); render_xdg_v6_popups(popup, wlr_output, when, - base_x + popup_sx, base_y + popup_sy, rotation); + base_x + popup_sx, base_y + popup_sy, rotation, alpha); } } static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, struct wlr_output *wlr_output, struct timespec *when, - double lx, double ly, float rotation, + double lx, double ly, float rotation, float alpha, bool is_child) { if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) { render_surface(surface->surface, wlr_output, when, - lx, ly, rotation); + lx, ly, rotation, alpha); double width = surface->surface->current->width; double height = surface->surface->current->height; @@ -164,7 +164,7 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, width, height, rotation); render_wl_shell_surface(popup, wlr_output, when, - lx + popup_x, ly + popup_y, rotation, true); + lx + popup_x, ly + popup_y, rotation, alpha, true); } } } @@ -181,6 +181,7 @@ static void render_view(struct sway_container *view, void *data) { struct wlr_output *wlr_output = output->wlr_output; struct sway_view *sway_view = view->sway_view; struct wlr_surface *surface = sway_view->surface; + float alpha = sway_view->swayc->alpha; if (!surface) { return; @@ -191,17 +192,18 @@ static void render_view(struct sway_container *view, void *data) { int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; render_surface(surface, wlr_output, when, - view->x - window_offset_x, view->y - window_offset_y, 0); + view->x - window_offset_x, view->y - window_offset_y, 0, alpha); render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, - when, view->x - window_offset_x, view->y - window_offset_y, 0); + when, view->x - window_offset_x, view->y - window_offset_y, 0, alpha); break; } case SWAY_WL_SHELL_VIEW: render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, - when, view->x, view->y, 0, false); + when, view->x, view->y, 0, alpha, false); break; case SWAY_XWAYLAND_VIEW: - render_surface(surface, wlr_output, when, view->x, view->y, 0); + render_surface(surface, wlr_output, when, view->x, view->y, + 0, alpha); break; default: break; @@ -214,7 +216,7 @@ static void render_layer(struct sway_output *output, struct timespec *when, wl_list_for_each(sway_layer, layer, link) { struct wlr_layer_surface *layer = sway_layer->layer_surface; render_surface(layer->surface, output->wlr_output, when, - sway_layer->geo.x, sway_layer->geo.y, 0); + sway_layer->geo.x, sway_layer->geo.y, 0, 1.0f); wlr_surface_send_frame_done(layer->surface, when); } } @@ -288,7 +290,7 @@ static void render_output(struct sway_output *output, struct timespec *when, } render_surface(xsurface->surface, wlr_output, &output->last_frame, - view_box.x - output_box->x, view_box.y - output_box->y, 0); + view_box.x - output_box->x, view_box.y - output_box->y, 0, 1.0f); } // TODO: Consider revising this when fullscreen windows are supported diff --git a/sway/meson.build b/sway/meson.build index 91aab0a0b..f210c195b 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -15,6 +15,7 @@ sway_sources = files( 'commands/focus.c', 'commands/focus_follows_mouse.c', 'commands/kill.c', + 'commands/opacity.c', 'commands/include.c', 'commands/input.c', 'commands/layout.c', diff --git a/sway/sway.5.txt b/sway/sway.5.txt index 900e499aa..59c3295aa 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -413,6 +413,10 @@ The default colors are: However, any mark that starts with an underscore will not be drawn even if the option is on. The default option is _on_. +**opacity** :: + Set the opacity of the window between 0 (completely transparent) and 1 + (completely opaque). + **unmark** :: **Unmark** will remove _identifier_ from the list of current marks on a window. If no _identifier_ is specified, then **unmark** will remove all marks. diff --git a/sway/tree/container.c b/sway/tree/container.c index 753f333cb..3be086454 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -72,6 +72,8 @@ struct sway_container *container_create(enum sway_container_type type) { c->layout = L_NONE; c->workspace_layout = L_NONE; c->type = type; + c->alpha = 1.0f; + if (type != C_VIEW) { c->children = create_list(); } From 679c51e4214dda459d73c2074d4e9afdf56ed992 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 4 Apr 2018 15:34:39 -0400 Subject: [PATCH 437/522] Remove unused sway_view.unmanaged_link --- include/sway/tree/view.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 4b84205ed..6bc5ceda9 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -101,9 +101,6 @@ struct sway_view { struct sway_xwayland_surface *sway_xwayland_surface; struct sway_wl_shell_surface *sway_wl_shell_surface; }; - - // only used for unmanaged views (shell specific) - struct wl_list unmanaged_view_link; // sway_root::unmanaged_views }; struct sway_view *view_create(enum sway_view_type type, From 8eff00f72395add1881aa677e3c718c0554cb096 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 4 Apr 2018 15:53:46 -0400 Subject: [PATCH 438/522] Remove unused SWAY_VIEW_TYPES --- include/sway/tree/view.h | 8 +++---- sway/desktop/output.c | 9 ++++---- sway/desktop/wl_shell.c | 4 ++-- sway/desktop/xdg_shell_v6.c | 4 ++-- sway/desktop/xwayland.c | 4 ++-- sway/input/seat.c | 2 +- sway/tree/container.c | 43 +++++++++++++++++-------------------- 7 files changed, 34 insertions(+), 40 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 6bc5ceda9..f32ccc5ae 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -59,11 +59,9 @@ struct sway_wl_shell_surface { }; enum sway_view_type { - SWAY_WL_SHELL_VIEW, - SWAY_XDG_SHELL_V6_VIEW, - SWAY_XWAYLAND_VIEW, - // Keep last - SWAY_VIEW_TYPES, + SWAY_VIEW_WL_SHELL, + SWAY_VIEW_XDG_SHELL_V6, + SWAY_VIEW_XWAYLAND, }; enum sway_view_prop { diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6cf5da48f..38b52a41c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -188,7 +188,7 @@ static void render_view(struct sway_container *view, void *data) { } switch (sway_view->type) { - case SWAY_XDG_SHELL_V6_VIEW: { + case SWAY_VIEW_XDG_SHELL_V6: { int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; render_surface(surface, wlr_output, when, @@ -197,13 +197,12 @@ static void render_view(struct sway_container *view, void *data) { when, view->x - window_offset_x, view->y - window_offset_y, 0, alpha); break; } - case SWAY_WL_SHELL_VIEW: + case SWAY_VIEW_WL_SHELL: render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, when, view->x, view->y, 0, alpha, false); break; - case SWAY_XWAYLAND_VIEW: - render_surface(surface, wlr_output, when, view->x, view->y, - 0, alpha); + case SWAY_VIEW_XWAYLAND: + render_surface(surface, wlr_output, when, view->x, view->y, 0, alpha); break; default: break; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 6528a3972..a470674da 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -12,7 +12,7 @@ #include "log.h" static bool assert_wl_shell(struct sway_view *view) { - return sway_assert(view->type == SWAY_WL_SHELL_VIEW, + return sway_assert(view->type == SWAY_VIEW_WL_SHELL, "Expecting wl_shell view!"); } @@ -97,7 +97,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW, &view_impl); + struct sway_view *view = view_create(SWAY_VIEW_WL_SHELL, &view_impl); if (!sway_assert(view, "Failed to allocate view")) { return; } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 49305b39e..5cdb8f9f6 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -12,7 +12,7 @@ #include "log.h" static bool assert_xdg(struct sway_view *view) { - return sway_assert(view->type == SWAY_XDG_SHELL_V6_VIEW, + return sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, "Expected xdg shell v6 view!"); } @@ -126,7 +126,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW, &view_impl); + struct sway_view *view = view_create(SWAY_VIEW_XDG_SHELL_V6, &view_impl); if (!sway_assert(view, "Failed to allocate view")) { return; } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index bfef68cf3..a793928cf 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -42,7 +42,7 @@ static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { static bool assert_xwayland(struct sway_view *view) { - return sway_assert(view->type == SWAY_XWAYLAND_VIEW, + return sway_assert(view->type == SWAY_VIEW_XWAYLAND, "Expected xwayland view!"); } @@ -185,7 +185,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { return; } - struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW, &view_impl); + struct sway_view *view = view_create(SWAY_VIEW_XWAYLAND, &view_impl); if (!sway_assert(view, "Failed to allocate view")) { return; } diff --git a/sway/input/seat.c b/sway/input/seat.c index 0699324ab..87dbd8701 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -66,7 +66,7 @@ static void seat_send_focus(struct sway_seat *seat, return; } struct sway_view *view = con->sway_view; - if (view->type == SWAY_XWAYLAND_VIEW) { + if (view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland *xwayland = seat->input->server->xwayland; wlr_xwayland_set_seat(xwayland, seat->wlr_seat); diff --git a/sway/tree/container.c b/sway/tree/container.c index 3be086454..1ea107592 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -413,31 +413,28 @@ struct sway_container *container_at(struct sway_container *parent, double view_sy = oy - swayc->y; switch (sview->type) { - case SWAY_WL_SHELL_VIEW: - break; - case SWAY_XDG_SHELL_V6_VIEW: - // the top left corner of the sway container is the - // coordinate of the top left corner of the window geometry - view_sx += sview->wlr_xdg_surface_v6->geometry.x; - view_sy += sview->wlr_xdg_surface_v6->geometry.y; + case SWAY_VIEW_XWAYLAND: + case SWAY_VIEW_WL_SHELL: + break; + case SWAY_VIEW_XDG_SHELL_V6: + // the top left corner of the sway container is the + // coordinate of the top left corner of the window geometry + view_sx += sview->wlr_xdg_surface_v6->geometry.x; + view_sy += sview->wlr_xdg_surface_v6->geometry.y; - // check for popups - double popup_sx, popup_sy; - struct wlr_xdg_surface_v6 *popup = - wlr_xdg_surface_v6_popup_at(sview->wlr_xdg_surface_v6, - view_sx, view_sy, &popup_sx, &popup_sy); + // check for popups + double popup_sx, popup_sy; + struct wlr_xdg_surface_v6 *popup = + wlr_xdg_surface_v6_popup_at(sview->wlr_xdg_surface_v6, + view_sx, view_sy, &popup_sx, &popup_sy); - if (popup) { - *sx = view_sx - popup_sx; - *sy = view_sy - popup_sy; - *surface = popup->surface; - return swayc; - } - break; - case SWAY_XWAYLAND_VIEW: - break; - default: - break; + if (popup) { + *sx = view_sx - popup_sx; + *sy = view_sy - popup_sy; + *surface = popup->surface; + return swayc; + } + break; } // check for subsurfaces From 44b8d30f5254628f8e6d5a12010f6e5f810d756e Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 4 Apr 2018 17:57:12 -0400 Subject: [PATCH 439/522] Use new wlr_*_surface_at functions --- sway/desktop/output.c | 2 -- sway/tree/container.c | 45 +++++++++++++++---------------------------- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 38b52a41c..0e8a94858 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -204,8 +204,6 @@ static void render_view(struct sway_container *view, void *data) { case SWAY_VIEW_XWAYLAND: render_surface(surface, wlr_output, when, view->x, view->y, 0, alpha); break; - default: - break; } } diff --git a/sway/tree/container.c b/sway/tree/container.c index 1ea107592..bd9f1edfc 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -412,9 +412,17 @@ struct sway_container *container_at(struct sway_container *parent, double view_sx = ox - swayc->x; double view_sy = oy - swayc->y; + double _sx, _sy; + struct wlr_surface *_surface; switch (sview->type) { case SWAY_VIEW_XWAYLAND: + _surface = wlr_surface_surface_at(sview->surface, + view_sx, view_sy, &_sx, &_sy); + break; case SWAY_VIEW_WL_SHELL: + _surface = wlr_wl_shell_surface_surface_at( + sview->wlr_wl_shell_surface, + view_sx, view_sy, &_sx, &_sy); break; case SWAY_VIEW_XDG_SHELL_V6: // the top left corner of the sway container is the @@ -422,38 +430,15 @@ struct sway_container *container_at(struct sway_container *parent, view_sx += sview->wlr_xdg_surface_v6->geometry.x; view_sy += sview->wlr_xdg_surface_v6->geometry.y; - // check for popups - double popup_sx, popup_sy; - struct wlr_xdg_surface_v6 *popup = - wlr_xdg_surface_v6_popup_at(sview->wlr_xdg_surface_v6, - view_sx, view_sy, &popup_sx, &popup_sy); - - if (popup) { - *sx = view_sx - popup_sx; - *sy = view_sy - popup_sy; - *surface = popup->surface; - return swayc; - } + _surface = wlr_xdg_surface_v6_surface_at( + sview->wlr_xdg_surface_v6, + view_sx, view_sy, &_sx, &_sy); break; } - - // check for subsurfaces - double sub_x, sub_y; - struct wlr_subsurface *subsurface = - wlr_surface_subsurface_at(sview->surface, - view_sx, view_sy, &sub_x, &sub_y); - if (subsurface) { - *sx = view_sx - sub_x; - *sy = view_sy - sub_y; - *surface = subsurface->surface; - return swayc; - } - - if (wlr_surface_point_accepts_input( - sview->surface, view_sx, view_sy)) { - *sx = view_sx; - *sy = view_sy; - *surface = swayc->sway_view->surface; + if (_surface) { + *sx = _sx; + *sy = _sy; + *surface = _surface; return swayc; } } else { From deda37469ad4e21ad86b7c83c7c8a966301b9d5e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 4 Apr 2018 22:31:10 -0400 Subject: [PATCH 440/522] fix focus child --- sway/input/seat.c | 4 ++-- sway/tree/layout.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 078cb8b8e..50134aae5 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -123,7 +123,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) { - if (con->type < C_WORKSPACE) { + if (con->type == C_ROOT || con->type == C_OUTPUT) { // these don't get seat containers ever return NULL; } @@ -473,7 +473,7 @@ struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, struct sway_seat_container *current = NULL; wl_list_for_each(current, &seat->focus_stack, link) { - if (type != C_TYPES && container->type != type) { + if (current->container->type != type && type != C_TYPES) { continue; } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 5abdbc321..1769609bd 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -638,16 +638,16 @@ struct sway_container *container_get_in_direction( wrap_candidate = parent->children->items[0]; } if (config->force_focus_wrapping) { - return seat_get_focus_by_type(seat, - wrap_candidate, C_VIEW); + return wrap_candidate; } } } else { + struct sway_container *desired_con = 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 seat_get_focus_by_type(seat, - parent->children->items[desired], C_VIEW); + container, dir, desired, desired_con); + struct sway_container *next = seat_get_focus_by_type(seat, desired_con, C_VIEW); + return next; } } From 04ce09630c7d84f3215a0f877f85f9e0855244b5 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 4 Apr 2018 22:41:05 -0400 Subject: [PATCH 441/522] add type to container json --- sway/ipc-json.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 3427c8ec3..54824a361 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -132,6 +132,7 @@ static void ipc_json_describe_workspace(struct sway_container *workspace, 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_object_add(object, "type", json_object_new_string("con")); } json_object *ipc_json_describe_container(struct sway_container *c) { From f77986338fc4186d003908012685c12d718ed647 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 4 Apr 2018 21:32:31 -0400 Subject: [PATCH 442/522] Implement resize command --- config.in | 16 +-- include/sway/tree/layout.h | 10 ++ sway/commands.c | 1 + sway/commands/resize.c | 284 +++++++++++++++++++++++++++++++++++++ sway/meson.build | 46 +++--- sway/tree/layout.c | 21 +++ 6 files changed, 351 insertions(+), 27 deletions(-) create mode 100644 sway/commands/resize.c diff --git a/config.in b/config.in index 086b66dc6..54817f2ac 100644 --- a/config.in +++ b/config.in @@ -164,16 +164,16 @@ mode "resize" { # right will grow the containers width # up will shrink the containers height # down will grow the containers height - bindsym $left resize shrink width 10 px or 10 ppt - bindsym $down resize grow height 10 px or 10 ppt - bindsym $up resize shrink height 10 px or 10 ppt - bindsym $right resize grow width 10 px or 10 ppt + bindsym $left resize shrink width 10px + bindsym $down resize grow height 10px + bindsym $up resize shrink height 10px + bindsym $right resize grow width 10px # ditto, with arrow keys - bindsym Left resize shrink width 10 px or 10 ppt - bindsym Down resize grow height 10 px or 10 ppt - bindsym Up resize shrink height 10 px or 10 ppt - bindsym Right resize grow width 10 px or 10 ppt + bindsym Left resize shrink width 10px + bindsym Down resize grow height 10px + bindsym Up resize shrink height 10px + bindsym Right resize grow width 10px # return to default mode bindsym Return mode "default" diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 784dcc9b1..fc5ce21f8 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -13,6 +13,13 @@ enum movement_direction { MOVE_CHILD, }; +enum resize_edge { + RESIZE_EDGE_LEFT, + RESIZE_EDGE_RIGHT, + RESIZE_EDGE_TOP, + RESIZE_EDGE_BOTTOM, +}; + struct sway_container; struct sway_root { @@ -63,4 +70,7 @@ struct sway_container *container_get_in_direction(struct sway_container struct sway_container *container_split(struct sway_container *child, enum sway_container_layout layout); +void container_recursive_resize(struct sway_container *container, + double amount, enum resize_edge edge); + #endif diff --git a/sway/commands.c b/sway/commands.c index 2786a8791..22decef36 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -165,6 +165,7 @@ static struct cmd_handler command_handlers[] = { { "move", cmd_move }, { "opacity", cmd_opacity }, { "reload", cmd_reload }, + { "resize", cmd_resize }, { "split", cmd_split }, { "splith", cmd_splith }, { "splitt", cmd_splitt }, diff --git a/sway/commands/resize.c b/sway/commands/resize.c new file mode 100644 index 000000000..93c1fe7de --- /dev/null +++ b/sway/commands/resize.c @@ -0,0 +1,284 @@ +#include +#include +#include +#include +#include +#include +#include +#include "sway/commands.h" +#include "sway/tree/layout.h" +#include "log.h" + +static const int MIN_SANE_W = 100, MIN_SANE_H = 60; + +enum resize_unit { + RESIZE_UNIT_PX, + RESIZE_UNIT_PPT, + RESIZE_UNIT_DEFAULT, + RESIZE_UNIT_INVALID, +}; + +enum resize_axis { + RESIZE_AXIS_HORIZONTAL, + RESIZE_AXIS_VERTICAL, + RESIZE_AXIS_INVALID, +}; + +static enum resize_unit parse_resize_unit(const char *unit) { + if (strcasecmp(unit, "px") == 0) { + return RESIZE_UNIT_PX; + } + if (strcasecmp(unit, "ppt") == 0) { + return RESIZE_UNIT_PPT; + } + if (strcasecmp(unit, "default") == 0) { + return RESIZE_UNIT_DEFAULT; + } + return RESIZE_UNIT_INVALID; +} + +static enum resize_axis parse_resize_axis(const char *axis) { + if (strcasecmp(axis, "width") == 0 || strcasecmp(axis, "horizontal") == 0) { + return RESIZE_AXIS_HORIZONTAL; + } + if (strcasecmp(axis, "height") == 0 || strcasecmp(axis, "vertical") == 0) { + return RESIZE_AXIS_VERTICAL; + } + return RESIZE_AXIS_INVALID; +} + +static int parallel_coord(struct sway_container *c, enum resize_axis a) { + return a == RESIZE_AXIS_HORIZONTAL ? c->x : c->y; +} + +static int parallel_size(struct sway_container *c, enum resize_axis a) { + return a == RESIZE_AXIS_HORIZONTAL ? c->width : c->height; +} + +static void resize_tiled(int amount, enum resize_axis axis) { + struct sway_container *parent = config->handler_context.current_container; + struct sway_container *focused = parent; + if (!parent) { + return; + } + + enum sway_container_layout parallel_layout = + axis == RESIZE_AXIS_HORIZONTAL ? L_HORIZ : L_VERT; + int minor_weight = 0; + int major_weight = 0; + while (parent->parent) { + struct sway_container *next = parent->parent; + if (next->layout == parallel_layout) { + for (int i = 0; i < next->children->length; i++) { + struct sway_container *sibling = next->children->items[i]; + + int sibling_pos = parallel_coord(sibling, axis); + int focused_pos = parallel_coord(focused, axis); + int parent_pos = parallel_coord(parent, axis); + + if (sibling_pos != focused_pos) { + if (sibling_pos < parent_pos) { + minor_weight++; + } else if (sibling_pos > parent_pos) { + major_weight++; + } + } + } + if (major_weight || minor_weight) { + break; + } + } + parent = next; + } + + if (parent->type == C_ROOT) { + return; + } + + wlr_log(L_DEBUG, + "Found the proper parent: %p. It has %d l conts, and %d r conts", + parent->parent, minor_weight, major_weight); + + int min_sane = axis == RESIZE_AXIS_HORIZONTAL ? MIN_SANE_W : MIN_SANE_H; + + //TODO: Ensure rounding is done in such a way that there are NO pixel leaks + // ^ ????? + + for (int i = 0; i < parent->parent->children->length; i++) { + struct sway_container *sibling = parent->parent->children->items[i]; + + int sibling_pos = parallel_coord(sibling, axis); + int focused_pos = parallel_coord(focused, axis); + int parent_pos = parallel_coord(parent, axis); + + int sibling_size = parallel_size(sibling, axis); + int parent_size = parallel_size(parent, axis); + + if (sibling_pos != focused_pos) { + if (sibling_pos < parent_pos) { + double pixels = -amount / minor_weight; + if (major_weight && (sibling_size + pixels / 2) < min_sane) { + return; // Too small + } else if ((sibling_size + pixels) < min_sane) { + return; // Too small + } + } else if (sibling_pos > parent_pos) { + double pixels = -amount / major_weight; + if (minor_weight && (sibling_size + pixels / 2) < min_sane) { + return; // Too small + } else if ((sibling_size + pixels) < min_sane) { + return; // Too small + } + } + } else { + double pixels = amount; + if (parent_size + pixels < min_sane) { + return; // Too small + } + } + } + + enum resize_edge minor_edge = axis == RESIZE_AXIS_HORIZONTAL ? + RESIZE_EDGE_LEFT : RESIZE_EDGE_TOP; + enum resize_edge major_edge = axis == RESIZE_AXIS_HORIZONTAL ? + RESIZE_EDGE_RIGHT : RESIZE_EDGE_BOTTOM; + + for (int i = 0; i < parent->parent->children->length; i++) { + struct sway_container *sibling = parent->parent->children->items[i]; + + int sibling_pos = parallel_coord(sibling, axis); + int focused_pos = parallel_coord(focused, axis); + int parent_pos = parallel_coord(parent, axis); + + if (sibling_pos != focused_pos) { + if (sibling_pos < parent_pos) { + double pixels = -1 * amount; + pixels /= minor_weight; + if (major_weight) { + container_recursive_resize(sibling, pixels / 2, major_edge); + } else { + container_recursive_resize(sibling, pixels, major_edge); + } + } else if (sibling_pos > parent_pos) { + double pixels = -1 * amount; + pixels /= major_weight; + if (minor_weight) { + container_recursive_resize(sibling, pixels / 2, minor_edge); + } else { + container_recursive_resize(sibling, pixels, minor_edge); + } + } + } else { + if (major_weight != 0 && minor_weight != 0) { + double pixels = amount; + pixels /= 2; + container_recursive_resize(parent, pixels, minor_edge); + container_recursive_resize(parent, pixels, major_edge); + } else if (major_weight) { + container_recursive_resize(parent, amount, major_edge); + } else if (minor_weight) { + container_recursive_resize(parent, amount, minor_edge); + } + } + } + + arrange_windows(parent->parent, -1, -1); +} + +static void resize(int amount, enum resize_axis axis, enum resize_unit unit) { + struct sway_container *current = config->handler_context.current_container; + if (unit == RESIZE_UNIT_DEFAULT) { + // Default for tiling; TODO floating should be px + unit = RESIZE_UNIT_PPT; + } + + if (unit == RESIZE_UNIT_PPT) { + float pct = amount / 100.0f; + switch (axis) { + case RESIZE_AXIS_HORIZONTAL: + amount = (float)current->width * pct; + break; + case RESIZE_AXIS_VERTICAL: + amount = (float)current->height * pct; + break; + default: + sway_assert(0, "invalid resize axis"); + return; + } + } + + return resize_tiled(amount, axis); +} + +struct cmd_results *cmd_resize(int argc, char **argv) { + struct sway_container *current = config->handler_context.current_container; + if (!current) { + return cmd_results_new(CMD_INVALID, "resize", "Cannot resize nothing"); + } + if (current->type != C_VIEW && current->type != C_CONTAINER) { + return cmd_results_new(CMD_INVALID, "resize", + "Can only resize views/containers"); + } + if (strcasecmp(argv[0], "set") == 0) { + // TODO + //return cmd_resize_set(argc - 1, &argv[1]); + return cmd_results_new(CMD_INVALID, "resize", "resize set unimplemented"); + } + struct cmd_results *error; + if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { + return error; + } + + // TODO: resize grow|shrink left|right|up|down + + const char *usage = "Expected 'resize " + " [] [px|ppt]'"; + + int multiplier = 0; + if (strcasecmp(*argv, "grow") == 0) { + multiplier = 1; + } else if (strcasecmp(*argv, "shrink") == 0) { + multiplier = -1; + } else { + return cmd_results_new(CMD_INVALID, "resize", usage); + } + --argc; ++argv; + + enum resize_axis axis = parse_resize_axis(*argv); + if (axis == RESIZE_AXIS_INVALID) { + return cmd_results_new(CMD_INVALID, "resize", usage); + } + --argc; ++argv; + + int amount = 10; // Default amount + enum resize_unit unit = RESIZE_UNIT_DEFAULT; + + if (argc) { + char *err; + amount = (int)strtol(*argv, &err, 10); + if (*err) { + // e.g. `resize grow width 10px` + unit = parse_resize_unit(err); + if (unit == RESIZE_UNIT_INVALID) { + return cmd_results_new(CMD_INVALID, "resize", usage); + } + } + --argc; ++argv; + } + + if (argc) { + unit = parse_resize_unit(*argv); + if (unit == RESIZE_UNIT_INVALID) { + return cmd_results_new(CMD_INVALID, "resize", usage); + } + --argc; ++argv; + } + + if (argc) { + // Provied too many args, the bastard + return cmd_results_new(CMD_INVALID, "resize", usage); + } + + resize(amount * multiplier, axis, unit); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index f210c195b..ec7b4c42b 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -2,10 +2,28 @@ sway_sources = files( 'main.c', 'server.c', 'commands.c', + 'config.c', + 'criteria.c', + 'ipc-json.c', + 'ipc-server.c', + 'security.c', + + 'desktop/output.c', + 'desktop/layer_shell.c', + 'desktop/wl_shell.c', + 'desktop/xdg_shell_v6.c', + 'desktop/xwayland.c', + 'input/input-manager.c', 'input/seat.c', 'input/cursor.c', 'input/keyboard.c', + + 'config/bar.c', + 'config/output.c', + 'config/seat.c', + 'config/input.c', + 'commands/bar.c', 'commands/bind.c', 'commands/default_orientation.c', @@ -20,13 +38,19 @@ sway_sources = files( 'commands/input.c', 'commands/layout.c', 'commands/mode.c', - 'commands/split.c', + 'commands/mouse_warping.c', 'commands/move.c', + 'commands/output.c', + 'commands/reload.c', + 'commands/resize.c', 'commands/seat.c', 'commands/seat/attach.c', 'commands/seat/fallback.c', 'commands/set.c', + 'commands/split.c', 'commands/swaybg_command.c', + 'commands/workspace.c', + 'commands/bar/activate_button.c', 'commands/bar/binding_mode_indicator.c', 'commands/bar/bindsym.c', @@ -51,6 +75,7 @@ sway_sources = files( 'commands/bar/tray_padding.c', 'commands/bar/workspace_buttons.c', 'commands/bar/wrap_scroll.c', + 'commands/input/accel_profile.c', 'commands/input/click_method.c', 'commands/input/drag_lock.c', @@ -67,24 +92,7 @@ sway_sources = files( 'commands/input/xkb_options.c', 'commands/input/xkb_rules.c', 'commands/input/xkb_variant.c', - 'commands/mouse_warping.c', - 'commands/output.c', - 'commands/reload.c', - 'commands/workspace.c', - 'config.c', - 'config/bar.c', - 'config/output.c', - 'config/seat.c', - 'config/input.c', - 'criteria.c', - 'ipc-json.c', - 'ipc-server.c', - 'desktop/output.c', - 'desktop/layer_shell.c', - 'desktop/wl_shell.c', - 'desktop/xdg_shell_v6.c', - 'desktop/xwayland.c', - 'security.c', + 'tree/container.c', 'tree/layout.c', 'tree/view.c', diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 5abdbc321..7e2c61ed3 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -729,3 +729,24 @@ struct sway_container *container_split(struct sway_container *child, return cont; } + +void container_recursive_resize(struct sway_container *container, + double amount, enum resize_edge edge) { + bool layout_match = true; + wlr_log(L_DEBUG, "Resizing %p with amount: %f", container, amount); + if (edge == RESIZE_EDGE_LEFT || edge == RESIZE_EDGE_RIGHT) { + container->width += amount; + layout_match = container->layout == L_HORIZ; + } else if (edge == RESIZE_EDGE_TOP || edge == RESIZE_EDGE_BOTTOM) { + container->height += amount; + layout_match = container->layout == L_VERT; + } + if (container->children) { + for (int i = 0; i < container->children->length; i++) { + struct sway_container *child = container->children->items[i]; + double amt = layout_match ? + amount / container->children->length : amount; + container_recursive_resize(child, amt, edge); + } + } +} From 9939d98454db32635dd9d0887ac930d7a24440bc Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 5 Apr 2018 09:21:39 -0400 Subject: [PATCH 443/522] Error handling in swaylock daemonize() Fixes #1741 --- swaylock/main.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/swaylock/main.c b/swaylock/main.c index 1d5221849..4c6b44c69 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -23,12 +23,34 @@ #include "wlr-layer-shell-unstable-v1-client-protocol.h" static void daemonize() { + int fds[2]; + if (pipe(fds) != 0) { + wlr_log(L_ERROR, "Failed to pipe"); + exit(1); + } if (fork() == 0) { + close(fds[0]); int devnull = open("/dev/null", O_RDWR); dup2(STDOUT_FILENO, devnull); dup2(STDERR_FILENO, devnull); - chdir("/"); + uint8_t success = 0; + if (chdir("/") != 0) { + write(fds[1], &success, 1); + exit(1); + } + success = 1; + if (write(fds[1], &success, 1) != 1) { + exit(1); + } + close(fds[1]); } else { + close(fds[1]); + uint8_t success; + if (read(fds[0], &success, 1) != 1 || !success) { + wlr_log(L_ERROR, "Failed to daemonize"); + exit(1); + } + close(fds[0]); exit(0); } } From dcd15a2d3dd93e057fe702238eb21dd70331b44f Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 11:38:14 -0400 Subject: [PATCH 444/522] Implement shell views --- include/sway/tree/view.h | 110 +++++++++++++++----------------- sway/desktop/wl_shell.c | 79 ++++++++++++----------- sway/desktop/xdg_shell_v6.c | 110 +++++++++++++++++--------------- sway/desktop/xwayland.c | 123 +++++++++++++++++++----------------- sway/tree/view.c | 13 ++-- 5 files changed, 228 insertions(+), 207 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index f32ccc5ae..d4dace4ab 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -8,55 +8,6 @@ #include "sway/input/seat.h" 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 map; - struct wl_listener unmap; - 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 map; - struct wl_listener unmap; - struct wl_listener destroy; - - int pending_width, pending_height; -}; - -struct sway_xwayland_unmanaged { - struct wlr_xwayland_surface *wlr_xwayland_surface; - struct wl_list link; - - struct wl_listener destroy; -}; - -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_VIEW_WL_SHELL, @@ -78,6 +29,7 @@ struct sway_view_impl { int height); void (*set_activated)(struct sway_view *view, bool activated); void (*close)(struct sway_view *view); + void (*destroy)(struct sway_view *view); }; struct sway_view { @@ -93,18 +45,55 @@ struct sway_view { 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 sway_view *view_create(enum sway_view_type type, - const struct sway_view_impl *impl); +struct sway_xdg_shell_v6_view { + struct sway_view view; -void view_destroy(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 map; + struct wl_listener unmap; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +struct sway_xwayland_view { + 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 map; + struct wl_listener unmap; + struct wl_listener destroy; + + int pending_width, pending_height; +}; + +struct sway_xwayland_unmanaged { + struct wlr_xwayland_surface *wlr_xwayland_surface; + struct wl_list link; + + struct wl_listener destroy; +}; + +struct sway_wl_shell_view { + 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; +}; const char *view_get_title(struct sway_view *view); @@ -127,6 +116,11 @@ void view_damage_from(struct sway_view *view); // view implementation +void view_init(struct sway_view *view, enum sway_view_type type, + const struct sway_view_impl *impl); + +void view_destroy(struct sway_view *view); + void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); void view_unmap(struct sway_view *view); diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index a470674da..5955fa9db 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -11,13 +11,17 @@ #include "sway/input/input-manager.h" #include "log.h" -static bool assert_wl_shell(struct sway_view *view) { - return sway_assert(view->type == SWAY_VIEW_WL_SHELL, - "Expecting wl_shell view!"); +static struct sway_wl_shell_view *wl_shell_view_from_view( + struct sway_view *view) { + if (!sway_assert(view->type == SWAY_VIEW_WL_SHELL, + "Expected wl_shell view")) { + return NULL; + } + return (struct sway_wl_shell_view *)view; } static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { - if (!assert_wl_shell(view)) { + if (wl_shell_view_from_view(view) == NULL) { return NULL; } switch (prop) { @@ -32,23 +36,34 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { static void configure(struct sway_view *view, double ox, double oy, int width, int height) { - if (!assert_wl_shell(view)) { + struct sway_wl_shell_view *wl_shell_view = wl_shell_view_from_view(view); + if (wl_shell_view == NULL) { return; } view_update_position(view, ox, oy); - view->sway_wl_shell_surface->pending_width = width; - view->sway_wl_shell_surface->pending_height = height; + wl_shell_view->pending_width = width; + wl_shell_view->pending_height = height; wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); } static void _close(struct sway_view *view) { - if (!assert_wl_shell(view)) { + if (wl_shell_view_from_view(view) == NULL) { return; } wl_client_destroy(view->wlr_wl_shell_surface->client); } +static void destroy(struct sway_view *view) { + struct sway_wl_shell_view *wl_shell_view = wl_shell_view_from_view(view); + if (wl_shell_view == NULL) { + return; + } + wl_list_remove(&wl_shell_view->commit.link); + wl_list_remove(&wl_shell_view->destroy.link); + free(wl_shell_view); +} + static const struct sway_view_impl view_impl = { .get_prop = get_prop, .configure = configure, @@ -56,23 +71,20 @@ static const struct sway_view_impl view_impl = { }; static void handle_commit(struct wl_listener *listener, void *data) { - struct sway_wl_shell_surface *sway_surface = - wl_container_of(listener, sway_surface, commit); - struct sway_view *view = sway_surface->view; + struct sway_wl_shell_view *wl_shell_view = + wl_container_of(listener, wl_shell_view, commit); + struct sway_view *view = &wl_shell_view->view; // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever - view_update_size(view, sway_surface->pending_width, - sway_surface->pending_height); + view_update_size(view, wl_shell_view->pending_width, + wl_shell_view->pending_height); view_damage_from(view); } static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_wl_shell_surface *sway_surface = - wl_container_of(listener, sway_surface, destroy); - wl_list_remove(&sway_surface->commit.link); - wl_list_remove(&sway_surface->destroy.link); - view_destroy(sway_surface->view); - free(sway_surface); + struct sway_wl_shell_view *wl_shell_view = + wl_container_of(listener, wl_shell_view, destroy); + view_destroy(&wl_shell_view->view); } void handle_wl_shell_surface(struct wl_listener *listener, void *data) { @@ -82,42 +94,37 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { // popups don't get views + wlr_log(L_DEBUG, "New wl_shell popup"); return; } - // TODO make transient windows floating + // TODO: make transient windows floating wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", shell_surface->title, shell_surface->class); wlr_wl_shell_surface_ping(shell_surface); - struct sway_wl_shell_surface *sway_surface = - calloc(1, sizeof(struct sway_wl_shell_surface)); - if (!sway_assert(sway_surface, "Failed to allocate surface!")) { + struct sway_wl_shell_view *wl_shell_view = + calloc(1, sizeof(struct sway_wl_shell_view)); + if (!sway_assert(wl_shell_view, "Failed to allocate view")) { return; } - struct sway_view *view = view_create(SWAY_VIEW_WL_SHELL, &view_impl); - if (!sway_assert(view, "Failed to allocate view")) { - return; - } - view->wlr_wl_shell_surface = shell_surface; - view->sway_wl_shell_surface = sway_surface; - sway_surface->view = view; + view_init(&wl_shell_view->view, SWAY_VIEW_WL_SHELL, &view_impl); + wl_shell_view->view.wlr_wl_shell_surface = shell_surface; // TODO: // - Wire up listeners - // - Handle popups // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria - sway_surface->commit.notify = handle_commit; + wl_shell_view->commit.notify = handle_commit; wl_signal_add(&shell_surface->surface->events.commit, - &sway_surface->commit); + &wl_shell_view->commit); - sway_surface->destroy.notify = handle_destroy; - wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); + wl_shell_view->destroy.notify = handle_destroy; + wl_signal_add(&shell_surface->events.destroy, &wl_shell_view->destroy); - view_map(view, shell_surface->surface); + view_map(&wl_shell_view->view, shell_surface->surface); } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 5cdb8f9f6..7b9d5fb70 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -11,13 +11,17 @@ #include "sway/input/input-manager.h" #include "log.h" -static bool assert_xdg(struct sway_view *view) { - return sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, - "Expected xdg shell v6 view!"); +static struct sway_xdg_shell_v6_view *xdg_shell_v6_view_from_view( + struct sway_view *view) { + if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, + "Expected xdg_shell_v6 view")) { + return NULL; + } + return (struct sway_xdg_shell_v6_view *)view; } static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { - if (!assert_xdg(view)) { + if (xdg_shell_v6_view_from_view(view) == NULL) { return NULL; } switch (prop) { @@ -32,18 +36,20 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { static void configure(struct sway_view *view, double ox, double oy, int width, int height) { - if (!assert_xdg(view)) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + xdg_shell_v6_view_from_view(view); + if (xdg_shell_v6_view == NULL) { return; } view_update_position(view, ox, oy); - view->sway_xdg_surface_v6->pending_width = width; - view->sway_xdg_surface_v6->pending_height = height; + xdg_shell_v6_view->pending_width = width; + xdg_shell_v6_view->pending_height = height; wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); } static void set_activated(struct sway_view *view, bool activated) { - if (!assert_xdg(view)) { + if (xdg_shell_v6_view_from_view(view) == NULL) { return; } struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; @@ -53,7 +59,7 @@ static void set_activated(struct sway_view *view, bool activated) { } static void _close(struct sway_view *view) { - if (!assert_xdg(view)) { + if (xdg_shell_v6_view_from_view(view) == NULL) { return; } struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; @@ -62,6 +68,19 @@ static void _close(struct sway_view *view) { } } +static void destroy(struct sway_view *view) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + xdg_shell_v6_view_from_view(view); + if (xdg_shell_v6_view == NULL) { + return; + } + wl_list_remove(&xdg_shell_v6_view->commit.link); + wl_list_remove(&xdg_shell_v6_view->destroy.link); + wl_list_remove(&xdg_shell_v6_view->map.link); + wl_list_remove(&xdg_shell_v6_view->unmap.link); + free(xdg_shell_v6_view); +} + static const struct sway_view_impl view_impl = { .get_prop = get_prop, .configure = configure, @@ -70,83 +89,74 @@ static const struct sway_view_impl view_impl = { }; static void handle_commit(struct wl_listener *listener, void *data) { - struct sway_xdg_surface_v6 *sway_surface = - wl_container_of(listener, sway_surface, commit); - struct sway_view *view = sway_surface->view; + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, commit); + struct sway_view *view = &xdg_shell_v6_view->view; // NOTE: We intentionally discard the view's desired width here // TODO: Store this for restoration when moving to floating plane // TODO: Let floating views do whatever - view_update_size(view, sway_surface->pending_width, - sway_surface->pending_height); + view_update_size(view, xdg_shell_v6_view->pending_width, + xdg_shell_v6_view->pending_height); view_damage_from(view); } static void handle_unmap(struct wl_listener *listener, void *data) { - struct sway_xdg_surface_v6 *sway_surface = - wl_container_of(listener, sway_surface, unmap); - view_unmap(sway_surface->view); + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, unmap); + view_unmap(&xdg_shell_v6_view->view); } static void handle_map(struct wl_listener *listener, void *data) { - struct sway_xdg_surface_v6 *sway_surface = - wl_container_of(listener, sway_surface, map); - struct sway_view *view = sway_surface->view; + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, map); + struct sway_view *view = &xdg_shell_v6_view->view; view_map(view, view->wlr_xdg_surface_v6->surface); } static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_xdg_surface_v6 *sway_xdg_surface = - wl_container_of(listener, sway_xdg_surface, destroy); - wl_list_remove(&sway_xdg_surface->commit.link); - wl_list_remove(&sway_xdg_surface->destroy.link); - wl_list_remove(&sway_xdg_surface->map.link); - wl_list_remove(&sway_xdg_surface->unmap.link); - view_destroy(sway_xdg_surface->view); - free(sway_xdg_surface); + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, destroy); + view_destroy(&xdg_shell_v6_view->view); } void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { - struct sway_server *server = wl_container_of( - listener, server, xdg_shell_v6_surface); + struct sway_server *server = wl_container_of(listener, server, + xdg_shell_v6_surface); struct wlr_xdg_surface_v6 *xdg_surface = data; if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { - // TODO: popups + wlr_log(L_DEBUG, "New xdg_shell_v6 popup"); return; } wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", - xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); + xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); wlr_xdg_surface_v6_ping(xdg_surface); wlr_xdg_toplevel_v6_set_maximized(xdg_surface, true); - struct sway_xdg_surface_v6 *sway_surface = - calloc(1, sizeof(struct sway_xdg_surface_v6)); - if (!sway_assert(sway_surface, "Failed to allocate surface!")) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + calloc(1, sizeof(struct sway_xdg_shell_v6_view)); + if (!sway_assert(xdg_shell_v6_view, "Failed to allocate view")) { return; } - struct sway_view *view = view_create(SWAY_VIEW_XDG_SHELL_V6, &view_impl); - if (!sway_assert(view, "Failed to allocate view")) { - return; - } - view->wlr_xdg_surface_v6 = xdg_surface; - view->sway_xdg_surface_v6 = sway_surface; - sway_surface->view = view; + view_init(&xdg_shell_v6_view->view, SWAY_VIEW_XDG_SHELL_V6, &view_impl); + xdg_shell_v6_view->view.wlr_xdg_surface_v6 = xdg_surface; // TODO: // - Look up pid and open on appropriate workspace // - Criteria - sway_surface->commit.notify = handle_commit; - wl_signal_add(&xdg_surface->surface->events.commit, &sway_surface->commit); + xdg_shell_v6_view->commit.notify = handle_commit; + wl_signal_add(&xdg_surface->surface->events.commit, + &xdg_shell_v6_view->commit); - sway_surface->map.notify = handle_map; - wl_signal_add(&xdg_surface->events.map, &sway_surface->map); + xdg_shell_v6_view->map.notify = handle_map; + wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map); - sway_surface->unmap.notify = handle_unmap; - wl_signal_add(&xdg_surface->events.unmap, &sway_surface->unmap); + xdg_shell_v6_view->unmap.notify = handle_unmap; + wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_v6_view->unmap); - sway_surface->destroy.notify = handle_destroy; - wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); + xdg_shell_v6_view->destroy.notify = handle_destroy; + wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_v6_view->destroy); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index a793928cf..384f42364 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -41,13 +41,17 @@ static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { } -static bool assert_xwayland(struct sway_view *view) { - return sway_assert(view->type == SWAY_VIEW_XWAYLAND, - "Expected xwayland view!"); +static struct sway_xwayland_view *xwayland_view_from_view( + struct sway_view *view) { + if (!sway_assert(view->type == SWAY_VIEW_XWAYLAND, + "Expected xwayland view")) { + return NULL; + } + return (struct sway_xwayland_view *)view; } static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { - if (!assert_xwayland(view)) { + if (xwayland_view_from_view(view) == NULL) { return NULL; } switch (prop) { @@ -62,7 +66,8 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { static void configure(struct sway_view *view, double ox, double oy, int width, int height) { - if (!assert_xwayland(view)) { + struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view); + if (xwayland_view == NULL) { return; } struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; @@ -84,14 +89,14 @@ static void configure(struct sway_view *view, double ox, double oy, int width, view_update_position(view, ox, oy); - view->sway_xwayland_surface->pending_width = width; - view->sway_xwayland_surface->pending_height = height; + xwayland_view->pending_width = width; + xwayland_view->pending_height = height; wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, width, height); } static void set_activated(struct sway_view *view, bool activated) { - if (!assert_xwayland(view)) { + if (xwayland_view_from_view(view) == NULL) { return; } struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; @@ -99,12 +104,24 @@ static void set_activated(struct sway_view *view, bool activated) { } static void _close(struct sway_view *view) { - if (!assert_xwayland(view)) { + if (xwayland_view_from_view(view) == NULL) { return; } wlr_xwayland_surface_close(view->wlr_xwayland_surface); } +static void destroy(struct sway_view *view) { + struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view); + if (xwayland_view == NULL) { + return; + } + wl_list_remove(&xwayland_view->destroy.link); + wl_list_remove(&xwayland_view->request_configure.link); + wl_list_remove(&xwayland_view->map.link); + wl_list_remove(&xwayland_view->unmap.link); + free(xwayland_view); +} + static const struct sway_view_impl view_impl = { .get_prop = get_prop, .configure = configure, @@ -113,50 +130,50 @@ static const struct sway_view_impl view_impl = { }; static void handle_commit(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, commit); - struct sway_view *view = sway_surface->view; + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, commit); + struct sway_view *view = &xwayland_view->view; // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever - view_update_size(view, sway_surface->pending_width, - sway_surface->pending_height); + view_update_size(view, xwayland_view->pending_width, + xwayland_view->pending_height); view_damage_from(view); } static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, destroy); - wl_list_remove(&sway_surface->commit.link); - wl_list_remove(&sway_surface->destroy.link); - wl_list_remove(&sway_surface->request_configure.link); - wl_list_remove(&sway_surface->map.link); - wl_list_remove(&sway_surface->unmap.link); - view_destroy(sway_surface->view); - free(sway_surface); + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, destroy); + view_destroy(&xwayland_view->view); } static void handle_unmap(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, unmap); - view_unmap(sway_surface->view); + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, unmap); + wl_list_remove(&xwayland_view->commit.link); + view_unmap(&xwayland_view->view); } static void handle_map(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, map); + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, map); struct wlr_xwayland_surface *xsurface = data; - struct sway_view *view = sway_surface->view; + struct sway_view *view = &xwayland_view->view; - // put it back into the tree + // Wire up the commit listener here, because xwayland map/unmap can change + // the underlying wlr_surface + wl_signal_add(&xsurface->surface->events.commit, &xwayland_view->commit); + xwayland_view->commit.notify = handle_commit; + + // Put it back into the tree wlr_xwayland_surface_set_maximized(xsurface, true); view_map(view, xsurface->surface); } static void handle_request_configure(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, request_configure); + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, request_configure); struct wlr_xwayland_surface_configure_event *ev = data; - struct sway_view *view = sway_surface->view; + struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; // TODO: floating windows are allowed to move around like this, but make // sure tiling windows always stay in place. @@ -165,8 +182,8 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { } void handle_xwayland_surface(struct wl_listener *listener, void *data) { - struct sway_server *server = wl_container_of( - listener, server, xwayland_surface); + struct sway_server *server = wl_container_of(listener, server, + xwayland_surface); struct wlr_xwayland_surface *xsurface = data; if (wlr_xwayland_surface_is_unmanaged(xsurface) || @@ -179,39 +196,31 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", xsurface->title, xsurface->class); - struct sway_xwayland_surface *sway_surface = - calloc(1, sizeof(struct sway_xwayland_surface)); - if (!sway_assert(sway_surface, "Failed to allocate surface")) { + struct sway_xwayland_view *xwayland_view = + calloc(1, sizeof(struct sway_xwayland_view)); + if (!sway_assert(xwayland_view, "Failed to allocate view")) { return; } - struct sway_view *view = view_create(SWAY_VIEW_XWAYLAND, &view_impl); - if (!sway_assert(view, "Failed to allocate view")) { - return; - } - view->wlr_xwayland_surface = xsurface; - view->sway_xwayland_surface = sway_surface; - sway_surface->view = view; + view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl); + xwayland_view->view.wlr_xwayland_surface = xsurface; // TODO: // - Look up pid and open on appropriate workspace // - Criteria - wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); - sway_surface->commit.notify = handle_commit; - - wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); - sway_surface->destroy.notify = handle_destroy; + wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy); + xwayland_view->destroy.notify = handle_destroy; wl_signal_add(&xsurface->events.request_configure, - &sway_surface->request_configure); - sway_surface->request_configure.notify = handle_request_configure; + &xwayland_view->request_configure); + xwayland_view->request_configure.notify = handle_request_configure; - wl_signal_add(&xsurface->events.unmap, &sway_surface->unmap); - sway_surface->unmap.notify = handle_unmap; + wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap); + xwayland_view->unmap.notify = handle_unmap; - wl_signal_add(&xsurface->events.map, &sway_surface->map); - sway_surface->map.notify = handle_map; + wl_signal_add(&xsurface->events.map, &xwayland_view->map); + xwayland_view->map.notify = handle_map; - handle_map(&sway_surface->map, xsurface); + handle_map(&xwayland_view->map, xsurface); } diff --git a/sway/tree/view.c b/sway/tree/view.c index aa010a403..3927c1951 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -7,15 +7,10 @@ #include "sway/tree/layout.h" #include "sway/tree/view.h" -struct sway_view *view_create(enum sway_view_type type, +void view_init(struct sway_view *view, enum sway_view_type type, const struct sway_view_impl *impl) { - struct sway_view *view = calloc(1, sizeof(struct sway_view)); - if (view == NULL) { - return NULL; - } view->type = type; view->impl = impl; - return view; } void view_destroy(struct sway_view *view) { @@ -28,6 +23,12 @@ void view_destroy(struct sway_view *view) { } container_destroy(view->swayc); + + if (view->impl->destroy) { + view->impl->destroy(view); + } else { + free(view); + } } const char *view_get_title(struct sway_view *view) { From 94ecd0f0aa16a3eee037b62097c4d939576b4934 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 5 Apr 2018 14:01:14 -0400 Subject: [PATCH 445/522] Configure wlr_xdg_output_manager during init --- sway/server.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sway/server.c b/sway/server.c index 549453121..dfd017985 100644 --- a/sway/server.c +++ b/sway/server.c @@ -12,15 +12,17 @@ #include #include #include -#include #include +#include +#include #include // TODO WLR: make Xwayland optional #include #include "sway/commands.h" #include "sway/config.h" -#include "sway/server.h" #include "sway/input/input-manager.h" +#include "sway/server.h" +#include "sway/tree/layout.h" static void server_ready(struct wl_listener *listener, void *data) { wlr_log(L_DEBUG, "Compositor is ready, executing cmds in queue"); @@ -61,6 +63,9 @@ bool server_init(struct sway_server *server) { server->new_output.notify = handle_new_output; wl_signal_add(&server->backend->events.new_output, &server->new_output); + wlr_xdg_output_manager_create(server->wl_display, + root_container.sway_root->output_layout); + server->layer_shell = wlr_layer_shell_create(server->wl_display); wl_signal_add(&server->layer_shell->events.new_surface, &server->layer_shell_surface); From 45f93e165096ed04c4d1152523502ae5fc760632 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 14:46:02 -0400 Subject: [PATCH 446/522] Accumulate damage from subsurfaces --- include/sway/tree/view.h | 33 ++++++++++++ sway/tree/view.c | 112 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index d4dace4ab..f8e416523 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -45,6 +45,12 @@ struct sway_view { struct wlr_xwayland_surface *wlr_xwayland_surface; struct wlr_wl_shell_surface *wlr_wl_shell_surface; }; + + struct { + struct wl_signal unmap; + } events; + + struct wl_listener surface_new_subsurface; }; struct sway_xdg_shell_v6_view { @@ -95,6 +101,27 @@ struct sway_wl_shell_view { int pending_width, pending_height; }; +struct sway_view_child; + +struct sway_view_child_impl { + void (*destroy)(struct sway_view_child *child); +}; + +/** + * A view child is a surface in the view tree, such as a subsurface or a popup. + */ +struct sway_view_child { + const struct sway_view_child_impl *impl; + + struct sway_view *view; + struct wlr_surface *surface; + + struct wl_listener surface_commit; + struct wl_listener surface_new_subsurface; + struct wl_listener surface_destroy; + struct wl_listener view_unmap; +}; + const char *view_get_title(struct sway_view *view); const char *view_get_app_id(struct sway_view *view); @@ -129,4 +156,10 @@ void view_update_position(struct sway_view *view, double ox, double oy); void view_update_size(struct sway_view *view, int width, int height); +void view_child_init(struct sway_view_child *child, + const struct sway_view_child_impl *impl, struct sway_view *view, + struct wlr_surface *surface); + +void view_child_destroy(struct sway_view_child *child); + #endif diff --git a/sway/tree/view.c b/sway/tree/view.c index 3927c1951..85fd30939 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -11,6 +11,7 @@ void view_init(struct sway_view *view, enum sway_view_type type, const struct sway_view_impl *impl) { view->type = type; view->impl = impl; + wl_signal_init(&view->events.unmap); } void view_destroy(struct sway_view *view) { @@ -123,6 +124,20 @@ static void view_update_outputs(struct sway_view *view, } } +static void view_subsurface_create(struct sway_view *view, + struct wlr_subsurface *subsurface); + +static void view_init_subsurfaces(struct sway_view *view, + struct wlr_surface *surface); + +static void view_handle_surface_new_subsurface(struct wl_listener *listener, + void *data) { + struct sway_view *view = + wl_container_of(listener, view, surface_new_subsurface); + struct wlr_subsurface *subsurface = data; + view_subsurface_create(view, subsurface); +} + void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { return; @@ -136,11 +151,18 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { view->surface = wlr_surface; view->swayc = cont; + view_init_subsurfaces(view, wlr_surface); + wl_signal_add(&wlr_surface->events.new_subsurface, + &view->surface_new_subsurface); + view->surface_new_subsurface.notify = view_handle_surface_new_subsurface; + arrange_windows(cont->parent, -1, -1); input_manager_set_focus(input_manager, cont); view_damage_whole(view); view_update_outputs(view, NULL); + + // TODO: create view children for subsurfaces } void view_unmap(struct sway_view *view) { @@ -148,6 +170,8 @@ void view_unmap(struct sway_view *view) { return; } + wl_signal_emit(&view->events.unmap, view); + view_damage_whole(view); struct sway_container *parent = container_destroy(view->swayc); @@ -185,3 +209,91 @@ void view_update_size(struct sway_view *view, int width, int height) { view_update_outputs(view, &box); view_damage_whole(view); } + + +static void view_subsurface_create(struct sway_view *view, + struct wlr_subsurface *subsurface) { + struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); + if (child == NULL) { + wlr_log(L_ERROR, "Allocation failed"); + return; + } + view_child_init(child, NULL, view, subsurface->surface); +} + +static void view_child_handle_surface_commit(struct wl_listener *listener, + void *data) { + struct sway_view_child *child = + wl_container_of(listener, child, surface_commit); + // TODO: only accumulate damage from the child + view_damage_from(child->view); +} + +static void view_child_handle_surface_new_subsurface( + struct wl_listener *listener, void *data) { + struct sway_view_child *child = + wl_container_of(listener, child, surface_new_subsurface); + struct wlr_subsurface *subsurface = data; + view_subsurface_create(child->view, subsurface); +} + +static void view_child_handle_surface_destroy(struct wl_listener *listener, + void *data) { + struct sway_view_child *child = + wl_container_of(listener, child, surface_destroy); + view_child_destroy(child); +} + +static void view_child_handle_view_unmap(struct wl_listener *listener, + void *data) { + struct sway_view_child *child = + wl_container_of(listener, child, view_unmap); + view_child_destroy(child); +} + +static void view_init_subsurfaces(struct sway_view *view, + struct wlr_surface *surface) { + struct wlr_subsurface *subsurface; + wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { + view_subsurface_create(view, subsurface); + } +} + +void view_child_init(struct sway_view_child *child, + const struct sway_view_child_impl *impl, struct sway_view *view, + struct wlr_surface *surface) { + child->impl = impl; + child->view = view; + child->surface = surface; + + wl_signal_add(&surface->events.commit, &child->surface_commit); + child->surface_commit.notify = view_child_handle_surface_commit; + wl_signal_add(&surface->events.new_subsurface, + &child->surface_new_subsurface); + child->surface_new_subsurface.notify = + view_child_handle_surface_new_subsurface; + wl_signal_add(&surface->events.destroy, &child->surface_destroy); + child->surface_destroy.notify = view_child_handle_surface_destroy; + wl_signal_add(&view->events.unmap, &child->view_unmap); + child->view_unmap.notify = view_child_handle_view_unmap; + + view_init_subsurfaces(child->view, surface); + + // TODO: only damage the whole child + view_damage_whole(child->view); +} + +void view_child_destroy(struct sway_view_child *child) { + // TODO: only damage the whole child + view_damage_whole(child->view); + + wl_list_remove(&child->surface_commit.link); + wl_list_remove(&child->surface_destroy.link); + wl_list_remove(&child->view_unmap.link); + + if (child->impl && child->impl->destroy) { + child->impl->destroy(child); + } else { + free(child); + } +} From 842a3ea45c07ab5ed8e3c20af5ef0dc92fff22de Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 5 Apr 2018 15:23:59 -0400 Subject: [PATCH 447/522] Add -Wno-unused-result Fixes #1744 --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index d02a446b5..5a37b0e22 100644 --- a/meson.build +++ b/meson.build @@ -11,6 +11,7 @@ project( add_project_arguments('-Wno-unused-parameter', language: 'c') add_project_arguments('-Wno-unused-function', language: 'c') +add_project_arguments('-Wno-unused-result', language: 'c') cc = meson.get_compiler('c') From f242362e7e521a8f35f47572038a20d404d25327 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 5 Apr 2018 15:39:57 -0400 Subject: [PATCH 448/522] Handle output removal on swaybar --- client/pool-buffer.c | 2 +- include/pool-buffer.h | 1 + include/swaybar/bar.h | 1 + sway/tree/container.c | 4 +++- swaybar/bar.c | 42 ++++++++++++++++++++++++++++++++++++++---- swaybar/ipc.c | 2 +- swaybar/render.c | 2 -- 7 files changed, 45 insertions(+), 9 deletions(-) diff --git a/client/pool-buffer.c b/client/pool-buffer.c index b5ed9c988..1f54a77cd 100644 --- a/client/pool-buffer.c +++ b/client/pool-buffer.c @@ -79,7 +79,7 @@ static struct pool_buffer *create_buffer(struct wl_shm *shm, return buf; } -static void destroy_buffer(struct pool_buffer *buffer) { +void destroy_buffer(struct pool_buffer *buffer) { if (buffer->buffer) { wl_buffer_destroy(buffer->buffer); } diff --git a/include/pool-buffer.h b/include/pool-buffer.h index cdebd64dc..856f7c8c0 100644 --- a/include/pool-buffer.h +++ b/include/pool-buffer.h @@ -17,5 +17,6 @@ struct pool_buffer { struct pool_buffer *get_next_buffer(struct wl_shm *shm, struct pool_buffer pool[static 2], uint32_t width, uint32_t height); +void destroy_buffer(struct pool_buffer *buffer); #endif diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 503b961c1..0037190b3 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -49,6 +49,7 @@ struct swaybar_output { struct wl_output *output; struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; + uint32_t wl_name; struct wl_list workspaces; struct wl_list hotspots; diff --git a/sway/tree/container.c b/sway/tree/container.c index 8fc9e3e87..3e8c1c759 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -64,7 +64,9 @@ static void container_close_notify(struct sway_container *container) { return; } // TODO send ipc event type based on the container type - ipc_event_window(container, "close"); + if (container->type == C_VIEW || container->type == C_WORKSPACE) { + ipc_event_window(container, "close"); + } } struct sway_container *container_create(enum sway_container_type type) { diff --git a/swaybar/bar.c b/swaybar/bar.c index ea0141ccd..f1a701b91 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -34,6 +34,34 @@ static void bar_init(struct swaybar *bar) { wl_list_init(&bar->outputs); } +static void swaybar_output_free(struct swaybar_output *output) { + if (!output) { + return; + } + wlr_log(L_DEBUG, "Removing output %s", output->name); + zwlr_layer_surface_v1_destroy(output->layer_surface); + wl_surface_destroy(output->surface); + wl_output_destroy(output->output); + destroy_buffer(&output->buffers[0]); + destroy_buffer(&output->buffers[1]); + struct swaybar_workspace *ws, *ws_tmp; + wl_list_for_each_safe(ws, ws_tmp, &output->workspaces, link) { + wl_list_remove(&ws->link); + free(ws->name); + free(ws); + } + struct swaybar_hotspot *hotspot, *hotspot_tmp; + wl_list_for_each_safe(hotspot, hotspot_tmp, &output->hotspots, link) { + if (hotspot->destroy) { + hotspot->destroy(hotspot->data); + } + free(hotspot); + } + wl_list_remove(&output->link); + free(output->name); + free(output); +} + static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height) { @@ -46,10 +74,8 @@ static void layer_surface_configure(void *data, 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); + swaybar_output_free(output); } struct zwlr_layer_surface_v1_listener layer_surface_listener = { @@ -261,6 +287,7 @@ static void handle_global(void *data, struct wl_registry *registry, wl_output_add_listener(output->output, &output_listener, output); output->scale = 1; output->index = index++; + output->wl_name = name; wl_list_init(&output->workspaces); wl_list_init(&output->hotspots); wl_list_insert(&bar->outputs, &output->link); @@ -272,7 +299,14 @@ static void handle_global(void *data, struct wl_registry *registry, static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { - // who cares + struct swaybar *bar = data; + struct swaybar_output *output, *tmp; + wl_list_for_each_safe(output, tmp, &bar->outputs, link) { + if (output->wl_name == name) { + swaybar_output_free(output); + break; + } + } } static const struct wl_registry_listener registry_listener = { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index ed5d9a315..92dbb8ead 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -367,5 +367,5 @@ bool handle_ipc_readable(struct swaybar *bar) { return false; } free_ipc_response(resp); - return true; + return false; } diff --git a/swaybar/render.c b/swaybar/render.c index be58301d0..53e578f0f 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -421,8 +421,6 @@ static uint32_t render_workspace_button(cairo_t *cairo, static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, struct swaybar_output *output) { struct swaybar_config *config = bar->config; - wlr_log(L_DEBUG, "output %p", output); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); if (output->focused) { cairo_set_source_u32(cairo, config->colors.focused_background); From f5e5b1819bf88841f6f42fdfe416fa588abbeeb5 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 16:48:11 -0400 Subject: [PATCH 449/522] Track damage of xdg-shell-v6 popups --- include/sway/tree/view.h | 11 ++++++ sway/desktop/xdg_shell_v6.c | 72 +++++++++++++++++++++++++++++++++++++ sway/tree/view.c | 2 ++ 3 files changed, 85 insertions(+) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index f8e416523..2eca7a3e1 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -60,6 +60,7 @@ struct sway_xdg_shell_v6_view { struct wl_listener request_move; struct wl_listener request_resize; struct wl_listener request_maximize; + struct wl_listener new_popup; struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; @@ -122,6 +123,16 @@ struct sway_view_child { struct wl_listener view_unmap; }; +struct sway_xdg_popup_v6 { + struct sway_view_child child; + + struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; + + struct wl_listener new_popup; + struct wl_listener unmap; + struct wl_listener destroy; +}; + const char *view_get_title(struct sway_view *view); const char *view_get_app_id(struct sway_view *view); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 7b9d5fb70..baf07a1e4 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -11,6 +11,66 @@ #include "sway/input/input-manager.h" #include "log.h" +static const struct sway_view_child_impl popup_impl; + +static void popup_destroy(struct sway_view_child *child) { + if (!sway_assert(child->impl == &popup_impl, + "Expected an xdg_shell_v6 popup")) { + return; + } + struct sway_xdg_popup_v6 *popup = (struct sway_xdg_popup_v6 *)child; + wl_list_remove(&popup->new_popup.link); + wl_list_remove(&popup->unmap.link); + wl_list_remove(&popup->destroy.link); + free(popup); +} + +static const struct sway_view_child_impl popup_impl = { + .destroy = popup_destroy, +}; + +static struct sway_xdg_popup_v6 *popup_create( + struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view); + +static void popup_handle_new_popup(struct wl_listener *listener, void *data) { + struct sway_xdg_popup_v6 *popup = + wl_container_of(listener, popup, new_popup); + struct wlr_xdg_popup_v6 *wlr_popup = data; + popup_create(wlr_popup, popup->child.view); +} + +static void popup_handle_unmap(struct wl_listener *listener, void *data) { + struct sway_xdg_popup_v6 *popup = wl_container_of(listener, popup, unmap); + view_child_destroy(&popup->child); +} + +static void popup_handle_destroy(struct wl_listener *listener, void *data) { + struct sway_xdg_popup_v6 *popup = wl_container_of(listener, popup, destroy); + view_child_destroy(&popup->child); +} + +static struct sway_xdg_popup_v6 *popup_create( + struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) { + struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base; + + struct sway_xdg_popup_v6 *popup = + calloc(1, sizeof(struct sway_xdg_popup_v6)); + if (popup == NULL) { + return NULL; + } + view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); + + wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); + popup->new_popup.notify = popup_handle_new_popup; + wl_signal_add(&xdg_surface->events.unmap, &popup->unmap); + popup->unmap.notify = popup_handle_unmap; + wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); + popup->destroy.notify = popup_handle_destroy; + + return popup; +} + + static struct sway_xdg_shell_v6_view *xdg_shell_v6_view_from_view( struct sway_view *view) { if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, @@ -76,6 +136,7 @@ static void destroy(struct sway_view *view) { } wl_list_remove(&xdg_shell_v6_view->commit.link); wl_list_remove(&xdg_shell_v6_view->destroy.link); + wl_list_remove(&xdg_shell_v6_view->new_popup.link); wl_list_remove(&xdg_shell_v6_view->map.link); wl_list_remove(&xdg_shell_v6_view->unmap.link); free(xdg_shell_v6_view); @@ -100,6 +161,13 @@ static void handle_commit(struct wl_listener *listener, void *data) { view_damage_from(view); } +static void handle_new_popup(struct wl_listener *listener, void *data) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, new_popup); + struct wlr_xdg_popup_v6 *wlr_popup = data; + popup_create(wlr_popup, &xdg_shell_v6_view->view); +} + static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, unmap); @@ -151,6 +219,10 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xdg_surface->surface->events.commit, &xdg_shell_v6_view->commit); + xdg_shell_v6_view->new_popup.notify = handle_new_popup; + wl_signal_add(&xdg_surface->events.new_popup, + &xdg_shell_v6_view->new_popup); + xdg_shell_v6_view->map.notify = handle_map; wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map); diff --git a/sway/tree/view.c b/sway/tree/view.c index 85fd30939..293edc959 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -176,6 +176,8 @@ void view_unmap(struct sway_view *view) { struct sway_container *parent = container_destroy(view->swayc); + wl_list_remove(&view->surface_new_subsurface.link); + view->swayc = NULL; view->surface = NULL; From 7ce1038478de99f9328beaa289503826f107ac83 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 17:08:30 -0400 Subject: [PATCH 450/522] Fix xwayland unmanaged surfaces --- include/sway/tree/view.h | 3 ++ sway/desktop/wl_shell.c | 1 + sway/desktop/xdg_shell_v6.c | 1 + sway/desktop/xwayland.c | 68 ++++++++++++++++++++++++++++--------- 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 2eca7a3e1..e52bee669 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -87,6 +87,9 @@ struct sway_xwayland_unmanaged { struct wlr_xwayland_surface *wlr_xwayland_surface; struct wl_list link; + struct wl_listener commit; + struct wl_listener map; + struct wl_listener unmap; struct wl_listener destroy; }; diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 5955fa9db..fff31da81 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -68,6 +68,7 @@ static const struct sway_view_impl view_impl = { .get_prop = get_prop, .configure = configure, .close = _close, + .destroy = destroy, }; static void handle_commit(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index baf07a1e4..c66cc39a4 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -147,6 +147,7 @@ static const struct sway_view_impl view_impl = { .configure = configure, .set_activated = set_activated, .close = _close, + .destroy = destroy, }; static void handle_commit(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 384f42364..543c914e6 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -14,30 +14,65 @@ #include "sway/input/input-manager.h" #include "log.h" -static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { - struct sway_xwayland_unmanaged *sway_surface = - wl_container_of(listener, sway_surface, destroy); - wl_list_remove(&sway_surface->destroy.link); - wl_list_remove(&sway_surface->link); - free(sway_surface); +static void unmanaged_handle_commit(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, commit); + // TODO: damage tracking } -static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { - struct sway_xwayland_unmanaged *sway_surface = +static void unmanaged_handle_map(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, map); + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + wl_list_insert(&root_container.sway_root->xwayland_unmanaged, + &surface->link); + wl_signal_add(&xsurface->surface->events.commit, &surface->commit); + surface->commit.notify = unmanaged_handle_commit; + // TODO: damage tracking +} + +static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, unmap); + wl_list_remove(&surface->link); + wl_list_remove(&surface->commit.link); + // TODO: damage tracking +} + +static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, destroy); + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + if (xsurface->mapped) { + unmanaged_handle_unmap(&surface->unmap, xsurface); + } + wl_list_remove(&surface->map.link); + wl_list_remove(&surface->unmap.link); + wl_list_remove(&surface->destroy.link); + free(surface); +} + +static struct sway_xwayland_unmanaged *create_unmanaged( + struct wlr_xwayland_surface *xsurface) { + struct sway_xwayland_unmanaged *surface = calloc(1, sizeof(struct sway_xwayland_unmanaged)); - if (!sway_assert(sway_surface, "Failed to allocate surface")) { - return; + if (surface == NULL) { + wlr_log(L_ERROR, "Allocation failed"); + return NULL; } - sway_surface->wlr_xwayland_surface = xsurface; + surface->wlr_xwayland_surface = xsurface; - wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); - sway_surface->destroy.notify = unmanaged_handle_destroy; + wl_signal_add(&xsurface->events.map, &surface->map); + surface->map.notify = unmanaged_handle_map; + wl_signal_add(&xsurface->events.unmap, &surface->unmap); + surface->unmap.notify = unmanaged_handle_unmap; + wl_signal_add(&xsurface->events.destroy, &surface->destroy); + surface->destroy.notify = unmanaged_handle_destroy; - wl_list_insert(&root_container.sway_root->xwayland_unmanaged, - &sway_surface->link); + unmanaged_handle_map(&surface->map, xsurface); - // TODO: damage tracking + return surface; } @@ -127,6 +162,7 @@ static const struct sway_view_impl view_impl = { .configure = configure, .set_activated = set_activated, .close = _close, + .destroy = destroy, }; static void handle_commit(struct wl_listener *listener, void *data) { From a528aea2ee87a211edd3e6df83f2d408656430ab Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 17:11:46 -0400 Subject: [PATCH 451/522] Make xwayland surface destroy more foolproof --- sway/desktop/xwayland.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 543c914e6..0a70b6808 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -176,12 +176,6 @@ static void handle_commit(struct wl_listener *listener, void *data) { view_damage_from(view); } -static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_xwayland_view *xwayland_view = - wl_container_of(listener, xwayland_view, destroy); - view_destroy(&xwayland_view->view); -} - static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, unmap); @@ -205,6 +199,17 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, xsurface->surface); } +static void handle_destroy(struct wl_listener *listener, void *data) { + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, destroy); + struct sway_view *view = &xwayland_view->view; + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; + if (xsurface->mapped) { + handle_unmap(&xwayland_view->unmap, xsurface); + } + view_destroy(&xwayland_view->view); +} + static void handle_request_configure(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, request_configure); From 07f3bb3ad126e48247207126b977688a77e03928 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 17:22:39 -0400 Subject: [PATCH 452/522] Handle xwayland configure requests for unmanaged surfaces --- include/sway/tree/view.h | 1 + sway/desktop/xwayland.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index e52bee669..faf38bdf2 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -87,6 +87,7 @@ struct sway_xwayland_unmanaged { struct wlr_xwayland_surface *wlr_xwayland_surface; struct wl_list link; + struct wl_listener request_configure; struct wl_listener commit; struct wl_listener map; struct wl_listener unmap; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 0a70b6808..3842c2c85 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -14,6 +14,16 @@ #include "sway/input/input-manager.h" #include "log.h" +static void unmanaged_handle_request_configure(struct wl_listener *listener, + void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, request_configure); + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + struct wlr_xwayland_surface_configure_event *ev = data; + wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, + ev->width, ev->height); +} + static void unmanaged_handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, commit); @@ -63,6 +73,9 @@ static struct sway_xwayland_unmanaged *create_unmanaged( surface->wlr_xwayland_surface = xsurface; + wl_signal_add(&xsurface->events.request_configure, + &surface->request_configure); + surface->request_configure.notify = unmanaged_handle_request_configure; wl_signal_add(&xsurface->events.map, &surface->map); surface->map.notify = unmanaged_handle_map; wl_signal_add(&xsurface->events.unmap, &surface->unmap); From bbfc5487bce982ad7ad782fe00e7ac7c8de4c9d2 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 5 Apr 2018 17:33:35 -0400 Subject: [PATCH 453/522] add layout to ipc containers --- sway/ipc-json.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 54824a361..44828a0df 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -11,6 +11,40 @@ #include #include "wlr-layer-shell-unstable-v1-protocol.h" +static const char *ipc_json_layout_description(enum sway_container_layout l) { + const char *layout; + + switch (l) { + case L_VERT: + layout = "splitv"; + break; + + case L_HORIZ: + layout = "splith"; + break; + + case L_TABBED: + layout = "tabbed"; + break; + + case L_STACKED: + layout = "stacked"; + break; + + case L_FLOATING: + layout = "floating"; + break; + + case L_NONE: // fallthrough + case L_LAYOUTS: // fallthrough; this should never happen, I'm just trying to silence compiler warnings + default: + layout = "null"; + break; + } + + return layout; +} + json_object *ipc_json_get_version() { int major = 0, minor = 0, patch = 0; json_object *version = json_object_new_object(); @@ -116,6 +150,9 @@ static void ipc_json_describe_output(struct sway_container *container, json_obje json_object_array_add(modes_array, mode_object); } json_object_object_add(object, "modes", modes_array); + + + json_object_object_add(object, "layout", json_object_new_string("output")); } static void ipc_json_describe_workspace(struct sway_container *workspace, @@ -127,12 +164,23 @@ static void ipc_json_describe_workspace(struct sway_container *workspace, json_object_new_string(workspace->parent->name) : NULL); json_object_object_add(object, "type", json_object_new_string("workspace")); json_object_object_add(object, "urgent", json_object_new_boolean(false)); + + const char *layout = ipc_json_layout_description(workspace->workspace_layout); + json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? + NULL : json_object_new_string(layout)); } 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_object_add(object, "type", json_object_new_string("con")); + + if (c->parent) { + const char *layout = (c->parent->type == C_CONTAINER) ? + ipc_json_layout_description(c->parent->layout) : "none"; + json_object_object_add(object, "layout", + (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); + } } json_object *ipc_json_describe_container(struct sway_container *c) { From 1c91d0c10ffbed14cafaba79276a14f55172b7eb Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 17:37:24 -0400 Subject: [PATCH 454/522] Add damage tracking for xwayland unmanaged surfaces --- include/sway/desktop.h | 7 +++++++ include/sway/output.h | 3 +++ sway/desktop/desktop.c | 20 ++++++++++++++++++++ sway/desktop/output.c | 6 ++++++ sway/desktop/xwayland.c | 22 +++++++++++++--------- sway/meson.build | 1 + 6 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 include/sway/desktop.h create mode 100644 sway/desktop/desktop.c diff --git a/include/sway/desktop.h b/include/sway/desktop.h new file mode 100644 index 000000000..96bdc94cc --- /dev/null +++ b/include/sway/desktop.h @@ -0,0 +1,7 @@ +#include + +void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, + double ly); + +void desktop_damage_from_surface(struct wlr_surface *surface, double lx, + double ly); diff --git a/include/sway/output.h b/include/sway/output.h index 98d0f83f2..9964a484c 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -37,6 +37,9 @@ void output_damage_whole(struct sway_output *output); void output_damage_whole_view(struct sway_output *output, struct sway_view *view); +void output_damage_whole_surface(struct sway_output *output, + struct wlr_surface *surface, double ox, double oy); + struct sway_container *output_by_name(const char *name); #endif diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c new file mode 100644 index 000000000..78a2d49fd --- /dev/null +++ b/sway/desktop/desktop.c @@ -0,0 +1,20 @@ +#include "sway/tree/container.h" +#include "sway/desktop.h" +#include "sway/output.h" + +void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, + double ly) { + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *cont = root_container.children->items[i]; + if (cont->type == C_OUTPUT) { + output_damage_whole_surface(cont->sway_output, surface, + lx - cont->x, ly - cont->y); + } + } +} + +void desktop_damage_from_surface(struct wlr_surface *surface, double lx, + double ly) { + // TODO + desktop_damage_whole_surface(surface, lx, ly); +} diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0e8a94858..0ae5e7822 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -341,6 +341,12 @@ void output_damage_whole_view(struct sway_output *output, output_damage_whole(output); } +void output_damage_whole_surface(struct sway_output *output, + struct wlr_surface *surface, double ox, double oy) { + // TODO + output_damage_whole(output); +} + static void damage_handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, damage_destroy); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 3842c2c85..4797b8011 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -2,17 +2,18 @@ #include #include #include -#include #include #include +#include +#include "log.h" +#include "sway/desktop.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" +#include "sway/output.h" +#include "sway/server.h" #include "sway/tree/container.h" #include "sway/tree/layout.h" -#include "sway/server.h" #include "sway/tree/view.h" -#include "sway/output.h" -#include "sway/input/seat.h" -#include "sway/input/input-manager.h" -#include "log.h" static void unmanaged_handle_request_configure(struct wl_listener *listener, void *data) { @@ -27,7 +28,9 @@ static void unmanaged_handle_request_configure(struct wl_listener *listener, static void unmanaged_handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, commit); - // TODO: damage tracking + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + desktop_damage_from_surface(xsurface->surface, xsurface->x, xsurface->y); + // TODO: handle window motion } static void unmanaged_handle_map(struct wl_listener *listener, void *data) { @@ -38,15 +41,16 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) { &surface->link); wl_signal_add(&xsurface->surface->events.commit, &surface->commit); surface->commit.notify = unmanaged_handle_commit; - // TODO: damage tracking + desktop_damage_whole_surface(xsurface->surface, xsurface->x, xsurface->y); } static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, unmap); + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + desktop_damage_whole_surface(xsurface->surface, xsurface->x, xsurface->y); wl_list_remove(&surface->link); wl_list_remove(&surface->commit.link); - // TODO: damage tracking } static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { diff --git a/sway/meson.build b/sway/meson.build index ec7b4c42b..29aaa7b71 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -8,6 +8,7 @@ sway_sources = files( 'ipc-server.c', 'security.c', + 'desktop/desktop.c', 'desktop/output.c', 'desktop/layer_shell.c', 'desktop/wl_shell.c', From 076bedb85eface4a6c41a0e99059c89186bdb275 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 18:31:19 -0400 Subject: [PATCH 455/522] Add container_damage_whole --- include/sway/output.h | 4 ++-- include/sway/tree/container.h | 8 +++++--- sway/desktop/desktop.c | 5 +++-- sway/desktop/output.c | 4 ++-- sway/tree/container.c | 13 +++++++++++-- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 9964a484c..8945dde4e 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -37,8 +37,8 @@ void output_damage_whole(struct sway_output *output); void output_damage_whole_view(struct sway_output *output, struct sway_view *view); -void output_damage_whole_surface(struct sway_output *output, - struct wlr_surface *surface, double ox, double oy); +void output_damage_whole_rect(struct sway_output *output, double ox, double oy, + int width, int height); struct sway_container *output_by_name(const char *name); diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 3a3a94292..7acb607b6 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -97,8 +97,7 @@ struct sway_container *container_create(enum sway_container_type type); const char *container_type_to_str(enum sway_container_type type); -struct sway_container *output_create( - struct sway_output *sway_output); +struct sway_container *output_create(struct sway_output *sway_output); /** * Create a new container container. A container container can be a a child of @@ -116,7 +115,8 @@ struct sway_container *output_create(struct sway_output *sway_output); * Create a new workspace container. Workspaces are children of an output * container and are ordered alphabetically by name. */ -struct sway_container *workspace_create(struct sway_container *output, const char *name); +struct sway_container *workspace_create(struct sway_container *output, + const char *name); /* * Create a new view container. A view can be a child of a workspace container @@ -182,4 +182,6 @@ bool container_has_child(struct sway_container *con, void container_create_notify(struct sway_container *container); +void container_damage_whole(struct sway_container *container); + #endif diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index 78a2d49fd..c23d988cb 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c @@ -7,8 +7,9 @@ void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *cont = root_container.children->items[i]; if (cont->type == C_OUTPUT) { - output_damage_whole_surface(cont->sway_output, surface, - lx - cont->x, ly - cont->y); + output_damage_whole_rect(cont->sway_output, + lx - cont->x, ly - cont->y, + surface->current->width, surface->current->height); } } } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0ae5e7822..09244460c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -341,8 +341,8 @@ void output_damage_whole_view(struct sway_output *output, output_damage_whole(output); } -void output_damage_whole_surface(struct sway_output *output, - struct wlr_surface *surface, double ox, double oy) { +void output_damage_whole_rect(struct sway_output *output, + double ox, double oy, int width, int height) { // TODO output_damage_whole(output); } diff --git a/sway/tree/container.c b/sway/tree/container.c index 8fc9e3e87..1450db6d3 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -512,9 +512,18 @@ static bool find_child_func(struct sway_container *con, void *data) { bool container_has_child(struct sway_container *con, struct sway_container *child) { - if (con == NULL || con->type == C_VIEW || - con->children->length == 0) { + if (con == NULL || con->type == C_VIEW || con->children->length == 0) { return false; } return container_find(con, find_child_func, child); } + +void container_damage_whole(struct sway_container *con) { + struct sway_container *output = con; + if (output->type != C_OUTPUT) { + output = container_parent(output, C_OUTPUT); + } + + output_damage_whole_rect(output->sway_output, con->x, con->y, con->width, + con->height); +} From 6b9b03f09ffae8c8a9d7150d1ec68845c9e0ebf0 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 18:33:13 -0400 Subject: [PATCH 456/522] Remove outdated TODO --- sway/tree/view.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 293edc959..d3e3186ce 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -161,8 +161,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { view_damage_whole(view); view_update_outputs(view, NULL); - - // TODO: create view children for subsurfaces } void view_unmap(struct sway_view *view) { From d65d001aa55c71f67a35c8ce78d3cb3f7f5fd65e Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 18:38:50 -0400 Subject: [PATCH 457/522] Fix desktop_damage_whole_surface --- include/sway/output.h | 7 +++++-- sway/desktop/desktop.c | 5 ++--- sway/desktop/output.c | 10 ++++++++-- sway/tree/container.c | 4 +--- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 8945dde4e..4bffa2b7d 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -34,11 +34,14 @@ struct sway_output { void output_damage_whole(struct sway_output *output); +void output_damage_whole_surface(struct sway_output *output, + double ox, double oy, struct wlr_surface *surface); + void output_damage_whole_view(struct sway_output *output, struct sway_view *view); -void output_damage_whole_rect(struct sway_output *output, double ox, double oy, - int width, int height); +void output_damage_whole_container(struct sway_output *output, + struct sway_container *con); struct sway_container *output_by_name(const char *name); diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index c23d988cb..3a13191f2 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c @@ -7,9 +7,8 @@ void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *cont = root_container.children->items[i]; if (cont->type == C_OUTPUT) { - output_damage_whole_rect(cont->sway_output, - lx - cont->x, ly - cont->y, - surface->current->width, surface->current->height); + output_damage_whole_surface(cont->sway_output, + lx - cont->x, ly - cont->y, surface); } } } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 09244460c..a7f40ef8a 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -335,14 +335,20 @@ void output_damage_whole(struct sway_output *output) { wlr_output_damage_add_whole(output->damage); } +void output_damage_whole_surface(struct sway_output *output, + double ox, double oy, struct wlr_surface *surface) { + // TODO + output_damage_whole(output); +} + void output_damage_whole_view(struct sway_output *output, struct sway_view *view) { // TODO output_damage_whole(output); } -void output_damage_whole_rect(struct sway_output *output, - double ox, double oy, int width, int height) { +void output_damage_whole_container(struct sway_output *output, + struct sway_container *con) { // TODO output_damage_whole(output); } diff --git a/sway/tree/container.c b/sway/tree/container.c index 1450db6d3..404d413fd 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -523,7 +523,5 @@ void container_damage_whole(struct sway_container *con) { if (output->type != C_OUTPUT) { output = container_parent(output, C_OUTPUT); } - - output_damage_whole_rect(output->sway_output, con->x, con->y, con->width, - con->height); + output_damage_whole_container(output->sway_output, con); } From 641807d920854fdecc1307bd809c198db1a7dff1 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 18:48:35 -0400 Subject: [PATCH 458/522] Handle unmanaged surfaces motion --- include/sway/tree/view.h | 2 ++ sway/desktop/output.c | 13 +++++-------- sway/desktop/xwayland.c | 22 +++++++++++++++++++--- sway/input/cursor.c | 14 +++++--------- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index faf38bdf2..03d27cebb 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -87,6 +87,8 @@ struct sway_xwayland_unmanaged { struct wlr_xwayland_surface *wlr_xwayland_surface; struct wl_list link; + int lx, ly; + struct wl_listener request_configure; struct wl_listener commit; struct wl_listener map; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a7f40ef8a..aa18f1b8a 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -267,17 +267,14 @@ static void render_output(struct sway_output *output, struct timespec *when, // render unmanaged views on top struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; - struct sway_xwayland_unmanaged *sway_surface; - wl_list_for_each(sway_surface, unmanaged, link) { + struct sway_xwayland_unmanaged *unmanaged_surface; + wl_list_for_each(unmanaged_surface, unmanaged, link) { struct wlr_xwayland_surface *xsurface = - sway_surface->wlr_xwayland_surface; - if (xsurface->surface == NULL) { - continue; - } + unmanaged_surface->wlr_xwayland_surface; const struct wlr_box view_box = { - .x = xsurface->x, - .y = xsurface->y, + .x = unmanaged_surface->lx, + .y = unmanaged_surface->ly, .width = xsurface->width, .height = xsurface->height, }; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 4797b8011..e3da1da7d 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -29,19 +29,35 @@ static void unmanaged_handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, commit); struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; - desktop_damage_from_surface(xsurface->surface, xsurface->x, xsurface->y); - // TODO: handle window motion + + if (xsurface->x != surface->lx || xsurface->y != surface->ly) { + // Surface has moved + desktop_damage_whole_surface(xsurface->surface, + surface->lx, surface->ly); + surface->lx = xsurface->x; + surface->ly = xsurface->y; + desktop_damage_whole_surface(xsurface->surface, + surface->lx, surface->ly); + } else { + desktop_damage_from_surface(xsurface->surface, + xsurface->x, xsurface->y); + } } static void unmanaged_handle_map(struct wl_listener *listener, void *data) { struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, map); struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + wl_list_insert(&root_container.sway_root->xwayland_unmanaged, &surface->link); + wl_signal_add(&xsurface->surface->events.commit, &surface->commit); surface->commit.notify = unmanaged_handle_commit; - desktop_damage_whole_surface(xsurface->surface, xsurface->x, xsurface->y); + + surface->lx = xsurface->x; + surface->ly = xsurface->y; + desktop_damage_whole_surface(xsurface->surface, surface->lx, surface->ly); } static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 195ddce93..b83bc9fe4 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -48,17 +48,13 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, struct wlr_surface **surface, double *sx, double *sy) { // check for unmanaged views first struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; - struct sway_xwayland_unmanaged *sway_surface; - wl_list_for_each_reverse(sway_surface, unmanaged, link) { + struct sway_xwayland_unmanaged *unmanaged_surface; + wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { struct wlr_xwayland_surface *xsurface = - sway_surface->wlr_xwayland_surface; - if (xsurface->surface == NULL) { - continue; - } - + unmanaged_surface->wlr_xwayland_surface; struct wlr_box box = { - .x = xsurface->x, - .y = xsurface->y, + .x = unmanaged_surface->lx, + .y = unmanaged_surface->ly, .width = xsurface->width, .height = xsurface->height, }; From 235798ff8e9e60d919cbb671f7c399ff97c164d5 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 5 Apr 2018 19:01:03 -0400 Subject: [PATCH 459/522] dont send ipc events when there are no listeners --- sway/ipc-server.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/sway/ipc-server.c b/sway/ipc-server.c index df5fb699f..5fe5c7555 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -241,10 +241,25 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { return 0; } -static void ipc_send_event(const char *json_string, enum ipc_command_type event) { - int i; +static bool ipc_has_event_listeners(enum ipc_command_type event) { + bool has_listeners = false; + struct ipc_client *client; - for (i = 0; i < ipc_client_list->length; i++) { + for (int i = 0; i < ipc_client_list->length; i++) { + client = ipc_client_list->items[i]; + if ((client->subscribed_events & event_mask(event)) == 0) { + continue; + } + has_listeners = true; + break; + } + + return has_listeners; +} + +static void ipc_send_event(const char *json_string, enum ipc_command_type event) { + struct ipc_client *client; + for (int i = 0; i < ipc_client_list->length; i++) { client = ipc_client_list->items[i]; if ((client->subscribed_events & event_mask(event)) == 0) { continue; @@ -259,6 +274,9 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) void ipc_event_workspace(struct sway_container *old, struct sway_container *new, const char *change) { + if (!ipc_has_event_listeners(IPC_EVENT_WORKSPACE)) { + return; + } 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)); @@ -284,6 +302,9 @@ void ipc_event_workspace(struct sway_container *old, } void ipc_event_window(struct sway_container *window, const char *change) { + if (!ipc_has_event_listeners(IPC_EVENT_WINDOW)) { + return; + } 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)); @@ -295,6 +316,9 @@ void ipc_event_window(struct sway_container *window, const char *change) { } void ipc_event_barconfig_update(struct bar_config *bar) { + if (!ipc_has_event_listeners(IPC_EVENT_BARCONFIG_UPDATE)) { + return; + } wlr_log(L_DEBUG, "Sending barconfig_update event"); json_object *json = ipc_json_describe_bar_config(bar); @@ -304,6 +328,9 @@ void ipc_event_barconfig_update(struct bar_config *bar) { } void ipc_event_mode(const char *mode) { + if (!ipc_has_event_listeners(IPC_EVENT_MODE)) { + return; + } wlr_log(L_DEBUG, "Sending mode::%s event", mode); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(mode)); From 6b308dbeb7a1f2b26279481c001c15434d2468cb Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 5 Apr 2018 22:50:10 -0400 Subject: [PATCH 460/522] address feedback --- sway/ipc-json.c | 44 ++++++++++++++------------------------------ sway/ipc-server.c | 12 +++--------- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 44828a0df..2c7c73254 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -12,37 +12,22 @@ #include "wlr-layer-shell-unstable-v1-protocol.h" static const char *ipc_json_layout_description(enum sway_container_layout l) { - const char *layout; - switch (l) { case L_VERT: - layout = "splitv"; - break; - + return "splitv"; case L_HORIZ: - layout = "splith"; - break; - + return "splith"; case L_TABBED: - layout = "tabbed"; - break; - + return "tabbed"; case L_STACKED: - layout = "stacked"; - break; - + return "stacked"; case L_FLOATING: - layout = "floating"; - break; - - case L_NONE: // fallthrough - case L_LAYOUTS: // fallthrough; this should never happen, I'm just trying to silence compiler warnings - default: - layout = "null"; + return "floating"; + case L_NONE: + case L_LAYOUTS: break; } - - return layout; + return "none"; } json_object *ipc_json_get_version() { @@ -149,9 +134,8 @@ static void ipc_json_describe_output(struct sway_container *container, json_obje json_object_new_int(mode->refresh)); json_object_array_add(modes_array, mode_object); } + json_object_object_add(object, "modes", modes_array); - - json_object_object_add(object, "layout", json_object_new_string("output")); } @@ -166,8 +150,7 @@ static void ipc_json_describe_workspace(struct sway_container *workspace, json_object_object_add(object, "urgent", json_object_new_boolean(false)); const char *layout = ipc_json_layout_description(workspace->workspace_layout); - json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? - NULL : json_object_new_string(layout)); + json_object_object_add(object, "layout", json_object_new_string(layout)); } static void ipc_json_describe_view(struct sway_container *c, json_object *object) { @@ -176,10 +159,11 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object json_object_object_add(object, "type", json_object_new_string("con")); if (c->parent) { - const char *layout = (c->parent->type == C_CONTAINER) ? - ipc_json_layout_description(c->parent->layout) : "none"; + enum sway_container_layout layout = (c->parent->type == C_CONTAINER) ? + c->parent->layout : c->layout; + json_object_object_add(object, "layout", - (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); + json_object_new_string(ipc_json_layout_description(layout))); } } diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 5fe5c7555..045802e10 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -242,19 +242,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { } static bool ipc_has_event_listeners(enum ipc_command_type event) { - bool has_listeners = false; - - struct ipc_client *client; for (int i = 0; i < ipc_client_list->length; i++) { - client = ipc_client_list->items[i]; + struct ipc_client *client = ipc_client_list->items[i]; if ((client->subscribed_events & event_mask(event)) == 0) { - continue; + return true; } - has_listeners = true; - break; } - - return has_listeners; + return false; } static void ipc_send_event(const char *json_string, enum ipc_command_type event) { From c2b1beef153828514707ff6e40269dc1ed7fb790 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 23:22:08 -0400 Subject: [PATCH 461/522] Remove L_TYPES --- include/sway/tree/container.h | 4 +--- sway/ipc-json.c | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 7acb607b6..4c60530fa 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -24,6 +24,7 @@ enum sway_container_type { C_CONTAINER, C_VIEW, + // Keep last C_TYPES, }; @@ -34,9 +35,6 @@ enum sway_container_layout { L_STACKED, L_TABBED, L_FLOATING, - - // Keep last - L_LAYOUTS, }; enum sway_container_border { diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 2c7c73254..f9c6c90bc 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -24,7 +24,6 @@ static const char *ipc_json_layout_description(enum sway_container_layout l) { case L_FLOATING: return "floating"; case L_NONE: - case L_LAYOUTS: break; } return "none"; From 0f1068ed2571210817ec5d139a44cadc4fa67565 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 5 Apr 2018 23:25:42 -0400 Subject: [PATCH 462/522] Remove wlc-git from .build.yml --- .build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.build.yml b/.build.yml index 40be2300f..3cfb7483c 100644 --- a/.build.yml +++ b/.build.yml @@ -2,7 +2,6 @@ image: archlinux packages: - meson - - wlc-git - xorg-server-xwayland - xcb-util-image - json-c From 88e3e5ea5dc6792080eab8a2c81fbda3dde3ae66 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 23:50:21 -0400 Subject: [PATCH 463/522] Fix wl_output enter/leave events Fixes #1739 --- include/sway/tree/view.h | 1 + sway/tree/view.c | 68 ++++++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 03d27cebb..6b2d279e5 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -51,6 +51,7 @@ struct sway_view { } events; struct wl_listener surface_new_subsurface; + struct wl_listener container_reparent; }; struct sway_xdg_shell_v6_view { diff --git a/sway/tree/view.c b/sway/tree/view.c index d3e3186ce..16d48cc9c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -102,28 +102,6 @@ static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { box->height = view->height; } -static void view_update_outputs(struct sway_view *view, - const struct wlr_box *before) { - struct wlr_box box; - view_get_layout_box(view, &box); - - struct wlr_output_layout *output_layout = - root_container.sway_root->output_layout; - struct wlr_output_layout_output *layout_output; - wl_list_for_each(layout_output, &output_layout->outputs, link) { - bool intersected = before != NULL && wlr_output_layout_intersects( - output_layout, layout_output->output, before); - bool intersects = wlr_output_layout_intersects(output_layout, - layout_output->output, &box); - if (intersected && !intersects) { - wlr_surface_send_leave(view->surface, layout_output->output); - } - if (!intersected && intersects) { - wlr_surface_send_enter(view->surface, layout_output->output); - } - } -} - static void view_subsurface_create(struct sway_view *view, struct wlr_subsurface *subsurface); @@ -138,6 +116,36 @@ static void view_handle_surface_new_subsurface(struct wl_listener *listener, view_subsurface_create(view, subsurface); } +static void view_handle_container_reparent(struct wl_listener *listener, + void *data) { + struct sway_view *view = + wl_container_of(listener, view, container_reparent); + struct sway_container *old_parent = data; + + struct sway_container *old_output = old_parent; + if (old_output != NULL && old_output->type != C_OUTPUT) { + old_output = container_parent(old_output, C_OUTPUT); + } + + struct sway_container *new_output = view->swayc->parent; + if (new_output != NULL && new_output->type != C_OUTPUT) { + new_output = container_parent(new_output, C_OUTPUT); + } + + if (old_output == new_output) { + return; + } + + if (old_output != NULL) { + wlr_surface_send_leave(view->surface, + old_output->sway_output->wlr_output); + } + if (new_output != NULL) { + wlr_surface_send_enter(view->surface, + new_output->sway_output->wlr_output); + } +} + void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { return; @@ -156,11 +164,14 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { &view->surface_new_subsurface); view->surface_new_subsurface.notify = view_handle_surface_new_subsurface; + wl_signal_add(&view->swayc->events.reparent, &view->container_reparent); + view->container_reparent.notify = view_handle_container_reparent; + arrange_windows(cont->parent, -1, -1); input_manager_set_focus(input_manager, cont); view_damage_whole(view); - view_update_outputs(view, NULL); + view_handle_container_reparent(&view->container_reparent, NULL); } void view_unmap(struct sway_view *view) { @@ -172,9 +183,10 @@ void view_unmap(struct sway_view *view) { view_damage_whole(view); - struct sway_container *parent = container_destroy(view->swayc); - wl_list_remove(&view->surface_new_subsurface.link); + wl_list_remove(&view->container_reparent.link); + + struct sway_container *parent = container_destroy(view->swayc); view->swayc = NULL; view->surface = NULL; @@ -187,12 +199,9 @@ void view_update_position(struct sway_view *view, double ox, double oy) { return; } - struct wlr_box box; - view_get_layout_box(view, &box); view_damage_whole(view); view->swayc->x = ox; view->swayc->y = oy; - view_update_outputs(view, &box); view_damage_whole(view); } @@ -201,12 +210,9 @@ void view_update_size(struct sway_view *view, int width, int height) { return; } - struct wlr_box box; - view_get_layout_box(view, &box); view_damage_whole(view); view->width = width; view->height = height; - view_update_outputs(view, &box); view_damage_whole(view); } From b08f7e5183d25ce0d4ae89796893a6d25d4a1b93 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 09:26:28 -0400 Subject: [PATCH 464/522] Fix deletion of still-visible workspaces on unfocus --- sway/input/seat.c | 4 +++- sway/tree/container.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index e3df69559..ad3584a09 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -6,6 +6,7 @@ #include #include #include "sway/tree/container.h" +#include "sway/tree/workspace.h" #include "sway/input/seat.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" @@ -398,7 +399,8 @@ void seat_set_focus_warp(struct sway_seat *seat, } if (last_ws) { ipc_event_workspace(last_ws, container, "focus"); - if (last_ws->children->length == 0) { + if (!workspace_is_visible(last_ws) + && last_ws->children->length == 0) { container_destroy(last_ws); } } diff --git a/sway/tree/container.c b/sway/tree/container.c index 41321dc82..ab8363bc3 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -216,6 +216,7 @@ static bool container_reap_empty(struct sway_container *con) { break; case C_WORKSPACE: if (!workspace_is_visible(con) && con->children->length == 0) { + wlr_log(L_DEBUG, "Destroying workspace via reaper"); container_workspace_destroy(con); return true; } From cca420b2f83da0af97de82677b7027710a0fd8d7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 09:32:38 -0400 Subject: [PATCH 465/522] Fix focus_follows_mouse issues --- sway/input/cursor.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index b83bc9fe4..6db615b1d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -116,7 +116,16 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, return ws; } - return NULL; + c = seat_get_focus_inactive(cursor->seat, output->swayc); + if (c) { + return c; + } + if (!c && output->swayc->children->length) { + c = output->swayc->children->items[0]; + return c; + } + + return output->swayc; } static void cursor_send_pointer_motion(struct sway_cursor *cursor, From d77a0119f46ab977beca6725efed38fcb5f9e434 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 09:43:12 -0400 Subject: [PATCH 466/522] Avoid arranging windows while reloading config --- sway/tree/layout.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 65fd5d4a3..343f349a4 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -228,6 +228,9 @@ static void apply_vert_layout(struct sway_container *container, const double x, void arrange_windows(struct sway_container *container, double width, double height) { + if (config->reloading) { + return; + } int i; if (width == -1 || height == -1) { width = container->width; @@ -246,7 +249,6 @@ void arrange_windows(struct sway_container *container, double x = 0, y = 0; switch (container->type) { case C_ROOT: - // TODO: wlr_output_layout probably for (i = 0; i < container->children->length; ++i) { struct sway_container *output = container->children->items[i]; wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", From 57954a2b24f1e211c3b8811fb898ef4e076cb098 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 13:49:37 -0400 Subject: [PATCH 467/522] Implement move [left|right|up|down] The exact semantics of this command are complicated. I'll describe each test scenario as s-expressions. Everything assumes L_HORIZ if not specified, but if you rotate everything 90 degrees the same test cases hold. ``` (container (view a) (view b focus) (view c)) -> move left (container (view b focus) (view a) (view c)) (container (view a) (view b focus) (view c)) -> move right (container (view a) (view c) (view b focus)) (container L_VERT (view a)) (container L_HORIZ (view b) (view c focus)) -> move up (container L_VERT (view a) (view c focus)) (container L_HORIZ (view b)) (workspace (view a) (view b focus) (view c)) -> move up (workspace [split direction flipped] (view b focus) (container (view a) (view c))) (workspace (view a) (view b focus) (view c)) -> move down (workspace [split direction flipped] (container (view a) (view c)) (view b focus))) Note: outputs use wlr_output_layout instead of assuming that i+/-1 is the next output in the move direction. (root (output X11-1 (workspace 1)) (output X11-2 (workspace 1 (view a focus) (view b))))) -> move left (root (output X11-1 (workspace 1 (view a focus))) (output X11-2 (workspace 1 (view b))))) (root (output X11-1 (workspace 1 (container (view a) (view b))) (output X11-2 (workspace 1 (view c focus))))) -> move left (root (output X11-1 (workspace 1 (container (view a) (view b)) (view c focus))) (output X11-2 (workspace 1))) ``` --- include/sway/tree/container.h | 7 + sway/commands/move.c | 4 + sway/tree/container.c | 46 +++--- sway/tree/layout.c | 294 +++++++++++++++++++++++++++++++--- 4 files changed, 306 insertions(+), 45 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 4c60530fa..2a8b8abaf 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -182,4 +182,11 @@ void container_create_notify(struct sway_container *container); void container_damage_whole(struct sway_container *container); +bool container_reap_empty(struct sway_container *con); + +struct sway_container *container_reap_empty_recursive( + struct sway_container *con); + +struct sway_container *container_flatten(struct sway_container *container); + #endif diff --git a/sway/commands/move.c b/sway/commands/move.c index c954ab94e..15a5ebc49 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -82,6 +82,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, config->handler_context.seat, ws); container_move_to(current, focus); seat_set_focus(config->handler_context.seat, old_parent); + container_reap_empty(old_parent); + container_reap_empty(focus->parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "output") == 0) { @@ -109,6 +111,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, struct sway_container *old_parent = current->parent; container_move_to(current, focus); seat_set_focus(config->handler_context.seat, old_parent); + container_reap_empty(old_parent); + container_reap_empty(focus->parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } return cmd_results_new(CMD_INVALID, "move", expected_syntax); diff --git a/sway/tree/container.c b/sway/tree/container.c index ab8363bc3..ea1c93bb6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -208,7 +208,7 @@ static void container_root_finish(struct sway_container *con) { wlr_log(L_ERROR, "TODO: destroy the root container"); } -static bool container_reap_empty(struct sway_container *con) { +bool container_reap_empty(struct sway_container *con) { switch (con->type) { case C_ROOT: case C_OUTPUT: @@ -225,14 +225,6 @@ static bool container_reap_empty(struct sway_container *con) { if (con->children->length == 0) { _container_destroy(con); return true; - } else if (con->children->length == 1) { - struct sway_container *child = con->children->items[0]; - if (child->type == C_CONTAINER) { - container_remove_child(child); - container_replace_child(con, child); - _container_destroy(con); - return true; - } } case C_VIEW: break; @@ -245,6 +237,29 @@ static bool container_reap_empty(struct sway_container *con) { return false; } +struct sway_container *container_reap_empty_recursive( + struct sway_container *con) { + while (con) { + struct sway_container *next = con->parent; + if (!container_reap_empty(con)) { + break; + } + con = next; + } + return con; +} + +struct sway_container *container_flatten(struct sway_container *container) { + while (container->type == C_CONTAINER && container->children->length == 1) { + struct sway_container *child = container->children->items[0]; + struct sway_container *parent = container->parent; + container_replace_child(container, child); + container_destroy(container); + container = parent; + } + return container; +} + struct sway_container *container_destroy(struct sway_container *con) { if (con == NULL) { return NULL; @@ -283,18 +298,7 @@ struct sway_container *container_destroy(struct sway_container *con) { break; } - struct sway_container *tmp = parent; - while (parent) { - tmp = parent->parent; - - if (!container_reap_empty(parent)) { - break; - } - - parent = tmp; - } - - return tmp; + return container_reap_empty_recursive(parent); } static void container_close_func(struct sway_container *container, void *data) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 343f349a4..a060cb852 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -100,13 +100,31 @@ static int index_child(const struct sway_container *child) { return i; } +void container_insert_child(struct sway_container *parent, + struct sway_container *child, int i) { + struct sway_container *old_parent = NULL; + list_insert(parent->children, i, child); + child->parent = parent; + if (old_parent && old_parent != parent) { + wl_signal_emit(&child->events.reparent, old_parent); + } +} + struct sway_container *container_add_sibling(struct sway_container *fixed, struct sway_container *active) { // TODO handle floating + struct sway_container *old_parent = NULL; + if (active->parent) { + old_parent = active->parent; + container_remove_child(active); + } struct sway_container *parent = fixed->parent; int i = index_child(fixed); list_insert(parent->children, i + 1, active); active->parent = parent; + if (old_parent && old_parent != parent) { + wl_signal_emit(&active->events.reparent, old_parent); + } return active->parent; } @@ -166,9 +184,253 @@ void container_move_to(struct sway_container *container, arrange_windows(new_parent, -1, -1); } +static bool sway_dir_to_wlr(enum movement_direction dir, + enum wlr_direction *out) { + switch (dir) { + case MOVE_UP: + *out = WLR_DIRECTION_UP; + break; + case MOVE_DOWN: + *out = WLR_DIRECTION_DOWN; + break; + case MOVE_LEFT: + *out = WLR_DIRECTION_LEFT; + break; + case MOVE_RIGHT: + *out = WLR_DIRECTION_RIGHT; + break; + default: + return false; + } + + return true; +} + +static bool is_parallel(enum sway_container_layout layout, + enum movement_direction dir) { + switch (layout) { + case L_TABBED: + case L_STACKED: + case L_HORIZ: + return dir == MOVE_LEFT || dir == MOVE_RIGHT; + case L_VERT: + return dir == MOVE_UP || dir == MOVE_DOWN; + default: + return false; + } +} + +static enum movement_direction invert_movement(enum movement_direction dir) { + switch (dir) { + case MOVE_LEFT: + return MOVE_RIGHT; + case MOVE_RIGHT: + return MOVE_LEFT; + case MOVE_UP: + return MOVE_DOWN; + case MOVE_DOWN: + return MOVE_LEFT; + default: + sway_assert(0, "This function expects left|right|up|down"); + return MOVE_LEFT; + } +} + +/* Gets the index of the most extreme member based on the movement offset */ +static int container_limit(struct sway_container *container, int offs) { + if (container->children->length == 0) { + return 0; + } + return offs < 0 ? 0 : container->children->length - 1; +} + +static int move_offs(enum movement_direction move_dir) { + return move_dir == MOVE_LEFT || move_dir == MOVE_UP ? -1 : 1; +} + +static void workspace_rejigger(struct sway_container *ws, + struct sway_container *child, enum movement_direction move_dir) { + struct sway_container *original_parent = child->parent; + struct sway_container *new_parent = + container_split(ws, ws->layout); + + container_remove_child(child); + for (int i = 0; i < ws->children->length; ++i) { + struct sway_container *_child = ws->children->items[i]; + container_move_to(new_parent, _child); + } + + int index = move_offs(move_dir); + container_insert_child(ws, child, index < 0 ? 0 : 1); + container_set_layout(ws, + move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT); + + container_flatten(ws); + container_reap_empty_recursive(original_parent); + arrange_windows(ws, -1, -1); +} + void container_move(struct sway_container *container, - enum movement_direction dir, int move_amt) { - // TODO + enum movement_direction move_dir, int move_amt) { + if (!sway_assert( + container->type != C_CONTAINER || container->type != C_VIEW, + "Can only move containers and views")) { + return; + } + int offs = move_offs(move_dir); + + struct sway_container *sibling = NULL; + struct sway_container *current = container; + struct sway_container *parent = current->parent; + + if (parent != container_flatten(parent)) { + // Special case: we were the last one in this container, so flatten it + // and leave + return; + } + + while (!sibling) { + if (current->type == C_ROOT) { + return; + } + + parent = current->parent; + wlr_log(L_DEBUG, "Visiting %p %s '%s'", current, + container_type_to_str(current->type), current->name); + + int index = index_child(current); + int limit = container_limit(parent, offs); + + switch (current->type) { + case C_OUTPUT: { + enum wlr_direction wlr_dir; + sway_dir_to_wlr(move_dir, &wlr_dir); + double ref_x = current->x + current->width / 2; + double ref_y = current->y + current->height / 2; + ref_x += current->sway_output->wlr_output->lx; + ref_y += current->sway_output->wlr_output->ly; + struct wlr_output *next = wlr_output_layout_adjacent_output( + root_container.sway_root->output_layout, wlr_dir, + current->sway_output->wlr_output, + current->x, current->y); + if (!next) { + wlr_log(L_DEBUG, "Hit edge of output, nowhere else to go"); + return; + } + struct sway_output *next_output = next->data; + current = next_output->swayc; + wlr_log(L_DEBUG, "Selected next output (%s)", current->name); + // Select workspace and get outta here + current = seat_get_focus_inactive( + config->handler_context.seat, current); + if (current->type != C_WORKSPACE) { + current = container_parent(current, C_WORKSPACE); + } + sibling = current; + break; + } + case C_WORKSPACE: + if (!is_parallel(current->layout, move_dir)) { + // Special case + wlr_log(L_DEBUG, "Rejiggering the workspace"); + workspace_rejigger(current, container, move_dir); + return; + } else { + wlr_log(L_DEBUG, "Selecting output"); + current = current->parent; + } + break; + case C_CONTAINER: + case C_VIEW: + if (is_parallel(parent->layout, move_dir)) { + if (index == limit) { + if (current->parent == container->parent) { + wlr_log(L_DEBUG, "Hit limit, selecting parent"); + current = current->parent; + } else { + wlr_log(L_DEBUG, "Hit limit, " + "promoting descendant to sibling"); + // Special case + struct sway_container *old_parent = container->parent; + container_remove_child(container); + container_insert_child(current->parent, container, + index + (offs < 0 ? 0 : 1)); + container->width = container->height = 0; + arrange_windows(current->parent, -1, -1); + arrange_windows(old_parent, -1, -1); + return; + } + } else { + wlr_log(L_DEBUG, "Selecting sibling"); + sibling = parent->children->items[index + offs]; + } + } else { + wlr_log(L_DEBUG, "Moving up to find a parallel container"); + current = current->parent; + } + break; + default: + sway_assert(0, "Not expecting to see container of type %s here", + container_type_to_str(current->type)); + return; + } + } + + // Part two: move stuff around + int index = index_child(container); + struct sway_container *old_parent = container->parent; + + switch (sibling->type) { + case C_VIEW: + if (sibling->parent == container->parent) { + wlr_log(L_DEBUG, "Swapping siblings"); + sibling->parent->children->items[index + offs] = container; + sibling->parent->children->items[index] = sibling; + arrange_windows(sibling->parent, -1, -1); + } else { + wlr_log(L_DEBUG, "Promoting to sibling of cousin"); + container_remove_child(container); + container_insert_child(sibling->parent, container, + index_child(sibling) + (offs > 0 ? 0 : 1)); + container->width = container->height = 0; + arrange_windows(sibling->parent, -1, -1); + arrange_windows(old_parent, -1, -1); + } + break; + case C_WORKSPACE: // Note: only in the case of moving between outputs + case C_CONTAINER: + if (is_parallel(sibling->layout, move_dir)) { + int limit = container_limit(sibling, move_dir); + wlr_log(L_DEBUG, "Reparenting container (paralell)"); + limit = limit != 0 ? limit + 1 : limit; // Convert to index + wlr_log(L_DEBUG, "Reparenting container (paralell) %d", limit); + container_remove_child(container); + container_insert_child(sibling, container, limit); + container->width = container->height = 0; + arrange_windows(sibling, -1, -1); + arrange_windows(old_parent, -1, -1); + } else { + wlr_log(L_DEBUG, "Reparenting container (perpendicular)"); + container_remove_child(container); + struct sway_container *focus_inactive = seat_get_focus_inactive( + config->handler_context.seat, sibling); + if (focus_inactive) { + container_add_sibling(focus_inactive, container); + } else if (sibling->children->length) { + container_add_sibling(sibling->children->items[0], container); + } else { + container_add_child(sibling, container); + } + container->width = container->height = 0; + arrange_windows(sibling, -1, -1); + arrange_windows(old_parent, -1, -1); + } + break; + default: + sway_assert(0, "Not expecting to see container of type %s here", + container_type_to_str(sibling->type)); + return; + } } enum sway_container_layout container_get_default_layout( @@ -320,6 +582,7 @@ void arrange_windows(struct sway_container *container, container->children->length); break; } + container_damage_whole(container); } static void apply_horiz_layout(struct sway_container *container, @@ -512,28 +775,6 @@ static void get_layout_center_position(struct sway_container *container, } } -static bool sway_dir_to_wlr(enum movement_direction dir, - enum wlr_direction *out) { - switch (dir) { - case MOVE_UP: - *out = WLR_DIRECTION_UP; - break; - case MOVE_DOWN: - *out = WLR_DIRECTION_DOWN; - break; - case MOVE_LEFT: - *out = WLR_DIRECTION_LEFT; - break; - case MOVE_RIGHT: - *out = WLR_DIRECTION_RIGHT; - break; - default: - return false; - } - - return true; -} - static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { if (output == NULL) { return NULL; @@ -673,6 +914,9 @@ struct sway_container *container_replace_child(struct sway_container *child, int i = index_child(child); // TODO floating + if (new_child->parent) { + container_remove_child(new_child); + } parent->children->items[i] = new_child; new_child->parent = parent; child->parent = NULL; @@ -718,7 +962,9 @@ struct sway_container *container_split(struct sway_container *child, } container_add_child(workspace, cont); + enum sway_container_layout old_layout = workspace->layout; container_set_layout(workspace, layout); + cont->layout = old_layout; if (set_focus) { seat_set_focus(seat, cont); From efac07db5fc066dd8f6d5e0dda63b463d13de0d6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 5 Apr 2018 23:05:43 -0400 Subject: [PATCH 468/522] Fix workspaces not updated on swaybar --- sway/tree/layout.c | 13 ++++++++++++- swaybar/ipc.c | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index a060cb852..e91fd5acb 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -403,7 +403,6 @@ void container_move(struct sway_container *container, int limit = container_limit(sibling, move_dir); wlr_log(L_DEBUG, "Reparenting container (paralell)"); limit = limit != 0 ? limit + 1 : limit; // Convert to index - wlr_log(L_DEBUG, "Reparenting container (paralell) %d", limit); container_remove_child(container); container_insert_child(sibling, container, limit); container->width = container->height = 0; @@ -431,6 +430,18 @@ void container_move(struct sway_container *container, container_type_to_str(sibling->type)); return; } + + struct sway_container *last_ws = old_parent; + struct sway_container *next_ws = container->parent; + if (last_ws && last_ws->type != C_WORKSPACE) { + last_ws = container_parent(last_ws, C_WORKSPACE); + } + if (next_ws && next_ws->type != C_WORKSPACE) { + next_ws = container_parent(next_ws, C_WORKSPACE); + } + if (last_ws && next_ws && last_ws != next_ws) { + ipc_event_workspace(last_ws, container, "focus"); + } } enum sway_container_layout container_get_default_layout( diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 92dbb8ead..e6231bd2a 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -331,7 +331,7 @@ bool handle_ipc_readable(struct swaybar *bar) { switch (resp->type) { case IPC_EVENT_WORKSPACE: ipc_get_workspaces(bar); - break; + return true; case IPC_EVENT_MODE: { json_object *result = json_tokener_parse(resp->payload); if (!result) { From a06052ad9da8f5e03b17aa791be49189f21b7a4f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 5 Apr 2018 23:22:33 -0400 Subject: [PATCH 469/522] Fix splitting workspaces --- sway/tree/layout.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index e91fd5acb..0011a9e3b 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -951,6 +951,14 @@ struct sway_container *container_split(struct sway_container *child, if (!sway_assert(child, "child cannot be null")) { return NULL; } + if (child->type == C_WORKSPACE && child->children->length == 0) { + // Special case: this just behaves like splitt + child->prev_layout = child->layout; + child->layout = layout; + arrange_windows(child, -1, -1); + return child; + } + struct sway_container *cont = container_create(C_CONTAINER); wlr_log(L_DEBUG, "creating container %p around %p", cont, child); From 290c9162901008d306b68566e4a5c2a778d19db8 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 6 Apr 2018 10:26:32 -0400 Subject: [PATCH 470/522] Send surface enter/leave events to view children --- include/sway/tree/view.h | 5 +++++ sway/desktop/xdg_shell_v6.c | 10 ++++++++++ sway/desktop/xwayland.c | 3 +++ sway/tree/view.c | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 6b2d279e5..611c4f0bc 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -28,6 +28,8 @@ struct sway_view_impl { void (*configure)(struct sway_view *view, double ox, double oy, int width, int height); void (*set_activated)(struct sway_view *view, bool activated); + void (*for_each_surface)(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data); void (*close)(struct sway_view *view); void (*destroy)(struct sway_view *view); }; @@ -159,6 +161,9 @@ void view_damage_whole(struct sway_view *view); void view_damage_from(struct sway_view *view); +void view_for_each_surface(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data); + // view implementation void view_init(struct sway_view *view, enum sway_view_type type, diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index c66cc39a4..8361aab34 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -118,6 +118,15 @@ static void set_activated(struct sway_view *view, bool activated) { } } +static void for_each_surface(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (xdg_shell_v6_view_from_view(view) == NULL) { + return; + } + wlr_xdg_surface_v6_for_each_surface(view->wlr_xdg_surface_v6, iterator, + user_data); +} + static void _close(struct sway_view *view) { if (xdg_shell_v6_view_from_view(view) == NULL) { return; @@ -146,6 +155,7 @@ static const struct sway_view_impl view_impl = { .get_prop = get_prop, .configure = configure, .set_activated = set_activated, + .for_each_surface = for_each_surface, .close = _close, .destroy = destroy, }; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index e3da1da7d..10bfcc895 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -58,6 +58,9 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) { surface->lx = xsurface->x; surface->ly = xsurface->y; desktop_damage_whole_surface(xsurface->surface, surface->lx, surface->ly); + + // TODO: we don't send surface enter/leave events to xwayland unmanaged + // surfaces, but xwayland doesn't support HiDPI anyway } static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 16d48cc9c..9855c5e15 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -102,6 +102,15 @@ static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { box->height = view->height; } +void view_for_each_surface(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (view->impl->for_each_surface) { + view->impl->for_each_surface(view, iterator, user_data); + } else { + wlr_surface_for_each_surface(view->surface, iterator, user_data); + } +} + static void view_subsurface_create(struct sway_view *view, struct wlr_subsurface *subsurface); @@ -116,6 +125,18 @@ static void view_handle_surface_new_subsurface(struct wl_listener *listener, view_subsurface_create(view, subsurface); } +static void surface_send_enter_iterator(struct wlr_surface *surface, + int x, int y, void *data) { + struct wlr_output *wlr_output = data; + wlr_surface_send_enter(surface, wlr_output); +} + +static void surface_send_leave_iterator(struct wlr_surface *surface, + int x, int y, void *data) { + struct wlr_output *wlr_output = data; + wlr_surface_send_leave(surface, wlr_output); +} + static void view_handle_container_reparent(struct wl_listener *listener, void *data) { struct sway_view *view = @@ -137,11 +158,11 @@ static void view_handle_container_reparent(struct wl_listener *listener, } if (old_output != NULL) { - wlr_surface_send_leave(view->surface, + view_for_each_surface(view, surface_send_leave_iterator, old_output->sway_output->wlr_output); } if (new_output != NULL) { - wlr_surface_send_enter(view->surface, + view_for_each_surface(view, surface_send_enter_iterator, new_output->sway_output->wlr_output); } } @@ -283,6 +304,14 @@ void view_child_init(struct sway_view_child *child, wl_signal_add(&view->events.unmap, &child->view_unmap); child->view_unmap.notify = view_child_handle_view_unmap; + struct sway_container *output = child->view->swayc->parent; + if (output != NULL) { + if (output->type != C_OUTPUT) { + output = container_parent(output, C_OUTPUT); + } + wlr_surface_send_enter(child->surface, output->sway_output->wlr_output); + } + view_init_subsurfaces(child->view, surface); // TODO: only damage the whole child From 516f5454adb3fc7dd2e02258251b7cb6d6949aa3 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 6 Apr 2018 11:27:40 -0400 Subject: [PATCH 471/522] Simplify damage tracking functions, use them in layer shell --- include/sway/desktop.h | 7 ++---- include/sway/output.h | 8 +++---- include/sway/tree/view.h | 4 +--- sway/commands/opacity.c | 5 +---- sway/desktop/desktop.c | 14 ++++-------- sway/desktop/layer_shell.c | 44 ++++++++++++++++++++++--------------- sway/desktop/output.c | 8 +++---- sway/desktop/wl_shell.c | 2 +- sway/desktop/xdg_shell_v6.c | 2 +- sway/desktop/xwayland.c | 18 +++++++-------- sway/tree/view.c | 27 ++++++++++------------- 11 files changed, 64 insertions(+), 75 deletions(-) diff --git a/include/sway/desktop.h b/include/sway/desktop.h index 96bdc94cc..f1ad759a1 100644 --- a/include/sway/desktop.h +++ b/include/sway/desktop.h @@ -1,7 +1,4 @@ #include -void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, - double ly); - -void desktop_damage_from_surface(struct wlr_surface *surface, double lx, - double ly); +void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, + bool whole); diff --git a/include/sway/output.h b/include/sway/output.h index 4bffa2b7d..565715480 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -34,11 +34,11 @@ struct sway_output { void output_damage_whole(struct sway_output *output); -void output_damage_whole_surface(struct sway_output *output, - double ox, double oy, struct wlr_surface *surface); +void output_damage_surface(struct sway_output *output, double ox, double oy, + struct wlr_surface *surface, bool whole); -void output_damage_whole_view(struct sway_output *output, - struct sway_view *view); +void output_damage_view(struct sway_output *output, struct sway_view *view, + bool whole); void output_damage_whole_container(struct sway_output *output, struct sway_container *con); diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 611c4f0bc..b51c54b53 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -157,9 +157,7 @@ void view_set_activated(struct sway_view *view, bool activated); void view_close(struct sway_view *view); -void view_damage_whole(struct sway_view *view); - -void view_damage_from(struct sway_view *view); +void view_damage(struct sway_view *view, bool whole); void view_for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); diff --git a/sway/commands/opacity.c b/sway/commands/opacity.c index b8cd1f09a..68fd9f427 100644 --- a/sway/commands/opacity.c +++ b/sway/commands/opacity.c @@ -30,10 +30,7 @@ struct cmd_results *cmd_opacity(int argc, char **argv) { } con->alpha = opacity; - - if (con->type == C_VIEW) { - view_damage_whole(con->sway_view); - } + container_damage_whole(con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index 3a13191f2..66f33151a 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c @@ -2,19 +2,13 @@ #include "sway/desktop.h" #include "sway/output.h" -void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, - double ly) { +void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, + bool whole) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *cont = root_container.children->items[i]; if (cont->type == C_OUTPUT) { - output_damage_whole_surface(cont->sway_output, - lx - cont->x, ly - cont->y, surface); + output_damage_surface(cont->sway_output, lx - cont->x, ly - cont->y, + surface, whole); } } } - -void desktop_damage_from_surface(struct wlr_surface *surface, double lx, - double ly) { - // TODO - desktop_damage_whole_surface(surface, lx, ly); -} diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 663ec7baf..f841e5f10 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -229,33 +229,39 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { wl_container_of(listener, layer, surface_commit); struct wlr_layer_surface *layer_surface = layer->layer_surface; struct wlr_output *wlr_output = layer_surface->output; - if (wlr_output != NULL) { - struct sway_output *output = wlr_output->data; - struct wlr_box old_geo = layer->geo; - arrange_layers(output); - if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { - // TODO DAMAGE apply whole surface from previous and new geos - } else { - // TODO DAMAGE from surface damage - } - wlr_output_damage_add_box(output->damage, &old_geo); - wlr_output_damage_add_box(output->damage, &layer->geo); + if (wlr_output == NULL) { + return; + } + + struct sway_output *output = wlr_output->data; + struct wlr_box old_geo = layer->geo; + arrange_layers(output); + if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { + output_damage_surface(output, old_geo.x, old_geo.y, + layer_surface->surface, true); + output_damage_surface(output, layer->geo.x, layer->geo.y, + layer_surface->surface, true); + } else { + output_damage_surface(output, layer->geo.x, layer->geo.y, + layer_surface->surface, false); } } static void unmap(struct sway_layer_surface *sway_layer) { struct wlr_output *wlr_output = sway_layer->layer_surface->output; - if (wlr_output != NULL) { - struct sway_output *output = wlr_output->data; - wlr_output_damage_add_box(output->damage, &sway_layer->geo); + if (wlr_output == NULL) { + return; } + struct sway_output *output = wlr_output->data; + output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, + sway_layer->layer_surface->surface, true); } static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_layer_surface *sway_layer = wl_container_of(listener, - sway_layer, destroy); + struct sway_layer_surface *sway_layer = + wl_container_of(listener, sway_layer, destroy); wlr_log(L_DEBUG, "Layer surface destroyed (%s)", - sway_layer->layer_surface->namespace); + sway_layer->layer_surface->namespace); if (sway_layer->layer_surface->mapped) { unmap(sway_layer); } @@ -277,7 +283,9 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_layer_surface *sway_layer = wl_container_of(listener, sway_layer, map); struct sway_output *output = sway_layer->layer_surface->output->data; - wlr_output_damage_add_box(output->damage, &sway_layer->geo); + output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, + sway_layer->layer_surface->surface, true); + // TODO: send enter to subsurfaces and popups wlr_surface_send_enter(sway_layer->layer_surface->surface, sway_layer->layer_surface->output); } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index aa18f1b8a..3bbd0bb2c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -332,14 +332,14 @@ void output_damage_whole(struct sway_output *output) { wlr_output_damage_add_whole(output->damage); } -void output_damage_whole_surface(struct sway_output *output, - double ox, double oy, struct wlr_surface *surface) { +void output_damage_surface(struct sway_output *output, double ox, double oy, + struct wlr_surface *surface, bool whole) { // TODO output_damage_whole(output); } -void output_damage_whole_view(struct sway_output *output, - struct sway_view *view) { +void output_damage_view(struct sway_output *output, struct sway_view *view, + bool whole) { // TODO output_damage_whole(output); } diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index fff31da81..b63c220c6 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -79,7 +79,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { // TODO: Let floating views do whatever view_update_size(view, wl_shell_view->pending_width, wl_shell_view->pending_height); - view_damage_from(view); + view_damage(view, false); } static void handle_destroy(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 8361aab34..b82eec8fb 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -169,7 +169,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { // TODO: Let floating views do whatever view_update_size(view, xdg_shell_v6_view->pending_width, xdg_shell_v6_view->pending_height); - view_damage_from(view); + view_damage(view, false); } static void handle_new_popup(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 10bfcc895..6de1365d5 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -32,15 +32,15 @@ static void unmanaged_handle_commit(struct wl_listener *listener, void *data) { if (xsurface->x != surface->lx || xsurface->y != surface->ly) { // Surface has moved - desktop_damage_whole_surface(xsurface->surface, - surface->lx, surface->ly); + desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, + true); surface->lx = xsurface->x; surface->ly = xsurface->y; - desktop_damage_whole_surface(xsurface->surface, - surface->lx, surface->ly); + desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, + true); } else { - desktop_damage_from_surface(xsurface->surface, - xsurface->x, xsurface->y); + desktop_damage_surface(xsurface->surface, xsurface->x, xsurface->y, + false); } } @@ -57,7 +57,7 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) { surface->lx = xsurface->x; surface->ly = xsurface->y; - desktop_damage_whole_surface(xsurface->surface, surface->lx, surface->ly); + desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true); // TODO: we don't send surface enter/leave events to xwayland unmanaged // surfaces, but xwayland doesn't support HiDPI anyway @@ -67,7 +67,7 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, unmap); struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; - desktop_damage_whole_surface(xsurface->surface, xsurface->x, xsurface->y); + desktop_damage_surface(xsurface->surface, xsurface->x, xsurface->y, true); wl_list_remove(&surface->link); wl_list_remove(&surface->commit.link); } @@ -209,7 +209,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { // TODO: Let floating views do whatever view_update_size(view, xwayland_view->pending_width, xwayland_view->pending_height); - view_damage_from(view); + view_damage(view, false); } static void handle_unmap(struct wl_listener *listener, void *data) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 9855c5e15..99b447209 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -79,20 +79,15 @@ void view_close(struct sway_view *view) { } } -void view_damage_whole(struct sway_view *view) { +void view_damage(struct sway_view *view, bool whole) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *cont = root_container.children->items[i]; if (cont->type == C_OUTPUT) { - output_damage_whole_view(cont->sway_output, view); + output_damage_view(cont->sway_output, view, whole); } } } -void view_damage_from(struct sway_view *view) { - // TODO - view_damage_whole(view); -} - static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { struct sway_container *output = container_parent(view->swayc, C_OUTPUT); @@ -191,7 +186,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { arrange_windows(cont->parent, -1, -1); input_manager_set_focus(input_manager, cont); - view_damage_whole(view); + view_damage(view, true); view_handle_container_reparent(&view->container_reparent, NULL); } @@ -202,7 +197,7 @@ void view_unmap(struct sway_view *view) { wl_signal_emit(&view->events.unmap, view); - view_damage_whole(view); + view_damage(view, true); wl_list_remove(&view->surface_new_subsurface.link); wl_list_remove(&view->container_reparent.link); @@ -220,10 +215,10 @@ void view_update_position(struct sway_view *view, double ox, double oy) { return; } - view_damage_whole(view); + view_damage(view, true); view->swayc->x = ox; view->swayc->y = oy; - view_damage_whole(view); + view_damage(view, true); } void view_update_size(struct sway_view *view, int width, int height) { @@ -231,10 +226,10 @@ void view_update_size(struct sway_view *view, int width, int height) { return; } - view_damage_whole(view); + view_damage(view, true); view->width = width; view->height = height; - view_damage_whole(view); + view_damage(view, true); } @@ -253,7 +248,7 @@ static void view_child_handle_surface_commit(struct wl_listener *listener, struct sway_view_child *child = wl_container_of(listener, child, surface_commit); // TODO: only accumulate damage from the child - view_damage_from(child->view); + view_damage(child->view, false); } static void view_child_handle_surface_new_subsurface( @@ -315,12 +310,12 @@ void view_child_init(struct sway_view_child *child, view_init_subsurfaces(child->view, surface); // TODO: only damage the whole child - view_damage_whole(child->view); + view_damage(child->view, true); } void view_child_destroy(struct sway_view_child *child) { // TODO: only damage the whole child - view_damage_whole(child->view); + view_damage(child->view, true); wl_list_remove(&child->surface_commit.link); wl_list_remove(&child->surface_destroy.link); From 603e0e42c577026f1c688c393989e65dc3482808 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 11:49:27 -0400 Subject: [PATCH 472/522] Add debug tree view --- include/sway/debug.h | 7 +++ include/sway/tree/layout.h | 4 +- sway/debug-tree.c | 110 +++++++++++++++++++++++++++++++++++++ sway/desktop/output.c | 5 ++ sway/input/seat.c | 3 + sway/main.c | 6 +- sway/meson.build | 4 ++ sway/tree/layout.c | 8 +++ 8 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 include/sway/debug.h create mode 100644 sway/debug-tree.c diff --git a/include/sway/debug.h b/include/sway/debug.h new file mode 100644 index 000000000..2430d3191 --- /dev/null +++ b/include/sway/debug.h @@ -0,0 +1,7 @@ +#ifndef SWAY_DEBUG_H +#define SWAY_DEBUG_H + +extern bool enable_debug_tree; +void update_debug_tree(); + +#endif diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index fc5ce21f8..49ae00e44 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -1,7 +1,7 @@ #ifndef _SWAY_LAYOUT_H #define _SWAY_LAYOUT_H - #include +#include #include "sway/tree/container.h" enum movement_direction { @@ -29,6 +29,8 @@ struct sway_root { struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link + struct wlr_texture *debug_tree; + struct { struct wl_signal new_container; } events; diff --git a/sway/debug-tree.c b/sway/debug-tree.c new file mode 100644 index 000000000..08ee35858 --- /dev/null +++ b/sway/debug-tree.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include "config.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" +#include "sway/server.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" +#include "cairo.h" +#include "config.h" +#include "pango.h" + +static const char *layout_to_str(enum sway_container_layout layout) { + switch (layout) { + case L_HORIZ: + return "L_HORIZ"; + case L_VERT: + return "L_VERT"; + case L_STACKED: + return "L_STACKED"; + case L_TABBED: + return "L_TABBED"; + case L_FLOATING: + return "L_FLOATING"; + case L_NONE: + default: + return "L_NONE"; + } +} + +static int draw_container(cairo_t *cairo, struct sway_container *container, + struct sway_container *focus, int x, int y) { + int text_width, text_height; + get_text_size(cairo, "monospace", &text_width, &text_height, + 1, false, "%s '%s' %s %dx%d@%d,%d", + container_type_to_str(container->type), container->name, + layout_to_str(container->layout), + container->width, container->height, container->x, container->y); + cairo_rectangle(cairo, x, y, text_width, text_height); + cairo_set_source_u32(cairo, 0xFFFFFFFF); + cairo_fill(cairo); + cairo_move_to(cairo, x, y); + if (focus == container) { + cairo_set_source_u32(cairo, 0xFF0000FF); + } else { + cairo_set_source_u32(cairo, 0x000000FF); + } + pango_printf(cairo, "monospace", 1, false, "%s '%s' %s %dx%d@%d,%d", + container_type_to_str(container->type), container->name, + layout_to_str(container->layout), + container->width, container->height, container->x, container->y); + int height = text_height; + if (container->children) { + for (int i = 0; i < container->children->length; ++i) { + struct sway_container *child = container->children->items[i]; + height += draw_container(cairo, child, focus, x + 10, y + height); + } + } + return height; +} + +bool enable_debug_tree = false; + +void update_debug_tree() { + if (!enable_debug_tree) { + return; + } + + int width = 640, height = 480; + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *container = root_container.children->items[i]; + if (container->width > width) { + width = container->width; + } + if (container->height > height) { + height = container->height; + } + } + cairo_surface_t *surface = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo_t *cairo = cairo_create(surface); + PangoContext *pango = pango_cairo_create_context(cairo); + + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input_manager->seats, link) { + break; + } + + struct sway_container *focus; + if (seat != NULL) { + focus = seat_get_focus(seat); + } + draw_container(cairo, &root_container, focus, 0, 0); + + cairo_surface_flush(surface); + struct wlr_renderer *renderer = wlr_backend_get_renderer(server.backend); + if (root_container.sway_root->debug_tree) { + wlr_texture_destroy(root_container.sway_root->debug_tree); + } + unsigned char *data = cairo_image_surface_get_data(surface); + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); + struct wlr_texture *texture = wlr_texture_from_pixels(renderer, + WL_SHM_FORMAT_ARGB8888, stride, width, height, data); + root_container.sway_root->debug_tree = texture; + cairo_surface_destroy(surface); + g_object_unref(pango); + cairo_destroy(cairo); +} diff --git a/sway/desktop/output.c b/sway/desktop/output.c index aa18f1b8a..ad7777962 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -294,6 +294,11 @@ static void render_output(struct sway_output *output, struct timespec *when, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); renderer_end: + if (root_container.sway_root->debug_tree) { + wlr_render_texture(renderer, root_container.sway_root->debug_tree, + wlr_output->transform_matrix, 0, 0, 1); + } + wlr_renderer_end(renderer); if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { return; diff --git a/sway/input/seat.c b/sway/input/seat.c index ad3584a09..e8cf98245 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -5,6 +5,7 @@ #include #include #include +#include "sway/debug.h" #include "sway/tree/container.h" #include "sway/tree/workspace.h" #include "sway/input/seat.h" @@ -432,6 +433,8 @@ void seat_set_focus_warp(struct sway_seat *seat, } seat->has_focus = (container != NULL); + + update_debug_tree(); } void seat_set_focus(struct sway_seat *seat, diff --git a/sway/main.c b/sway/main.c index e7f8ddd38..efb674b6b 100644 --- a/sway/main.c +++ b/sway/main.c @@ -17,6 +17,7 @@ #endif #include #include "sway/config.h" +#include "sway/debug.h" #include "sway/server.h" #include "sway/tree/layout.h" #include "sway/ipc-server.h" @@ -288,7 +289,7 @@ int main(int argc, char **argv) { int c; while (1) { int option_index = 0; - c = getopt_long(argc, argv, "hCdvVc:", long_options, &option_index); + c = getopt_long(argc, argv, "hCdDvVc:", long_options, &option_index); if (c == -1) { break; } @@ -306,6 +307,9 @@ int main(int argc, char **argv) { case 'd': // debug debug = 1; break; + case 'D': // extended debug options + enable_debug_tree = true; + break; case 'v': // version fprintf(stdout, "sway version " SWAY_VERSION "\n"); exit(EXIT_SUCCESS); diff --git a/sway/meson.build b/sway/meson.build index 29aaa7b71..1fe0f29a0 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -4,6 +4,7 @@ sway_sources = files( 'commands.c', 'config.c', 'criteria.c', + 'debug-tree.c', 'ipc-json.c', 'ipc-server.c', 'security.c', @@ -102,10 +103,13 @@ sway_sources = files( ) sway_deps = [ + cairo, + gdk_pixbuf, jsonc, libcap, libinput, math, + pango, pcre, pixman, server_protos, diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 0011a9e3b..e633acc62 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -6,6 +6,7 @@ #include #include #include +#include "sway/debug.h" #include "sway/tree/container.h" #include "sway/tree/layout.h" #include "sway/output.h" @@ -431,6 +432,11 @@ void container_move(struct sway_container *container, return; } + if (old_parent) { + seat_set_focus(config->handler_context.seat, old_parent); + seat_set_focus(config->handler_context.seat, container); + } + struct sway_container *last_ws = old_parent; struct sway_container *next_ws = container->parent; if (last_ws && last_ws->type != C_WORKSPACE) { @@ -594,6 +600,8 @@ void arrange_windows(struct sway_container *container, break; } container_damage_whole(container); + // TODO: Make this less shitty + update_debug_tree(); } static void apply_horiz_layout(struct sway_container *container, From b5baa78dc3abcbe14199340cdf391497ddc9ca3d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 11:52:23 -0400 Subject: [PATCH 473/522] Address @emersion's comments --- sway/tree/layout.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index e633acc62..1c31b2155 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -103,12 +103,13 @@ static int index_child(const struct sway_container *child) { void container_insert_child(struct sway_container *parent, struct sway_container *child, int i) { - struct sway_container *old_parent = NULL; + struct sway_container *old_parent = child->parent; + if (old_parent) { + container_remove_child(child); + } list_insert(parent->children, i, child); child->parent = parent; - if (old_parent && old_parent != parent) { - wl_signal_emit(&child->events.reparent, old_parent); - } + wl_signal_emit(&child->events.reparent, old_parent); } struct sway_container *container_add_sibling(struct sway_container *fixed, @@ -123,9 +124,7 @@ struct sway_container *container_add_sibling(struct sway_container *fixed, int i = index_child(fixed); list_insert(parent->children, i + 1, active); active->parent = parent; - if (old_parent && old_parent != parent) { - wl_signal_emit(&active->events.reparent, old_parent); - } + wl_signal_emit(&active->events.reparent, old_parent); return active->parent; } @@ -268,6 +267,7 @@ static void workspace_rejigger(struct sway_container *ws, container_flatten(ws); container_reap_empty_recursive(original_parent); + wl_signal_emit(&child->events.reparent, original_parent); arrange_windows(ws, -1, -1); } @@ -287,6 +287,7 @@ void container_move(struct sway_container *container, if (parent != container_flatten(parent)) { // Special case: we were the last one in this container, so flatten it // and leave + update_debug_tree(); return; } @@ -353,7 +354,6 @@ void container_move(struct sway_container *container, "promoting descendant to sibling"); // Special case struct sway_container *old_parent = container->parent; - container_remove_child(container); container_insert_child(current->parent, container, index + (offs < 0 ? 0 : 1)); container->width = container->height = 0; @@ -390,7 +390,6 @@ void container_move(struct sway_container *container, arrange_windows(sibling->parent, -1, -1); } else { wlr_log(L_DEBUG, "Promoting to sibling of cousin"); - container_remove_child(container); container_insert_child(sibling->parent, container, index_child(sibling) + (offs > 0 ? 0 : 1)); container->width = container->height = 0; @@ -404,7 +403,6 @@ void container_move(struct sway_container *container, int limit = container_limit(sibling, move_dir); wlr_log(L_DEBUG, "Reparenting container (paralell)"); limit = limit != 0 ? limit + 1 : limit; // Convert to index - container_remove_child(container); container_insert_child(sibling, container, limit); container->width = container->height = 0; arrange_windows(sibling, -1, -1); From cd6e3182fa55dd8ab3a8a167e854a5446baf39c7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 12:46:33 -0400 Subject: [PATCH 474/522] Fix issues @orestisf1993 raised --- sway/debug-tree.c | 10 ++--- sway/tree/layout.c | 96 +++++++++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/sway/debug-tree.c b/sway/debug-tree.c index 08ee35858..aea6a8b12 100644 --- a/sway/debug-tree.c +++ b/sway/debug-tree.c @@ -34,12 +34,12 @@ static int draw_container(cairo_t *cairo, struct sway_container *container, struct sway_container *focus, int x, int y) { int text_width, text_height; get_text_size(cairo, "monospace", &text_width, &text_height, - 1, false, "%s '%s' %s %dx%d@%d,%d", - container_type_to_str(container->type), container->name, + 1, false, "%s id:%zd '%s' %s %dx%d@%d,%d", + container_type_to_str(container->type), container->id, container->name, layout_to_str(container->layout), container->width, container->height, container->x, container->y); cairo_rectangle(cairo, x, y, text_width, text_height); - cairo_set_source_u32(cairo, 0xFFFFFFFF); + cairo_set_source_u32(cairo, 0xFFFFFFE0); cairo_fill(cairo); cairo_move_to(cairo, x, y); if (focus == container) { @@ -47,8 +47,8 @@ static int draw_container(cairo_t *cairo, struct sway_container *container, } else { cairo_set_source_u32(cairo, 0x000000FF); } - pango_printf(cairo, "monospace", 1, false, "%s '%s' %s %dx%d@%d,%d", - container_type_to_str(container->type), container->name, + pango_printf(cairo, "monospace", 1, false, "%s id:%zd '%s' %s %dx%d@%d,%d", + container_type_to_str(container->type), container->id, container->name, layout_to_str(container->layout), container->width, container->height, container->x, container->y); int height = text_height; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 1c31b2155..a0586f405 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -381,53 +381,61 @@ void container_move(struct sway_container *container, int index = index_child(container); struct sway_container *old_parent = container->parent; - switch (sibling->type) { - case C_VIEW: - if (sibling->parent == container->parent) { - wlr_log(L_DEBUG, "Swapping siblings"); - sibling->parent->children->items[index + offs] = container; - sibling->parent->children->items[index] = sibling; - arrange_windows(sibling->parent, -1, -1); - } else { - wlr_log(L_DEBUG, "Promoting to sibling of cousin"); - container_insert_child(sibling->parent, container, - index_child(sibling) + (offs > 0 ? 0 : 1)); - container->width = container->height = 0; - arrange_windows(sibling->parent, -1, -1); - arrange_windows(old_parent, -1, -1); - } - break; - case C_WORKSPACE: // Note: only in the case of moving between outputs - case C_CONTAINER: - if (is_parallel(sibling->layout, move_dir)) { - int limit = container_limit(sibling, move_dir); - wlr_log(L_DEBUG, "Reparenting container (paralell)"); - limit = limit != 0 ? limit + 1 : limit; // Convert to index - container_insert_child(sibling, container, limit); - container->width = container->height = 0; - arrange_windows(sibling, -1, -1); - arrange_windows(old_parent, -1, -1); - } else { - wlr_log(L_DEBUG, "Reparenting container (perpendicular)"); - container_remove_child(container); - struct sway_container *focus_inactive = seat_get_focus_inactive( - config->handler_context.seat, sibling); - if (focus_inactive) { - container_add_sibling(focus_inactive, container); - } else if (sibling->children->length) { - container_add_sibling(sibling->children->items[0], container); + while (sibling) { + switch (sibling->type) { + case C_VIEW: + if (sibling->parent == container->parent) { + wlr_log(L_DEBUG, "Swapping siblings"); + sibling->parent->children->items[index + offs] = container; + sibling->parent->children->items[index] = sibling; + arrange_windows(sibling->parent, -1, -1); } else { - container_add_child(sibling, container); + wlr_log(L_DEBUG, "Promoting to sibling of cousin"); + container_insert_child(sibling->parent, container, + index_child(sibling) + (offs > 0 ? 0 : 1)); + container->width = container->height = 0; + arrange_windows(sibling->parent, -1, -1); + arrange_windows(old_parent, -1, -1); } - container->width = container->height = 0; - arrange_windows(sibling, -1, -1); - arrange_windows(old_parent, -1, -1); + sibling = NULL; + break; + case C_WORKSPACE: // Note: only in the case of moving between outputs + case C_CONTAINER: + if (is_parallel(sibling->layout, move_dir)) { + int limit = container_limit(sibling, move_dir); + wlr_log(L_DEBUG, "Reparenting container (paralell)"); + limit = limit != 0 ? limit + 1 : limit; // Convert to index + container_insert_child(sibling, container, limit); + container->width = container->height = 0; + arrange_windows(sibling, -1, -1); + arrange_windows(old_parent, -1, -1); + sibling = NULL; + } else { + wlr_log(L_DEBUG, "Reparenting container (perpendicular)"); + container_remove_child(container); + struct sway_container *focus_inactive = seat_get_focus_inactive( + config->handler_context.seat, sibling); + wlr_log(L_DEBUG, "Focus inactive: %zd", focus_inactive ? + focus_inactive->id : 0); + if (focus_inactive) { + sibling = focus_inactive; + continue; + } else if (sibling->children->length) { + container_add_sibling(sibling->children->items[0], container); + } else { + container_add_child(sibling, container); + } + container->width = container->height = 0; + arrange_windows(sibling, -1, -1); + arrange_windows(old_parent, -1, -1); + sibling = NULL; + } + break; + default: + sway_assert(0, "Not expecting to see container of type %s here", + container_type_to_str(sibling->type)); + return; } - break; - default: - sway_assert(0, "Not expecting to see container of type %s here", - container_type_to_str(sibling->type)); - return; } if (old_parent) { From 1f70b94f34813ee997a175e943dabbfec96648a6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 13:17:22 -0400 Subject: [PATCH 475/522] Fix moving into right end of container --- sway/tree/layout.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index a0586f405..f4049c712 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -107,6 +107,7 @@ void container_insert_child(struct sway_container *parent, if (old_parent) { container_remove_child(child); } + wlr_log(L_DEBUG, "Inserting id:%zd at index %d", child->id, i); list_insert(parent->children, i, child); child->parent = parent; wl_signal_emit(&child->events.reparent, old_parent); @@ -229,23 +230,24 @@ static enum movement_direction invert_movement(enum movement_direction dir) { case MOVE_UP: return MOVE_DOWN; case MOVE_DOWN: - return MOVE_LEFT; + return MOVE_UP; default: sway_assert(0, "This function expects left|right|up|down"); return MOVE_LEFT; } } +static int move_offs(enum movement_direction move_dir) { + return move_dir == MOVE_LEFT || move_dir == MOVE_UP ? -1 : 1; +} + /* Gets the index of the most extreme member based on the movement offset */ -static int container_limit(struct sway_container *container, int offs) { +static int container_limit(struct sway_container *container, + enum movement_direction move_dir) { if (container->children->length == 0) { return 0; } - return offs < 0 ? 0 : container->children->length - 1; -} - -static int move_offs(enum movement_direction move_dir) { - return move_dir == MOVE_LEFT || move_dir == MOVE_UP ? -1 : 1; + return move_offs(move_dir) < 0 ? 0 : container->children->length - 1; } static void workspace_rejigger(struct sway_container *ws, @@ -301,7 +303,7 @@ void container_move(struct sway_container *container, container_type_to_str(current->type), current->name); int index = index_child(current); - int limit = container_limit(parent, offs); + int limit = container_limit(parent, move_dir); switch (current->type) { case C_OUTPUT: { @@ -402,9 +404,11 @@ void container_move(struct sway_container *container, case C_WORKSPACE: // Note: only in the case of moving between outputs case C_CONTAINER: if (is_parallel(sibling->layout, move_dir)) { - int limit = container_limit(sibling, move_dir); - wlr_log(L_DEBUG, "Reparenting container (paralell)"); + int limit = container_limit(sibling, invert_movement(move_dir)); limit = limit != 0 ? limit + 1 : limit; // Convert to index + wlr_log(L_DEBUG, + "Reparenting container (parallel) to index %d " + "(move dir: %d)", limit, move_dir); container_insert_child(sibling, container, limit); container->width = container->height = 0; arrange_windows(sibling, -1, -1); @@ -421,8 +425,10 @@ void container_move(struct sway_container *container, sibling = focus_inactive; continue; } else if (sibling->children->length) { + wlr_log(L_DEBUG, "No focus-inactive, adding arbitrarily"); container_add_sibling(sibling->children->items[0], container); } else { + wlr_log(L_DEBUG, "No kiddos, adding container alone"); container_add_child(sibling, container); } container->width = container->height = 0; From e550e22c0b6e2192f2750a6e13356980426d26ba Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 6 Apr 2018 13:27:01 -0400 Subject: [PATCH 476/522] Refactor rendering code --- sway/desktop/output.c | 348 ++++++++++++++++++++---------------------- 1 file changed, 167 insertions(+), 181 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 3bbd0bb2c..90ec3c77e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -38,191 +38,201 @@ struct sway_container *output_by_name(const char *name) { */ static void rotate_child_position(double *sx, double *sy, double sw, double sh, double pw, double ph, float rotation) { - if (rotation != 0.0) { - // Coordinates relative to the center of the subsurface - double ox = *sx - pw/2 + sw/2, - oy = *sy - ph/2 + sh/2; - // Rotated coordinates - double rx = cos(-rotation)*ox - sin(-rotation)*oy, - ry = cos(-rotation)*oy + sin(-rotation)*ox; - *sx = rx + pw/2 - sw/2; - *sy = ry + ph/2 - sh/2; + if (rotation == 0.0f) { + return; } + + // Coordinates relative to the center of the subsurface + double ox = *sx - pw/2 + sw/2, + oy = *sy - ph/2 + sh/2; + // Rotated coordinates + double rx = cos(-rotation)*ox - sin(-rotation)*oy, + ry = cos(-rotation)*oy + sin(-rotation)*ox; + *sx = rx + pw/2 - sw/2; + *sy = ry + ph/2 - sh/2; } /** - * Checks whether a surface at (lx, ly) intersects an output. If `box` is not - * NULL, it populates it with the surface box in the output, in output-local - * coordinates. + * Contains a surface's root geometry information. For instance, when rendering + * a popup, this will contain the parent view's position and size. */ -static bool surface_intersect_output(struct wlr_surface *surface, - struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, - double ox, double oy, float rotation, struct wlr_box *box) { - if (box != NULL) { - box->x = ox * wlr_output->scale; - box->y = oy * wlr_output->scale; - box->width = surface->current->width * wlr_output->scale; - box->height = surface->current->height * wlr_output->scale; +struct root_geometry { + double x, y; + int width, height; + float rotation; +}; + +static bool get_surface_box(struct root_geometry *geo, + struct sway_output *output, struct wlr_surface *surface, int sx, int sy, + struct wlr_box *surface_box) { + int sw = surface->current->width; + int sh = surface->current->height; + + double _sx = sx, _sy = sy; + rotate_child_position(&_sx, &_sy, sw, sh, geo->width, geo->height, + geo->rotation); + + struct wlr_box box = { + .x = geo->x + _sx, + .y = geo->y + _sy, + .width = sw, + .height = sh, + }; + if (surface_box != NULL) { + memcpy(surface_box, &box, sizeof(struct wlr_box)); } - struct wlr_box layout_box = { - .x = wlr_output->lx + ox, .y = wlr_output->ly + oy, - .width = surface->current->width, .height = surface->current->height, + struct wlr_box rotated_box; + wlr_box_rotated_bounds(&box, geo->rotation, &rotated_box); + + struct wlr_box output_box = { + .width = output->swayc->width, + .height = output->swayc->height, }; - wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); - return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); + + struct wlr_box intersection; + return wlr_box_intersection(&output_box, &rotated_box, &intersection); } -static void render_surface(struct wlr_surface *surface, - struct wlr_output *wlr_output, struct timespec *when, - double ox, double oy, float rotation, float alpha) { - struct wlr_renderer *renderer = - wlr_backend_get_renderer(wlr_output->backend); +static void output_surface_for_each_surface(struct wlr_surface *surface, + double ox, double oy, float rotation, struct root_geometry *geo, + wlr_surface_iterator_func_t iterator, void *user_data) { + geo->x = ox; + geo->y = oy; + geo->width = surface->current->width; + geo->height = surface->current->height; + geo->rotation = rotation; + + wlr_surface_for_each_surface(surface, iterator, user_data); +} + +static void output_view_for_each_surface(struct sway_view *view, + struct root_geometry *geo, wlr_surface_iterator_func_t iterator, + void *user_data) { + geo->x = view->swayc->x; + geo->y = view->swayc->y; + geo->width = view->surface->current->width; + geo->height = view->surface->current->height; + geo->rotation = 0; // TODO + + view_for_each_surface(view, iterator, user_data); +} + +static void scale_box(struct wlr_box *box, float scale) { + box->x *= scale; + box->y *= scale; + box->width *= scale; + box->height *= scale; +} + +struct render_data { + struct root_geometry root_geo; + struct sway_output *output; + struct timespec *when; + float alpha; +}; + +static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, + void *_data) { + struct render_data *data = _data; + struct wlr_output *wlr_output = data->output->wlr_output; + struct timespec *when = data->when; + float rotation = data->root_geo.rotation; + float alpha = data->alpha; if (!wlr_surface_has_buffer(surface)) { return; } - struct wlr_output_layout *layout = root_container.sway_root->output_layout; - struct wlr_box box; - bool intersects = surface_intersect_output(surface, layout, wlr_output, - ox, oy, rotation, &box); - if (intersects) { - float matrix[9]; - enum wl_output_transform transform = - wlr_output_transform_invert(surface->current->transform); - wlr_matrix_project_box(matrix, &box, transform, rotation, - wlr_output->transform_matrix); - - wlr_render_texture_with_matrix(renderer, surface->texture, - matrix, alpha); - - wlr_surface_send_frame_done(surface, when); + bool intersects = get_surface_box(&data->root_geo, data->output, surface, + sx, sy, &box); + if (!intersects) { + return; } - struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { - struct wlr_surface_state *state = subsurface->surface->current; - double sx = state->subsurface_position.x; - double sy = state->subsurface_position.y; - rotate_child_position(&sx, &sy, state->width, state->height, - surface->current->width, surface->current->height, rotation); + struct wlr_renderer *renderer = + wlr_backend_get_renderer(wlr_output->backend); + if (!sway_assert(renderer != NULL, + "expected the output backend to have a renderer")) { + return; + } - render_surface(subsurface->surface, wlr_output, when, - ox + sx, oy + sy, rotation, alpha); + scale_box(&box, wlr_output->scale); + + float matrix[9]; + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current->transform); + wlr_matrix_project_box(matrix, &box, transform, rotation, + wlr_output->transform_matrix); + + wlr_render_texture_with_matrix(renderer, surface->texture, + matrix, alpha); + + // TODO: don't send the frame done event now + wlr_surface_send_frame_done(surface, when); +} + +static void render_surface(struct sway_output *output, struct timespec *when, + struct wlr_surface *surface, double ox, double oy, float rotation) { + struct render_data data = { + .output = output, + .when = when, + .alpha = 1.0f, + }; + + output_surface_for_each_surface(surface, ox, oy, rotation, &data.root_geo, + render_surface_iterator, &data); +} + +static void render_view(struct sway_output *output, struct timespec *when, + struct sway_view *view) { + struct render_data data = { + .output = output, + .when = when, + .alpha = view->swayc->alpha, + }; + + output_view_for_each_surface(view, &data.root_geo, + render_surface_iterator, &data); +} + +static void render_layer(struct sway_output *output, struct timespec *when, + struct wl_list *layer_surfaces) { + struct sway_layer_surface *layer_surface; + wl_list_for_each(layer_surface, layer_surfaces, link) { + struct wlr_layer_surface *wlr_layer_surface = + layer_surface->layer_surface; + render_surface(output, when, wlr_layer_surface->surface, + layer_surface->geo.x, layer_surface->geo.y, 0); } } -static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, - struct wlr_output *wlr_output, struct timespec *when, double base_x, - double base_y, float rotation, float alpha) { - double width = surface->surface->current->width; - double height = surface->surface->current->height; - - struct wlr_xdg_popup_v6 *popup_state; - wl_list_for_each(popup_state, &surface->popups, link) { - struct wlr_xdg_surface_v6 *popup = popup_state->base; - if (!popup->configured) { - continue; - } - - double popup_width = popup->surface->current->width; - double popup_height = popup->surface->current->height; - - double popup_sx, popup_sy; - wlr_xdg_surface_v6_popup_get_position(popup, &popup_sx, &popup_sy); - rotate_child_position(&popup_sx, &popup_sy, popup_width, popup_height, - width, height, rotation); - - render_surface(popup->surface, wlr_output, when, - base_x + popup_sx, base_y + popup_sy, rotation, alpha); - render_xdg_v6_popups(popup, wlr_output, when, - base_x + popup_sx, base_y + popup_sy, rotation, alpha); - } -} - -static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, - struct wlr_output *wlr_output, struct timespec *when, - double lx, double ly, float rotation, float alpha, - bool is_child) { - if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) { - render_surface(surface->surface, wlr_output, when, - lx, ly, rotation, alpha); - - double width = surface->surface->current->width; - double height = surface->surface->current->height; - - struct wlr_wl_shell_surface *popup; - wl_list_for_each(popup, &surface->popups, popup_link) { - double popup_width = popup->surface->current->width; - double popup_height = popup->surface->current->height; - - double popup_x = popup->transient_state->x; - double popup_y = popup->transient_state->y; - rotate_child_position(&popup_x, &popup_y, popup_width, popup_height, - width, height, rotation); - - render_wl_shell_surface(popup, wlr_output, when, - lx + popup_x, ly + popup_y, rotation, alpha, true); - } - } -} - -struct render_data { +struct render_view_data { struct sway_output *output; struct timespec *when; }; -static void render_view(struct sway_container *view, void *data) { - struct render_data *rdata = data; - struct sway_output *output = rdata->output; - struct timespec *when = rdata->when; - struct wlr_output *wlr_output = output->wlr_output; - struct sway_view *sway_view = view->sway_view; - struct wlr_surface *surface = sway_view->surface; - float alpha = sway_view->swayc->alpha; +static void render_view_iterator(struct sway_container *con, void *_data) { + struct render_view_data *data = _data; - if (!surface) { + if (!sway_assert(con->type == C_VIEW, "expected a view")) { return; } - switch (sway_view->type) { - case SWAY_VIEW_XDG_SHELL_V6: { - int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; - int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; - render_surface(surface, wlr_output, when, - view->x - window_offset_x, view->y - window_offset_y, 0, alpha); - render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, - when, view->x - window_offset_x, view->y - window_offset_y, 0, alpha); - break; - } - case SWAY_VIEW_WL_SHELL: - render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, - when, view->x, view->y, 0, alpha, false); - break; - case SWAY_VIEW_XWAYLAND: - render_surface(surface, wlr_output, when, view->x, view->y, 0, alpha); - break; - } -} - -static void render_layer(struct sway_output *output, struct timespec *when, - struct wl_list *layer) { - struct sway_layer_surface *sway_layer; - wl_list_for_each(sway_layer, layer, link) { - struct wlr_layer_surface *layer = sway_layer->layer_surface; - render_surface(layer->surface, output->wlr_output, when, - sway_layer->geo.x, sway_layer->geo.y, 0, 1.0f); - wlr_surface_send_frame_done(layer->surface, when); - } + render_view(data->output, data->when, con->sway_view); } static void render_output(struct sway_output *output, struct timespec *when, pixman_region32_t *damage) { struct wlr_output *wlr_output = output->wlr_output; + struct wlr_renderer *renderer = - wlr_backend_get_renderer(wlr_output->backend); + wlr_backend_get_renderer(wlr_output->backend); + if (!sway_assert(renderer != NULL, + "expected the output backend to have a renderer")) { + return; + } wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); @@ -231,24 +241,15 @@ static void render_output(struct sway_output *output, struct timespec *when, goto renderer_end; } - // TODO: don't damage the whole output here - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - pixman_region32_union_rect(damage, damage, 0, 0, width, height); - float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; wlr_renderer_clear(renderer, clear_color); - struct wlr_output_layout *output_layout = - root_container.sway_root->output_layout; - const struct wlr_box *output_box = - wlr_output_layout_get_box(output_layout, wlr_output); - render_layer(output, when, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); render_layer(output, when, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + // Render all views in the current workspace struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *focus = seat_get_focus_inactive(seat, output->swayc); @@ -258,36 +259,21 @@ static void render_output(struct sway_output *output, struct timespec *when, } struct sway_container *workspace = focus->type == C_WORKSPACE ? focus : container_parent(focus, C_WORKSPACE); + struct render_view_data data = { .output = output, .when = when }; + container_descendants(workspace, C_VIEW, render_view_iterator, &data); - struct render_data rdata = { - .output = output, - .when = when, - }; - container_descendants(workspace, C_VIEW, render_view, &rdata); - - // render unmanaged views on top + // Render unmanaged views on top struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; struct sway_xwayland_unmanaged *unmanaged_surface; wl_list_for_each(unmanaged_surface, unmanaged, link) { struct wlr_xwayland_surface *xsurface = unmanaged_surface->wlr_xwayland_surface; - - const struct wlr_box view_box = { - .x = unmanaged_surface->lx, - .y = unmanaged_surface->ly, - .width = xsurface->width, - .height = xsurface->height, - }; - struct wlr_box intersection; - if (!wlr_box_intersection(&view_box, output_box, &intersection)) { - continue; - } - - render_surface(xsurface->surface, wlr_output, &output->last_frame, - view_box.x - output_box->x, view_box.y - output_box->y, 0, 1.0f); + double ox = unmanaged_surface->lx - output->swayc->x; + double oy = unmanaged_surface->ly - output->swayc->y; + render_surface(output, when, xsurface->surface, ox, oy, 0); } - // TODO: Consider revising this when fullscreen windows are supported + // TODO: consider revising this when fullscreen windows are supported render_layer(output, when, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); render_layer(output, when, From c8be7bfc1e0c65730a5bf713e61105cd38bf9f4f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 13:57:04 -0400 Subject: [PATCH 477/522] Fix another of @orestisf1993's issues --- sway/debug-tree.c | 19 +++++++++++-------- sway/tree/layout.c | 9 ++++++--- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/sway/debug-tree.c b/sway/debug-tree.c index aea6a8b12..00501d9c1 100644 --- a/sway/debug-tree.c +++ b/sway/debug-tree.c @@ -38,9 +38,19 @@ static int draw_container(cairo_t *cairo, struct sway_container *container, container_type_to_str(container->type), container->id, container->name, layout_to_str(container->layout), container->width, container->height, container->x, container->y); - cairo_rectangle(cairo, x, y, text_width, text_height); + cairo_rectangle(cairo, x + 2, y, text_width - 2, text_height); cairo_set_source_u32(cairo, 0xFFFFFFE0); cairo_fill(cairo); + int height = text_height; + if (container->children) { + for (int i = 0; i < container->children->length; ++i) { + struct sway_container *child = container->children->items[i]; + height += draw_container(cairo, child, focus, x + 10, y + height); + } + } + cairo_set_source_u32(cairo, 0xFFFFFFE0); + cairo_rectangle(cairo, x, y, 2, height); + cairo_fill(cairo); cairo_move_to(cairo, x, y); if (focus == container) { cairo_set_source_u32(cairo, 0xFF0000FF); @@ -51,13 +61,6 @@ static int draw_container(cairo_t *cairo, struct sway_container *container, container_type_to_str(container->type), container->id, container->name, layout_to_str(container->layout), container->width, container->height, container->x, container->y); - int height = text_height; - if (container->children) { - for (int i = 0; i < container->children->length; ++i) { - struct sway_container *child = container->children->items[i]; - height += draw_container(cairo, child, focus, x + 10, y + height); - } - } return height; } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index f4049c712..b03b80d94 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -364,8 +364,8 @@ void container_move(struct sway_container *container, return; } } else { - wlr_log(L_DEBUG, "Selecting sibling"); sibling = parent->children->items[index + offs]; + wlr_log(L_DEBUG, "Selecting sibling id:%zd", sibling->id); } } else { wlr_log(L_DEBUG, "Moving up to find a parallel container"); @@ -419,9 +419,12 @@ void container_move(struct sway_container *container, container_remove_child(container); struct sway_container *focus_inactive = seat_get_focus_inactive( config->handler_context.seat, sibling); - wlr_log(L_DEBUG, "Focus inactive: %zd", focus_inactive ? - focus_inactive->id : 0); if (focus_inactive) { + while (focus_inactive->parent != sibling) { + focus_inactive = focus_inactive->parent; + } + wlr_log(L_DEBUG, "Focus inactive: id:%zd", + focus_inactive->id); sibling = focus_inactive; continue; } else if (sibling->children->length) { From 58914822aa70d69a61794c52aa2113dbe7fcc7af Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 6 Apr 2018 14:17:58 -0400 Subject: [PATCH 478/522] Don't damage the whole output --- sway/desktop/output.c | 103 +++++++++++++++++++++++++++++++----- sway/desktop/xdg_shell_v6.c | 24 +++++---- 2 files changed, 104 insertions(+), 23 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 90ec3c77e..0f25cff18 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -1,8 +1,8 @@ #define _POSIX_C_SOURCE 200809L #include #include -#include #include +#include #include #include #include @@ -12,6 +12,7 @@ #include #include #include +#include #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -95,13 +96,13 @@ static bool get_surface_box(struct root_geometry *geo, } static void output_surface_for_each_surface(struct wlr_surface *surface, - double ox, double oy, float rotation, struct root_geometry *geo, + double ox, double oy, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { geo->x = ox; geo->y = oy; geo->width = surface->current->width; geo->height = surface->current->height; - geo->rotation = rotation; + geo->rotation = 0; wlr_surface_for_each_surface(surface, iterator, user_data); } @@ -174,14 +175,14 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, } static void render_surface(struct sway_output *output, struct timespec *when, - struct wlr_surface *surface, double ox, double oy, float rotation) { + struct wlr_surface *surface, double ox, double oy) { struct render_data data = { .output = output, .when = when, .alpha = 1.0f, }; - output_surface_for_each_surface(surface, ox, oy, rotation, &data.root_geo, + output_surface_for_each_surface(surface, ox, oy, &data.root_geo, render_surface_iterator, &data); } @@ -204,7 +205,7 @@ static void render_layer(struct sway_output *output, struct timespec *when, struct wlr_layer_surface *wlr_layer_surface = layer_surface->layer_surface; render_surface(output, when, wlr_layer_surface->surface, - layer_surface->geo.x, layer_surface->geo.y, 0); + layer_surface->geo.x, layer_surface->geo.y); } } @@ -241,6 +242,11 @@ static void render_output(struct sway_output *output, struct timespec *when, goto renderer_end; } + // TODO: don't damage the whole output + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + pixman_region32_union_rect(damage, damage, 0, 0, width, height); + float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; wlr_renderer_clear(renderer, clear_color); @@ -270,7 +276,7 @@ static void render_output(struct sway_output *output, struct timespec *when, unmanaged_surface->wlr_xwayland_surface; double ox = unmanaged_surface->lx - output->swayc->x; double oy = unmanaged_surface->ly - output->swayc->y; - render_surface(output, when, xsurface->surface, ox, oy, 0); + render_surface(output, when, xsurface->surface, ox, oy); } // TODO: consider revising this when fullscreen windows are supported @@ -318,22 +324,93 @@ void output_damage_whole(struct sway_output *output) { wlr_output_damage_add_whole(output->damage); } +struct damage_data { + struct root_geometry root_geo; + struct sway_output *output; + bool whole; +}; + +static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, + void *_data) { + struct damage_data *data = _data; + struct sway_output *output = data->output; + float rotation = data->root_geo.rotation; + bool whole = data->whole; + + if (!wlr_surface_has_buffer(surface)) { + return; + } + + struct wlr_box box; + bool intersects = get_surface_box(&data->root_geo, data->output, surface, + sx, sy, &box); + if (!intersects) { + return; + } + + scale_box(&box, output->wlr_output->scale); + + if (whole) { + wlr_box_rotated_bounds(&box, rotation, &box); + wlr_output_damage_add_box(output->damage, &box); + } else { + int center_x = box.x + box.width/2; + int center_y = box.y + box.height/2; + + pixman_region32_t damage; + pixman_region32_init(&damage); + pixman_region32_copy(&damage, &surface->current->surface_damage); + wlr_region_scale(&damage, &damage, output->wlr_output->scale); + if (ceil(output->wlr_output->scale) > surface->current->scale) { + // When scaling up a surface, it'll become blurry so we need to + // expand the damage region + wlr_region_expand(&damage, &damage, + ceil(output->wlr_output->scale) - surface->current->scale); + } + pixman_region32_translate(&damage, box.x, box.y); + wlr_region_rotated_bounds(&damage, &damage, rotation, + center_x, center_y); + wlr_output_damage_add(output->damage, &damage); + pixman_region32_fini(&damage); + } +} + void output_damage_surface(struct sway_output *output, double ox, double oy, struct wlr_surface *surface, bool whole) { - // TODO - output_damage_whole(output); + struct damage_data data = { + .output = output, + .whole = whole, + }; + + output_surface_for_each_surface(surface, ox, oy, &data.root_geo, + damage_surface_iterator, &data); } void output_damage_view(struct sway_output *output, struct sway_view *view, bool whole) { - // TODO - output_damage_whole(output); + if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { + return; + } + + struct damage_data data = { + .output = output, + .whole = whole, + }; + + output_view_for_each_surface(view, &data.root_geo, + damage_surface_iterator, &data); } void output_damage_whole_container(struct sway_output *output, struct sway_container *con) { - // TODO - output_damage_whole(output); + float scale = output->wlr_output->scale; + struct wlr_box box = { + .x = con->x * scale, + .y = con->y * scale, + .width = con->width * scale, + .height = con->height * scale, + }; + wlr_output_damage_add_box(output->damage, &box); } static void damage_handle_destroy(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index b82eec8fb..e4703040c 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -143,9 +143,7 @@ static void destroy(struct sway_view *view) { if (xdg_shell_v6_view == NULL) { return; } - wl_list_remove(&xdg_shell_v6_view->commit.link); wl_list_remove(&xdg_shell_v6_view->destroy.link); - wl_list_remove(&xdg_shell_v6_view->new_popup.link); wl_list_remove(&xdg_shell_v6_view->map.link); wl_list_remove(&xdg_shell_v6_view->unmap.link); free(xdg_shell_v6_view); @@ -182,14 +180,28 @@ static void handle_new_popup(struct wl_listener *listener, void *data) { static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, unmap); + view_unmap(&xdg_shell_v6_view->view); + + wl_list_remove(&xdg_shell_v6_view->commit.link); + wl_list_remove(&xdg_shell_v6_view->new_popup.link); } static void handle_map(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, map); struct sway_view *view = &xdg_shell_v6_view->view; + struct wlr_xdg_surface_v6 *xdg_surface = view->wlr_xdg_surface_v6; + view_map(view, view->wlr_xdg_surface_v6->surface); + + xdg_shell_v6_view->commit.notify = handle_commit; + wl_signal_add(&xdg_surface->surface->events.commit, + &xdg_shell_v6_view->commit); + + xdg_shell_v6_view->new_popup.notify = handle_new_popup; + wl_signal_add(&xdg_surface->events.new_popup, + &xdg_shell_v6_view->new_popup); } static void handle_destroy(struct wl_listener *listener, void *data) { @@ -226,14 +238,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { // - Look up pid and open on appropriate workspace // - Criteria - xdg_shell_v6_view->commit.notify = handle_commit; - wl_signal_add(&xdg_surface->surface->events.commit, - &xdg_shell_v6_view->commit); - - xdg_shell_v6_view->new_popup.notify = handle_new_popup; - wl_signal_add(&xdg_surface->events.new_popup, - &xdg_shell_v6_view->new_popup); - xdg_shell_v6_view->map.notify = handle_map; wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map); From 5ff16994c57375c9b0b842a2f63e7d15984aeadd Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 15:09:52 -0400 Subject: [PATCH 479/522] Address @emersion feedback --- sway/debug-tree.c | 2 +- sway/tree/layout.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sway/debug-tree.c b/sway/debug-tree.c index 00501d9c1..07c48a257 100644 --- a/sway/debug-tree.c +++ b/sway/debug-tree.c @@ -91,7 +91,7 @@ void update_debug_tree() { break; } - struct sway_container *focus; + struct sway_container *focus = NULL; if (seat != NULL) { focus = seat_get_focus(seat); } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index b03b80d94..7296423bf 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -250,6 +250,9 @@ static int container_limit(struct sway_container *container, return move_offs(move_dir) < 0 ? 0 : container->children->length - 1; } +/* Takes one child, sets it aside, wraps the rest of the children in a new + * container, switches the layout of the workspace, and drops the child back in. + * In other words, rejigger it. */ static void workspace_rejigger(struct sway_container *ws, struct sway_container *child, enum movement_direction move_dir) { struct sway_container *original_parent = child->parent; @@ -311,8 +314,8 @@ void container_move(struct sway_container *container, sway_dir_to_wlr(move_dir, &wlr_dir); double ref_x = current->x + current->width / 2; double ref_y = current->y + current->height / 2; - ref_x += current->sway_output->wlr_output->lx; - ref_y += current->sway_output->wlr_output->ly; + ref_x += current->sway_output->swayc->x; + ref_y += current->sway_output->swayc->y; struct wlr_output *next = wlr_output_layout_adjacent_output( root_container.sway_root->output_layout, wlr_dir, current->sway_output->wlr_output, From 9109b1fd119c6fbe1c4b5de3b97d948b86f81ce0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 15:37:55 -0400 Subject: [PATCH 480/522] Fix moving to parallel container on another output --- sway/tree/layout.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 7296423bf..a3bee883b 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -244,10 +244,7 @@ static int move_offs(enum movement_direction move_dir) { /* Gets the index of the most extreme member based on the movement offset */ static int container_limit(struct sway_container *container, enum movement_direction move_dir) { - if (container->children->length == 0) { - return 0; - } - return move_offs(move_dir) < 0 ? 0 : container->children->length - 1; + return move_offs(move_dir) < 0 ? 0 : container->children->length; } /* Takes one child, sets it aside, wraps the rest of the children in a new @@ -306,7 +303,6 @@ void container_move(struct sway_container *container, container_type_to_str(current->type), current->name); int index = index_child(current); - int limit = container_limit(parent, move_dir); switch (current->type) { case C_OUTPUT: { @@ -350,7 +346,8 @@ void container_move(struct sway_container *container, case C_CONTAINER: case C_VIEW: if (is_parallel(parent->layout, move_dir)) { - if (index == limit) { + if ((index == parent->children->length - 1 && offs > 0) + || (index == 0 && offs < 0)) { if (current->parent == container->parent) { wlr_log(L_DEBUG, "Hit limit, selecting parent"); current = current->parent; @@ -408,7 +405,7 @@ void container_move(struct sway_container *container, case C_CONTAINER: if (is_parallel(sibling->layout, move_dir)) { int limit = container_limit(sibling, invert_movement(move_dir)); - limit = limit != 0 ? limit + 1 : limit; // Convert to index + wlr_log(L_DEBUG, "limit: %d", limit); wlr_log(L_DEBUG, "Reparenting container (parallel) to index %d " "(move dir: %d)", limit, move_dir); From 764489e73760534d49760af123cae46109564e86 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 15:03:05 -0400 Subject: [PATCH 481/522] Break everything^W^WUse wlr_box for sway_container --- include/sway/tree/container.h | 10 +- include/sway/tree/layout.h | 3 +- sway/commands/layout.c | 2 +- sway/commands/move.c | 7 +- sway/commands/resize.c | 8 +- sway/desktop/desktop.c | 2 +- sway/desktop/output.c | 15 ++- sway/input/seat.c | 4 +- sway/ipc-json.c | 8 +- sway/tree/container.c | 8 +- sway/tree/layout.c | 204 +++++++++++++++++----------------- sway/tree/view.c | 10 +- sway/tree/workspace.c | 8 +- 13 files changed, 144 insertions(+), 145 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 4c60530fa..e7a071bea 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -68,12 +68,10 @@ struct sway_container { enum sway_container_layout prev_layout; enum sway_container_layout workspace_layout; - // For C_ROOT, this has no meaning - // For C_OUTPUT, this is the output position in layout coordinates - // For other types, this is the position in output-local coordinates - double x, y; - // does not include borders or gaps. - double width, height; + // For C_ROOT, this is the extents of the whole layout box. + // For C_OUTPUT, this is the output position in layout coordinates. + // For other types, this is the position in output-local coordinates. + struct wlr_box box; list_t *children; diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index fc5ce21f8..b2b98ee44 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -61,8 +61,7 @@ enum sway_container_layout container_get_default_layout( void container_sort_workspaces(struct sway_container *output); -void arrange_windows(struct sway_container *container, - double width, double height); +void arrange_windows(struct sway_container *container, int width, int height); struct sway_container *container_get_in_direction(struct sway_container *container, struct sway_seat *seat, enum movement_direction dir); diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 4c49a627f..162173c53 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -49,7 +49,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } } - arrange_windows(parent, parent->width, parent->height); + arrange_windows(parent, parent->box.width, parent->box.height); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/move.c b/sway/commands/move.c index c954ab94e..e8668ce76 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -95,7 +95,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, } struct sway_container *source = container_parent(current, C_OUTPUT); struct sway_container *destination = output_in_direction(argv[3], - source->sway_output->wlr_output, current->x, current->y); + source->sway_output->wlr_output, + current->box.x, current->box.y); if (!destination) { return cmd_results_new(CMD_FAILURE, "move workspace", "Can't find output with name/direction '%s'", argv[3]); @@ -124,8 +125,8 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current, return cmd_results_new(CMD_INVALID, "move", expected_syntax); } struct sway_container *source = container_parent(current, C_OUTPUT); - int center_x = current->width / 2 + current->x, - center_y = current->height / 2 + current->y; + int center_x = current->box.width / 2 + current->box.x, + center_y = current->box.height / 2 + current->box.y; struct sway_container *destination = output_in_direction(argv[3], source->sway_output->wlr_output, center_x, center_y); if (!destination) { diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 93c1fe7de..8e295f655 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -48,11 +48,11 @@ static enum resize_axis parse_resize_axis(const char *axis) { } static int parallel_coord(struct sway_container *c, enum resize_axis a) { - return a == RESIZE_AXIS_HORIZONTAL ? c->x : c->y; + return a == RESIZE_AXIS_HORIZONTAL ? c->box.x : c->box.y; } static int parallel_size(struct sway_container *c, enum resize_axis a) { - return a == RESIZE_AXIS_HORIZONTAL ? c->width : c->height; + return a == RESIZE_AXIS_HORIZONTAL ? c->box.width : c->box.height; } static void resize_tiled(int amount, enum resize_axis axis) { @@ -196,10 +196,10 @@ static void resize(int amount, enum resize_axis axis, enum resize_unit unit) { float pct = amount / 100.0f; switch (axis) { case RESIZE_AXIS_HORIZONTAL: - amount = (float)current->width * pct; + amount = (float)current->box.width * pct; break; case RESIZE_AXIS_VERTICAL: - amount = (float)current->height * pct; + amount = (float)current->box.height * pct; break; default: sway_assert(0, "invalid resize axis"); diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index 3a13191f2..f0a14445f 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c @@ -8,7 +8,7 @@ void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, struct sway_container *cont = root_container.children->items[i]; if (cont->type == C_OUTPUT) { output_damage_whole_surface(cont->sway_output, - lx - cont->x, ly - cont->y, surface); + lx - cont->box.x, ly - cont->box.y, surface); } } } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index aa18f1b8a..49ffe74c8 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -192,17 +192,22 @@ static void render_view(struct sway_container *view, void *data) { int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; render_surface(surface, wlr_output, when, - view->x - window_offset_x, view->y - window_offset_y, 0, alpha); - render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, - when, view->x - window_offset_x, view->y - window_offset_y, 0, alpha); + view->box.x - window_offset_x, + view->box.y - window_offset_y, + 0, alpha); + render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, when, + view->box.x - window_offset_x, + view->box.y - window_offset_y, + 0, alpha); break; } case SWAY_VIEW_WL_SHELL: render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, - when, view->x, view->y, 0, alpha, false); + when, view->box.x, view->box.y, 0, alpha, false); break; case SWAY_VIEW_XWAYLAND: - render_surface(surface, wlr_output, when, view->x, view->y, 0, alpha); + render_surface(surface, wlr_output, when, + view->box.x, view->box.y, 0, alpha); break; } } diff --git a/sway/input/seat.c b/sway/input/seat.c index ad3584a09..44a471bd2 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -415,8 +415,8 @@ void seat_set_focus_warp(struct sway_seat *seat, if (new_output && last_output && new_output != last_output && config->mouse_warping && warp) { struct wlr_output *output = new_output->sway_output->wlr_output; - double x = container->x + output->lx + container->width / 2.0; - double y = container->y + output->ly + container->height / 2.0; + int x = container->box.x + output->lx + container->box.width / 2; + int y = container->box.y + output->ly + container->box.height / 2; if (!wlr_output_layout_contains_point( root_container.sway_root->output_layout, output, seat->cursor->cursor->x, seat->cursor->cursor->y)) { diff --git a/sway/ipc-json.c b/sway/ipc-json.c index f9c6c90bc..951adadab 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -47,10 +47,10 @@ json_object *ipc_json_get_version() { 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)); - json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); - json_object_object_add(rect, "width", json_object_new_int((int32_t)c->width)); - json_object_object_add(rect, "height", json_object_new_int((int32_t)c->height)); + json_object_object_add(rect, "x", json_object_new_int(c->box.x)); + json_object_object_add(rect, "y", json_object_new_int(c->box.y)); + json_object_object_add(rect, "width", json_object_new_int(c->box.width)); + json_object_object_add(rect, "height", json_object_new_int(c->box.height)); return rect; } diff --git a/sway/tree/container.c b/sway/tree/container.c index ab8363bc3..04fcee813 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -333,8 +333,8 @@ struct sway_container *container_view_create(struct sway_container *sibling, // Setup values swayc->sway_view = sway_view; swayc->name = title ? strdup(title) : NULL; - swayc->width = 0; - swayc->height = 0; + swayc->box.width = 0; + swayc->box.height = 0; if (sibling->type == C_WORKSPACE) { // Case of focused workspace, just create as child of it @@ -418,8 +418,8 @@ struct sway_container *container_at(struct sway_container *parent, soutput->sway_output->wlr_output); double ox = lx - output_box->x; double oy = ly - output_box->y; - double view_sx = ox - swayc->x; - double view_sy = oy - swayc->y; + double view_sx = ox - swayc->box.x; + double view_sy = oy - swayc->box.y; double _sx, _sy; struct wlr_surface *_surface; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 343f349a4..9580d3a71 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -24,10 +24,10 @@ static void output_layout_handle_change(struct wl_listener *listener, root_container.sway_root->output_layout; const struct wlr_box *layout_box = wlr_output_layout_get_box(output_layout, NULL); - root_container.x = layout_box->x; - root_container.y = layout_box->y; - root_container.width = layout_box->width; - root_container.height = layout_box->height; + root_container.box.x = layout_box->x; + root_container.box.y = layout_box->y; + root_container.box.width = layout_box->width; + root_container.box.height = layout_box->height; for (int i = 0 ; i < root_container.children->length; ++i) { struct sway_container *output_container = @@ -42,10 +42,10 @@ static void output_layout_handle_change(struct wl_listener *listener, if (!output_box) { continue; } - output_container->x = output_box->x; - output_container->y = output_box->y; - output_container->width = output_box->width; - output_container->height = output_box->height; + output_container->box.x = output_box->x; + output_container->box.y = output_box->y; + output_container->box.width = output_box->width; + output_container->box.height = output_box->height; } arrange_windows(&root_container, -1, -1); @@ -112,9 +112,9 @@ struct sway_container *container_add_sibling(struct sway_container *fixed, 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); + wlr_log(L_DEBUG, "Adding id:%zd (%d, %dx%d) to id:%zd (%d, %dx%d)", + child->id, child->type, child->box.width, child->box.height, + parent->id, parent->type, parent->box.width, parent->box.height); list_add(parent->children, child); child->parent = parent; } @@ -138,7 +138,7 @@ void container_move_to(struct sway_container *container, return; } struct sway_container *old_parent = container_remove_child(container); - container->width = container->height = 0; + container->box.width = container->box.height = 0; struct sway_container *new_parent; if (destination->type == C_VIEW) { new_parent = container_add_sibling(destination, container); @@ -187,11 +187,10 @@ enum sway_container_layout container_get_default_layout( return config->default_layout; } else if (config->default_orientation != L_NONE) { return config->default_orientation; - } else if (con->width >= con->height) { + } else if (con->box.width >= con->box.height) { return L_HORIZ; - } else { - return L_VERT; } + return L_VERT; } static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { @@ -216,25 +215,23 @@ void container_sort_workspaces(struct sway_container *output) { list_stable_sort(output->children, sort_workspace_cmp_qsort); } -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_horiz_layout(struct sway_container *container, + const int x, const int y, const int width, + const int height, const int start, const int end); -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); +static void apply_vert_layout(struct sway_container *container, + const int x, const int y, const int width, + const int height, const int start, const int end); void arrange_windows(struct sway_container *container, - double width, double height) { + int width, int height) { if (config->reloading) { return; } int i; if (width == -1 || height == -1) { - width = container->width; - height = container->height; + width = container->box.width; + height = container->box.height; } // pixels are indivisible. if we don't round the pixels, then the view // calculations will be off (e.g. 50.5 + 50.5 = 101, but in reality it's @@ -242,17 +239,17 @@ void arrange_windows(struct sway_container *container, width = floor(width); height = floor(height); - wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, - container->name, container->width, container->height, container->x, - container->y); + wlr_log(L_DEBUG, "Arranging layout for %p %s %dx%d+%d,%d", container, + container->name, container->box.width, container->box.height, + container->box.x, container->box.y); - double x = 0, y = 0; + int x = 0, y = 0; switch (container->type) { case C_ROOT: for (i = 0; i < container->children->length; ++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); + wlr_log(L_DEBUG, "Arranging output '%s' at %d,%d", + output->name, output->box.x, output->box.y); arrange_windows(output, -1, -1); } return; @@ -261,8 +258,8 @@ void arrange_windows(struct sway_container *container, int _width, _height; wlr_output_effective_resolution( container->sway_output->wlr_output, &_width, &_height); - width = container->width = _width; - height = container->height = _height; + width = container->box.width = _width; + height = container->box.height = _height; } // arrange all workspaces: for (i = 0; i < container->children->length; ++i) { @@ -277,31 +274,32 @@ void arrange_windows(struct sway_container *container, 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); - container->width = width = area->width; - container->height = height = area->height; - container->x = x = area->x; - container->y = y = area->y; - wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", - container->name, container->x, container->y); + container->box.width = width = area->width; + container->box.height = height = area->height; + container->box.x = x = area->x; + container->box.y = y = area->y; + wlr_log(L_DEBUG, "Arranging workspace '%s' at %d,%d", + container->name, container->box.x, container->box.y); } // children are properly handled below break; case C_VIEW: { - container->width = width; - container->height = height; - view_configure(container->sway_view, container->x, container->y, - container->width, container->height); - wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", - container->width, container->height, - container->x, container->y); + container->box.width = width; + container->box.height = height; + view_configure(container->sway_view, + container->box.x, container->box.y, + container->box.width, container->box.height); + wlr_log(L_DEBUG, "Set view to %d x %d @ %d, %d", + container->box.width, container->box.height, + container->box.x, container->box.y); } return; default: - container->width = width; - container->height = height; - x = container->x; - y = container->y; + container->box.width = width; + container->box.height = height; + x = container->box.x; + y = container->box.y; break; } @@ -323,50 +321,49 @@ void arrange_windows(struct sway_container *container, } static void apply_horiz_layout(struct sway_container *container, - const double x, const double y, - const double width, const double height, + const int x, const int y, const int width, const int 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; - if (*old_width <= 0) { + struct sway_container *child = container->children->items[i]; + int old_width = child->box.width; + if (old_width <= 0) { if (end - start > 1) { - *old_width = width / (end - start - 1); + old_width = width / (end - start - 1); } else { - *old_width = width; + old_width = width; } } - scale += *old_width; + scale += old_width; } scale = width / scale; // Resize windows - double child_x = x; + int child_x = x; 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]; wlr_log(L_DEBUG, - "Calculating arrangement for %p:%d (will scale %f by %f)", + "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, width, scale); if (child->type == C_VIEW) { - view_configure(child->sway_view, child_x, y, child->width, - child->height); + view_configure(child->sway_view, child_x, y, + child->box.width, child->box.height); } else { - child->x = child_x; - child->y = y; + child->box.x = child_x; + child->box.y = y; } if (i == end - 1) { - double remaining_width = x + width - child_x; + int remaining_width = x + width - child_x; arrange_windows(child, remaining_width, height); } else { - arrange_windows(child, child->width * scale, height); + arrange_windows(child, child->box.width * scale, height); } - child_x += child->width; + child_x += child->box.width; } // update focused view border last because it may @@ -380,50 +377,49 @@ static void apply_horiz_layout(struct sway_container *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) { + const int x, const int y, const int width, const int height, + const int start, const int end) { int i; double scale = 0; // Calculate total height for (i = start; i < end; ++i) { - double *old_height = - &((struct sway_container *)container->children->items[i])->height; - if (*old_height <= 0) { + struct sway_container *child = container->children->items[i]; + int old_height = child->box.height; + if (old_height <= 0) { if (end - start > 1) { - *old_height = height / (end - start - 1); + old_height = height / (end - start - 1); } else { - *old_height = height; + old_height = height; } } - scale += *old_height; + scale += old_height; } scale = height / scale; // Resize - double child_y = y; + int child_y = y; 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]; wlr_log(L_DEBUG, - "Calculating arrangement for %p:%d (will scale %f by %f)", + "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, height, scale); if (child->type == C_VIEW) { - view_configure(child->sway_view, x, child_y, child->width, - child->height); + view_configure(child->sway_view, x, child_y, + child->box.width, child->box.height); } else { - child->x = x; - child->y = child_y; + child->box.x = x; + child->box.y = child_y; } if (i == end - 1) { - double remaining_height = y + height - child_y; + int remaining_height = y + height - child_y; arrange_windows(child, width, remaining_height); } else { - arrange_windows(child, width, child->height * scale); + arrange_windows(child, width, child->box.height * scale); } - child_y += child->height; + child_y += child->box.height; } // update focused view border last because it may @@ -496,18 +492,18 @@ 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; + *x = container->box.x + container->box.width / 2; + *y = container->box.y + container->box.height / 2; } else { 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. - *x = output->x; - *y = output->y; + *x = output->box.x; + *y = output->box.y; } else { - *x = output->x + container->x; - *y = output->y + container->y; + *x = output->box.x + container->box.x; + *y = output->box.y + container->box.y; } } } @@ -678,14 +674,14 @@ struct sway_container *container_replace_child(struct sway_container *child, child->parent = NULL; // Set geometry for new child - new_child->x = child->x; - new_child->y = child->y; - new_child->width = child->width; - new_child->height = child->height; + new_child->box.x = child->box.x; + new_child->box.y = child->box.y; + new_child->box.width = child->box.width; + new_child->box.height = child->box.height; // reset geometry for child - child->width = 0; - child->height = 0; + child->box.width = 0; + child->box.height = 0; return parent; } @@ -701,10 +697,10 @@ struct sway_container *container_split(struct sway_container *child, wlr_log(L_DEBUG, "creating container %p around %p", cont, child); cont->prev_layout = L_NONE; - cont->width = child->width; - cont->height = child->height; - cont->x = child->x; - cont->y = child->y; + cont->box.width = child->box.width; + cont->box.height = child->box.height; + cont->box.x = child->box.x; + cont->box.y = child->box.y; if (child->type == C_WORKSPACE) { struct sway_seat *seat = input_manager_get_default_seat(input_manager); @@ -737,10 +733,10 @@ void container_recursive_resize(struct sway_container *container, bool layout_match = true; wlr_log(L_DEBUG, "Resizing %p with amount: %f", container, amount); if (edge == RESIZE_EDGE_LEFT || edge == RESIZE_EDGE_RIGHT) { - container->width += amount; + container->box.width += amount; layout_match = container->layout == L_HORIZ; } else if (edge == RESIZE_EDGE_TOP || edge == RESIZE_EDGE_BOTTOM) { - container->height += amount; + container->box.height += amount; layout_match = container->layout == L_VERT; } if (container->children) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 9855c5e15..8ceb0d6cf 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -96,8 +96,8 @@ void view_damage_from(struct sway_view *view) { static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - box->x = output->x + view->swayc->x; - box->y = output->y + view->swayc->y; + box->x = output->box.x + view->swayc->box.x; + box->y = output->box.y + view->swayc->box.y; box->width = view->width; box->height = view->height; } @@ -216,13 +216,13 @@ void view_unmap(struct sway_view *view) { } void view_update_position(struct sway_view *view, double ox, double oy) { - if (view->swayc->x == ox && view->swayc->y == oy) { + if (view->swayc->box.x == ox && view->swayc->box.y == oy) { return; } view_damage_whole(view); - view->swayc->x = ox; - view->swayc->y = oy; + view->swayc->box.x = ox; + view->swayc->box.y = oy; view_damage_whole(view); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 316f01e4e..9e1a8a378 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -50,10 +50,10 @@ struct sway_container *workspace_create(struct sway_container *output, wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); struct sway_container *workspace = container_create(C_WORKSPACE); - workspace->x = output->x; - workspace->y = output->y; - workspace->width = output->width; - workspace->height = output->height; + workspace->box.x = output->box.x; + workspace->box.y = output->box.y; + workspace->box.width = output->box.width; + workspace->box.height = output->box.height; workspace->name = !name ? NULL : strdup(name); workspace->prev_layout = L_NONE; workspace->layout = container_get_default_layout(output); From df0d57b91660913659ba032fcb188b2d65e5c689 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 15:54:03 -0400 Subject: [PATCH 482/522] Fix issue with incorrectly rejiggered workspaces --- sway/debug-tree.c | 12 +++++++++--- sway/tree/layout.c | 9 ++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/sway/debug-tree.c b/sway/debug-tree.c index 07c48a257..d803d07b8 100644 --- a/sway/debug-tree.c +++ b/sway/debug-tree.c @@ -38,6 +38,7 @@ static int draw_container(cairo_t *cairo, struct sway_container *container, container_type_to_str(container->type), container->id, container->name, layout_to_str(container->layout), container->width, container->height, container->x, container->y); + cairo_save(cairo); cairo_rectangle(cairo, x + 2, y, text_width - 2, text_height); cairo_set_source_u32(cairo, 0xFFFFFFE0); cairo_fill(cairo); @@ -45,17 +46,21 @@ static int draw_container(cairo_t *cairo, struct sway_container *container, if (container->children) { for (int i = 0; i < container->children->length; ++i) { struct sway_container *child = container->children->items[i]; + if (child->parent == container) { + cairo_set_source_u32(cairo, 0x000000FF); + } else { + cairo_set_source_u32(cairo, 0xFF0000FF); + } height += draw_container(cairo, child, focus, x + 10, y + height); } } cairo_set_source_u32(cairo, 0xFFFFFFE0); cairo_rectangle(cairo, x, y, 2, height); cairo_fill(cairo); + cairo_restore(cairo); cairo_move_to(cairo, x, y); if (focus == container) { - cairo_set_source_u32(cairo, 0xFF0000FF); - } else { - cairo_set_source_u32(cairo, 0x000000FF); + cairo_set_source_u32(cairo, 0x0000FFFF); } pango_printf(cairo, "monospace", 1, false, "%s id:%zd '%s' %s %dx%d@%d,%d", container_type_to_str(container->type), container->id, container->name, @@ -95,6 +100,7 @@ void update_debug_tree() { if (seat != NULL) { focus = seat_get_focus(seat); } + cairo_set_source_u32(cairo, 0x000000FF); draw_container(cairo, &root_container, focus, 0, 0); cairo_surface_flush(surface); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index a3bee883b..5dbf48300 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -334,9 +334,12 @@ void container_move(struct sway_container *container, } case C_WORKSPACE: if (!is_parallel(current->layout, move_dir)) { - // Special case - wlr_log(L_DEBUG, "Rejiggering the workspace"); - workspace_rejigger(current, container, move_dir); + if (current->children->length != 1) { + // Special case + wlr_log(L_DEBUG, "Rejiggering the workspace (%d kiddos)", + current->children->length); + workspace_rejigger(current, container, move_dir); + } return; } else { wlr_log(L_DEBUG, "Selecting output"); From 0c627918bb1d4c056744157b8c37fb1f62c5ca8e Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 6 Apr 2018 15:59:50 -0400 Subject: [PATCH 483/522] Damage all surfaces when damaging whole container --- sway/desktop/output.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0f25cff18..db2928fd9 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -401,6 +401,17 @@ void output_damage_view(struct sway_output *output, struct sway_view *view, damage_surface_iterator, &data); } +static void output_damage_whole_container_iterator(struct sway_container *con, + void *data) { + struct sway_output *output = data; + + if (!sway_assert(con->type != C_VIEW, "expected a view")) { + return; + } + + output_damage_view(output, con->sway_view, true); +} + void output_damage_whole_container(struct sway_output *output, struct sway_container *con) { float scale = output->wlr_output->scale; @@ -411,6 +422,9 @@ void output_damage_whole_container(struct sway_output *output, .height = con->height * scale, }; wlr_output_damage_add_box(output->damage, &box); + + container_descendants(con, C_VIEW, output_damage_whole_container_iterator, + output); } static void damage_handle_destroy(struct wl_listener *listener, void *data) { From 640232eb225058a18f20190235f679caf678e1f7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 16:13:26 -0400 Subject: [PATCH 484/522] Revert "Break everything^W^WUse wlr_box for sway_container" --- include/sway/tree/container.h | 10 +- include/sway/tree/layout.h | 3 +- sway/commands/layout.c | 2 +- sway/commands/move.c | 7 +- sway/commands/resize.c | 8 +- sway/desktop/desktop.c | 2 +- sway/desktop/output.c | 15 +-- sway/input/seat.c | 4 +- sway/ipc-json.c | 8 +- sway/tree/container.c | 8 +- sway/tree/layout.c | 204 +++++++++++++++++----------------- sway/tree/view.c | 10 +- sway/tree/workspace.c | 8 +- 13 files changed, 145 insertions(+), 144 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index e7a071bea..4c60530fa 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -68,10 +68,12 @@ struct sway_container { enum sway_container_layout prev_layout; enum sway_container_layout workspace_layout; - // For C_ROOT, this is the extents of the whole layout box. - // For C_OUTPUT, this is the output position in layout coordinates. - // For other types, this is the position in output-local coordinates. - struct wlr_box box; + // For C_ROOT, this has no meaning + // For C_OUTPUT, this is the output position in layout coordinates + // For other types, this is the position in output-local coordinates + double x, y; + // does not include borders or gaps. + double width, height; list_t *children; diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index b2b98ee44..fc5ce21f8 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -61,7 +61,8 @@ enum sway_container_layout container_get_default_layout( void container_sort_workspaces(struct sway_container *output); -void arrange_windows(struct sway_container *container, int width, int height); +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); diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 162173c53..4c49a627f 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -49,7 +49,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } } - arrange_windows(parent, parent->box.width, parent->box.height); + arrange_windows(parent, parent->width, parent->height); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/move.c b/sway/commands/move.c index e8668ce76..c954ab94e 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -95,8 +95,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, } struct sway_container *source = container_parent(current, C_OUTPUT); struct sway_container *destination = output_in_direction(argv[3], - source->sway_output->wlr_output, - current->box.x, current->box.y); + source->sway_output->wlr_output, current->x, current->y); if (!destination) { return cmd_results_new(CMD_FAILURE, "move workspace", "Can't find output with name/direction '%s'", argv[3]); @@ -125,8 +124,8 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current, return cmd_results_new(CMD_INVALID, "move", expected_syntax); } struct sway_container *source = container_parent(current, C_OUTPUT); - int center_x = current->box.width / 2 + current->box.x, - center_y = current->box.height / 2 + current->box.y; + int center_x = current->width / 2 + current->x, + center_y = current->height / 2 + current->y; struct sway_container *destination = output_in_direction(argv[3], source->sway_output->wlr_output, center_x, center_y); if (!destination) { diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 8e295f655..93c1fe7de 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -48,11 +48,11 @@ static enum resize_axis parse_resize_axis(const char *axis) { } static int parallel_coord(struct sway_container *c, enum resize_axis a) { - return a == RESIZE_AXIS_HORIZONTAL ? c->box.x : c->box.y; + return a == RESIZE_AXIS_HORIZONTAL ? c->x : c->y; } static int parallel_size(struct sway_container *c, enum resize_axis a) { - return a == RESIZE_AXIS_HORIZONTAL ? c->box.width : c->box.height; + return a == RESIZE_AXIS_HORIZONTAL ? c->width : c->height; } static void resize_tiled(int amount, enum resize_axis axis) { @@ -196,10 +196,10 @@ static void resize(int amount, enum resize_axis axis, enum resize_unit unit) { float pct = amount / 100.0f; switch (axis) { case RESIZE_AXIS_HORIZONTAL: - amount = (float)current->box.width * pct; + amount = (float)current->width * pct; break; case RESIZE_AXIS_VERTICAL: - amount = (float)current->box.height * pct; + amount = (float)current->height * pct; break; default: sway_assert(0, "invalid resize axis"); diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index f0a14445f..3a13191f2 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c @@ -8,7 +8,7 @@ void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, struct sway_container *cont = root_container.children->items[i]; if (cont->type == C_OUTPUT) { output_damage_whole_surface(cont->sway_output, - lx - cont->box.x, ly - cont->box.y, surface); + lx - cont->x, ly - cont->y, surface); } } } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 49ffe74c8..aa18f1b8a 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -192,22 +192,17 @@ static void render_view(struct sway_container *view, void *data) { int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; render_surface(surface, wlr_output, when, - view->box.x - window_offset_x, - view->box.y - window_offset_y, - 0, alpha); - render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, when, - view->box.x - window_offset_x, - view->box.y - window_offset_y, - 0, alpha); + view->x - window_offset_x, view->y - window_offset_y, 0, alpha); + render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, + when, view->x - window_offset_x, view->y - window_offset_y, 0, alpha); break; } case SWAY_VIEW_WL_SHELL: render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, - when, view->box.x, view->box.y, 0, alpha, false); + when, view->x, view->y, 0, alpha, false); break; case SWAY_VIEW_XWAYLAND: - render_surface(surface, wlr_output, when, - view->box.x, view->box.y, 0, alpha); + render_surface(surface, wlr_output, when, view->x, view->y, 0, alpha); break; } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 44a471bd2..ad3584a09 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -415,8 +415,8 @@ void seat_set_focus_warp(struct sway_seat *seat, if (new_output && last_output && new_output != last_output && config->mouse_warping && warp) { struct wlr_output *output = new_output->sway_output->wlr_output; - int x = container->box.x + output->lx + container->box.width / 2; - int y = container->box.y + output->ly + container->box.height / 2; + double x = container->x + output->lx + container->width / 2.0; + double y = container->y + output->ly + container->height / 2.0; if (!wlr_output_layout_contains_point( root_container.sway_root->output_layout, output, seat->cursor->cursor->x, seat->cursor->cursor->y)) { diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 951adadab..f9c6c90bc 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -47,10 +47,10 @@ json_object *ipc_json_get_version() { 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(c->box.x)); - json_object_object_add(rect, "y", json_object_new_int(c->box.y)); - json_object_object_add(rect, "width", json_object_new_int(c->box.width)); - json_object_object_add(rect, "height", json_object_new_int(c->box.height)); + json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); + json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); + json_object_object_add(rect, "width", json_object_new_int((int32_t)c->width)); + json_object_object_add(rect, "height", json_object_new_int((int32_t)c->height)); return rect; } diff --git a/sway/tree/container.c b/sway/tree/container.c index 04fcee813..ab8363bc3 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -333,8 +333,8 @@ struct sway_container *container_view_create(struct sway_container *sibling, // Setup values swayc->sway_view = sway_view; swayc->name = title ? strdup(title) : NULL; - swayc->box.width = 0; - swayc->box.height = 0; + swayc->width = 0; + swayc->height = 0; if (sibling->type == C_WORKSPACE) { // Case of focused workspace, just create as child of it @@ -418,8 +418,8 @@ struct sway_container *container_at(struct sway_container *parent, soutput->sway_output->wlr_output); double ox = lx - output_box->x; double oy = ly - output_box->y; - double view_sx = ox - swayc->box.x; - double view_sy = oy - swayc->box.y; + double view_sx = ox - swayc->x; + double view_sy = oy - swayc->y; double _sx, _sy; struct wlr_surface *_surface; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 9580d3a71..343f349a4 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -24,10 +24,10 @@ static void output_layout_handle_change(struct wl_listener *listener, root_container.sway_root->output_layout; const struct wlr_box *layout_box = wlr_output_layout_get_box(output_layout, NULL); - root_container.box.x = layout_box->x; - root_container.box.y = layout_box->y; - root_container.box.width = layout_box->width; - root_container.box.height = layout_box->height; + root_container.x = layout_box->x; + root_container.y = layout_box->y; + 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 = @@ -42,10 +42,10 @@ static void output_layout_handle_change(struct wl_listener *listener, if (!output_box) { continue; } - output_container->box.x = output_box->x; - output_container->box.y = output_box->y; - output_container->box.width = output_box->width; - output_container->box.height = output_box->height; + output_container->x = output_box->x; + output_container->y = output_box->y; + output_container->width = output_box->width; + output_container->height = output_box->height; } arrange_windows(&root_container, -1, -1); @@ -112,9 +112,9 @@ struct sway_container *container_add_sibling(struct sway_container *fixed, void container_add_child(struct sway_container *parent, struct sway_container *child) { - wlr_log(L_DEBUG, "Adding id:%zd (%d, %dx%d) to id:%zd (%d, %dx%d)", - child->id, child->type, child->box.width, child->box.height, - parent->id, parent->type, parent->box.width, parent->box.height); + 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); list_add(parent->children, child); child->parent = parent; } @@ -138,7 +138,7 @@ void container_move_to(struct sway_container *container, return; } struct sway_container *old_parent = container_remove_child(container); - container->box.width = container->box.height = 0; + container->width = container->height = 0; struct sway_container *new_parent; if (destination->type == C_VIEW) { new_parent = container_add_sibling(destination, container); @@ -187,10 +187,11 @@ enum sway_container_layout container_get_default_layout( return config->default_layout; } else if (config->default_orientation != L_NONE) { return config->default_orientation; - } else if (con->box.width >= con->box.height) { + } else if (con->width >= con->height) { return L_HORIZ; + } else { + return L_VERT; } - return L_VERT; } static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { @@ -215,23 +216,25 @@ void container_sort_workspaces(struct sway_container *output) { list_stable_sort(output->children, sort_workspace_cmp_qsort); } -static void apply_horiz_layout(struct sway_container *container, - const int x, const int y, const int width, - const int height, const int start, const int end); +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(struct sway_container *container, - const int x, const int y, const int width, - const int height, const int start, const int end); +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(struct sway_container *container, - int width, int height) { + double width, double height) { if (config->reloading) { return; } int i; if (width == -1 || height == -1) { - width = container->box.width; - height = container->box.height; + width = container->width; + height = container->height; } // pixels are indivisible. if we don't round the pixels, then the view // calculations will be off (e.g. 50.5 + 50.5 = 101, but in reality it's @@ -239,17 +242,17 @@ void arrange_windows(struct sway_container *container, width = floor(width); height = floor(height); - wlr_log(L_DEBUG, "Arranging layout for %p %s %dx%d+%d,%d", container, - container->name, container->box.width, container->box.height, - container->box.x, container->box.y); + wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, + container->name, container->width, container->height, container->x, + container->y); - int x = 0, y = 0; + double x = 0, y = 0; switch (container->type) { case C_ROOT: for (i = 0; i < container->children->length; ++i) { struct sway_container *output = container->children->items[i]; - wlr_log(L_DEBUG, "Arranging output '%s' at %d,%d", - output->name, output->box.x, output->box.y); + wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", + output->name, output->x, output->y); arrange_windows(output, -1, -1); } return; @@ -258,8 +261,8 @@ void arrange_windows(struct sway_container *container, int _width, _height; wlr_output_effective_resolution( container->sway_output->wlr_output, &_width, &_height); - width = container->box.width = _width; - height = container->box.height = _height; + width = container->width = _width; + height = container->height = _height; } // arrange all workspaces: for (i = 0; i < container->children->length; ++i) { @@ -274,32 +277,31 @@ void arrange_windows(struct sway_container *container, 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); - container->box.width = width = area->width; - container->box.height = height = area->height; - container->box.x = x = area->x; - container->box.y = y = area->y; - wlr_log(L_DEBUG, "Arranging workspace '%s' at %d,%d", - container->name, container->box.x, container->box.y); + container->width = width = area->width; + container->height = height = area->height; + container->x = x = area->x; + container->y = y = area->y; + wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", + container->name, container->x, container->y); } // children are properly handled below break; case C_VIEW: { - container->box.width = width; - container->box.height = height; - view_configure(container->sway_view, - container->box.x, container->box.y, - container->box.width, container->box.height); - wlr_log(L_DEBUG, "Set view to %d x %d @ %d, %d", - container->box.width, container->box.height, - container->box.x, container->box.y); + container->width = width; + container->height = height; + view_configure(container->sway_view, container->x, container->y, + container->width, container->height); + wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", + container->width, container->height, + container->x, container->y); } return; default: - container->box.width = width; - container->box.height = height; - x = container->box.x; - y = container->box.y; + container->width = width; + container->height = height; + x = container->x; + y = container->y; break; } @@ -321,49 +323,50 @@ void arrange_windows(struct sway_container *container, } static void apply_horiz_layout(struct sway_container *container, - const int x, const int y, const int width, const int height, + 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) { - struct sway_container *child = container->children->items[i]; - int old_width = child->box.width; - if (old_width <= 0) { + 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); + *old_width = width / (end - start - 1); } else { - old_width = width; + *old_width = width; } } - scale += old_width; + scale += *old_width; } scale = width / scale; // Resize windows - int child_x = x; + double child_x = x; 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]; wlr_log(L_DEBUG, - "Calculating arrangement for %p:%d (will scale %d by %f)", + "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); if (child->type == C_VIEW) { - view_configure(child->sway_view, child_x, y, - child->box.width, child->box.height); + view_configure(child->sway_view, child_x, y, child->width, + child->height); } else { - child->box.x = child_x; - child->box.y = y; + child->x = child_x; + child->y = y; } if (i == end - 1) { - int remaining_width = x + width - child_x; + double remaining_width = x + width - child_x; arrange_windows(child, remaining_width, height); } else { - arrange_windows(child, child->box.width * scale, height); + arrange_windows(child, child->width * scale, height); } - child_x += child->box.width; + child_x += child->width; } // update focused view border last because it may @@ -377,49 +380,50 @@ static void apply_horiz_layout(struct sway_container *container, } void apply_vert_layout(struct sway_container *container, - const int x, const int y, const int width, const int height, - const int start, const int end) { + const double x, const double y, + const double width, const double height, const int start, + const int end) { int i; double scale = 0; // Calculate total height for (i = start; i < end; ++i) { - struct sway_container *child = container->children->items[i]; - int old_height = child->box.height; - if (old_height <= 0) { + 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); + *old_height = height / (end - start - 1); } else { - old_height = height; + *old_height = height; } } - scale += old_height; + scale += *old_height; } scale = height / scale; // Resize - int child_y = y; + double child_y = y; 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]; wlr_log(L_DEBUG, - "Calculating arrangement for %p:%d (will scale %d by %f)", + "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); if (child->type == C_VIEW) { - view_configure(child->sway_view, x, child_y, - child->box.width, child->box.height); + view_configure(child->sway_view, x, child_y, child->width, + child->height); } else { - child->box.x = x; - child->box.y = child_y; + child->x = x; + child->y = child_y; } if (i == end - 1) { - int remaining_height = y + height - child_y; + double remaining_height = y + height - child_y; arrange_windows(child, width, remaining_height); } else { - arrange_windows(child, width, child->box.height * scale); + arrange_windows(child, width, child->height * scale); } - child_y += child->box.height; + child_y += child->height; } // update focused view border last because it may @@ -492,18 +496,18 @@ 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->box.x + container->box.width / 2; - *y = container->box.y + container->box.height / 2; + *x = container->x + container->width/2; + *y = container->y + container->height/2; } else { 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. - *x = output->box.x; - *y = output->box.y; + *x = output->x; + *y = output->y; } else { - *x = output->box.x + container->box.x; - *y = output->box.y + container->box.y; + *x = output->x + container->x; + *y = output->y + container->y; } } } @@ -674,14 +678,14 @@ struct sway_container *container_replace_child(struct sway_container *child, child->parent = NULL; // Set geometry for new child - new_child->box.x = child->box.x; - new_child->box.y = child->box.y; - new_child->box.width = child->box.width; - new_child->box.height = child->box.height; + new_child->x = child->x; + new_child->y = child->y; + new_child->width = child->width; + new_child->height = child->height; // reset geometry for child - child->box.width = 0; - child->box.height = 0; + child->width = 0; + child->height = 0; return parent; } @@ -697,10 +701,10 @@ struct sway_container *container_split(struct sway_container *child, wlr_log(L_DEBUG, "creating container %p around %p", cont, child); cont->prev_layout = L_NONE; - cont->box.width = child->box.width; - cont->box.height = child->box.height; - cont->box.x = child->box.x; - cont->box.y = child->box.y; + cont->width = child->width; + cont->height = child->height; + cont->x = child->x; + cont->y = child->y; if (child->type == C_WORKSPACE) { struct sway_seat *seat = input_manager_get_default_seat(input_manager); @@ -733,10 +737,10 @@ void container_recursive_resize(struct sway_container *container, bool layout_match = true; wlr_log(L_DEBUG, "Resizing %p with amount: %f", container, amount); if (edge == RESIZE_EDGE_LEFT || edge == RESIZE_EDGE_RIGHT) { - container->box.width += amount; + container->width += amount; layout_match = container->layout == L_HORIZ; } else if (edge == RESIZE_EDGE_TOP || edge == RESIZE_EDGE_BOTTOM) { - container->box.height += amount; + container->height += amount; layout_match = container->layout == L_VERT; } if (container->children) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 8ceb0d6cf..9855c5e15 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -96,8 +96,8 @@ void view_damage_from(struct sway_view *view) { static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - box->x = output->box.x + view->swayc->box.x; - box->y = output->box.y + view->swayc->box.y; + box->x = output->x + view->swayc->x; + box->y = output->y + view->swayc->y; box->width = view->width; box->height = view->height; } @@ -216,13 +216,13 @@ void view_unmap(struct sway_view *view) { } void view_update_position(struct sway_view *view, double ox, double oy) { - if (view->swayc->box.x == ox && view->swayc->box.y == oy) { + if (view->swayc->x == ox && view->swayc->y == oy) { return; } view_damage_whole(view); - view->swayc->box.x = ox; - view->swayc->box.y = oy; + view->swayc->x = ox; + view->swayc->y = oy; view_damage_whole(view); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 9e1a8a378..316f01e4e 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -50,10 +50,10 @@ struct sway_container *workspace_create(struct sway_container *output, wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); struct sway_container *workspace = container_create(C_WORKSPACE); - workspace->box.x = output->box.x; - workspace->box.y = output->box.y; - workspace->box.width = output->box.width; - workspace->box.height = output->box.height; + workspace->x = output->x; + workspace->y = output->y; + workspace->width = output->width; + workspace->height = output->height; workspace->name = !name ? NULL : strdup(name); workspace->prev_layout = L_NONE; workspace->layout = container_get_default_layout(output); From 606d322bc20af217da7d015fc8527f4cb7e2a418 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 6 Apr 2018 16:19:06 -0400 Subject: [PATCH 485/522] Container coordiantes/sizes are floating point --- sway/debug-tree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/debug-tree.c b/sway/debug-tree.c index d803d07b8..ae0a1869b 100644 --- a/sway/debug-tree.c +++ b/sway/debug-tree.c @@ -34,7 +34,7 @@ static int draw_container(cairo_t *cairo, struct sway_container *container, struct sway_container *focus, int x, int y) { int text_width, text_height; get_text_size(cairo, "monospace", &text_width, &text_height, - 1, false, "%s id:%zd '%s' %s %dx%d@%d,%d", + 1, false, "%s id:%zd '%s' %s %.fx%.f@%.f,%.f", container_type_to_str(container->type), container->id, container->name, layout_to_str(container->layout), container->width, container->height, container->x, container->y); @@ -62,7 +62,7 @@ static int draw_container(cairo_t *cairo, struct sway_container *container, if (focus == container) { cairo_set_source_u32(cairo, 0x0000FFFF); } - pango_printf(cairo, "monospace", 1, false, "%s id:%zd '%s' %s %dx%d@%d,%d", + pango_printf(cairo, "monospace", 1, false, "%s id:%zd '%s' %s %.fx%.f@%.f,%.f", container_type_to_str(container->type), container->id, container->name, layout_to_str(container->layout), container->width, container->height, container->x, container->y); From 37b173f326d89a43812dfab5846a3f04400ff94a Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 6 Apr 2018 17:50:12 -0400 Subject: [PATCH 486/522] When moving between outputs, use output center as reference --- sway/tree/layout.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 5dbf48300..77b2448a7 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -308,14 +308,11 @@ void container_move(struct sway_container *container, case C_OUTPUT: { enum wlr_direction wlr_dir; sway_dir_to_wlr(move_dir, &wlr_dir); - double ref_x = current->x + current->width / 2; - double ref_y = current->y + current->height / 2; - ref_x += current->sway_output->swayc->x; - ref_y += current->sway_output->swayc->y; + double ref_lx = current->x + current->width / 2; + double ref_ly = current->y + current->height / 2; struct wlr_output *next = wlr_output_layout_adjacent_output( root_container.sway_root->output_layout, wlr_dir, - current->sway_output->wlr_output, - current->x, current->y); + current->sway_output->wlr_output, ref_lx, ref_ly); if (!next) { wlr_log(L_DEBUG, "Hit edge of output, nowhere else to go"); return; From 93ca8919f63c7022779c9780a24478559e7e47af Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 6 Apr 2018 18:10:02 -0400 Subject: [PATCH 487/522] Don't rejigger if parent has two children --- sway/tree/layout.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 77b2448a7..78af8b8cc 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -331,11 +331,17 @@ void container_move(struct sway_container *container, } case C_WORKSPACE: if (!is_parallel(current->layout, move_dir)) { - if (current->children->length != 1) { - // Special case + if (current->children->length > 2) { wlr_log(L_DEBUG, "Rejiggering the workspace (%d kiddos)", current->children->length); workspace_rejigger(current, container, move_dir); + } else if (current->children->length == 2) { + wlr_log(L_DEBUG, "Changing workspace layout"); + container_set_layout(current, + move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? + L_HORIZ : L_VERT); + container_insert_child(current, container, offs < 0 ? 0 : 1); + arrange_windows(current, -1, -1); } return; } else { From 5727b81128dc0c8e4cffa80afcfe510d2051c103 Mon Sep 17 00:00:00 2001 From: Danilo Spinella Date: Sat, 7 Apr 2018 11:08:39 +0200 Subject: [PATCH 488/522] Fix json-c version dependency --- README.de.md | 2 +- README.el.md | 2 +- README.fr.md | 2 +- README.it.md | 2 +- README.ja.md | 2 +- README.md | 2 +- README.pt.md | 2 +- README.ru.md | 2 +- README.uk.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.de.md b/README.de.md index dbef4ee6a..530d8dd70 100644 --- a/README.de.md +++ b/README.de.md @@ -60,7 +60,7 @@ Abhängigkeiten: * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * diff --git a/README.el.md b/README.el.md index 8d8f0f3ea..682dbc844 100644 --- a/README.el.md +++ b/README.el.md @@ -53,7 +53,7 @@ To username μου στο Freenode είναι kon14 και θα με βρείτ * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * diff --git a/README.fr.md b/README.fr.md index 1ffcd4786..360fe6181 100644 --- a/README.fr.md +++ b/README.fr.md @@ -55,7 +55,7 @@ Installez les dépendances : * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * diff --git a/README.it.md b/README.it.md index ef5b81a72..94dc96c6c 100644 --- a/README.it.md +++ b/README.it.md @@ -56,7 +56,7 @@ Installa queste dipendenze: * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * diff --git a/README.ja.md b/README.ja.md index aa4208148..42d31b86e 100644 --- a/README.ja.md +++ b/README.ja.md @@ -46,7 +46,7 @@ Swayは沢山のディストリビューションで提供されています。" * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * diff --git a/README.md b/README.md index ae12ea894..cecbcdb18 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Install dependencies: * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * diff --git a/README.pt.md b/README.pt.md index 69c9538a3..98ad72e31 100644 --- a/README.pt.md +++ b/README.pt.md @@ -62,7 +62,7 @@ Antes de iniciar a compilação, instale as dependências: * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * diff --git a/README.ru.md b/README.ru.md index e1580c81a..659880ca5 100644 --- a/README.ru.md +++ b/README.ru.md @@ -55,7 +55,7 @@ Sway доступен во многих дистрибутивах и наход * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * diff --git a/README.uk.md b/README.uk.md index 71b354708..81bc70fab 100644 --- a/README.uk.md +++ b/README.uk.md @@ -62,7 +62,7 @@ Sway доступний у багатьох дистрибутивах Linux (а * libcap * asciidoc * pcre -* json-c <= 0.12.1 +* json-c >= 0.13 * pango * cairo * gdk-pixbuf2 * From 33b4f945aba39a728bfe20bef6ce4396df494a03 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 7 Apr 2018 12:03:13 -0400 Subject: [PATCH 489/522] Fix inverted assertion Seems like it doesn't work this way --- sway/desktop/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 23d20b79b..dea51bdf2 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -410,7 +410,7 @@ static void output_damage_whole_container_iterator(struct sway_container *con, void *data) { struct sway_output *output = data; - if (!sway_assert(con->type != C_VIEW, "expected a view")) { + if (!sway_assert(con->type == C_VIEW, "expected a view")) { return; } From 8af0c2b00074879335f6e224512667947ca234cf Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 6 Apr 2018 17:37:48 -0400 Subject: [PATCH 490/522] Don't send frame done immediately when rendering --- sway/desktop/output.c | 229 +++++++++++++++++++++++++++--------------- 1 file changed, 147 insertions(+), 82 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 23d20b79b..1a72b5db9 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -66,6 +66,10 @@ struct root_geometry { static bool get_surface_box(struct root_geometry *geo, struct sway_output *output, struct wlr_surface *surface, int sx, int sy, struct wlr_box *surface_box) { + if (!wlr_surface_has_buffer(surface)) { + return false; + } + int sw = surface->current->width; int sh = surface->current->height; @@ -95,7 +99,7 @@ static bool get_surface_box(struct root_geometry *geo, return wlr_box_intersection(&output_box, &rotated_box, &intersection); } -static void output_surface_for_each_surface(struct wlr_surface *surface, +static void surface_for_each_surface(struct wlr_surface *surface, double ox, double oy, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { geo->x = ox; @@ -119,6 +123,34 @@ static void output_view_for_each_surface(struct sway_view *view, view_for_each_surface(view, iterator, user_data); } +static void layer_for_each_surface(struct wl_list *layer_surfaces, + struct root_geometry *geo, wlr_surface_iterator_func_t iterator, + void *user_data) { + struct sway_layer_surface *layer_surface; + wl_list_for_each(layer_surface, layer_surfaces, link) { + struct wlr_layer_surface *wlr_layer_surface = + layer_surface->layer_surface; + surface_for_each_surface(wlr_layer_surface->surface, + layer_surface->geo.x, layer_surface->geo.y, geo, iterator, + user_data); + } +} + +static void unmanaged_for_each_surface(struct wl_list *unmanaged, + struct sway_output *output, struct root_geometry *geo, + wlr_surface_iterator_func_t iterator, void *user_data) { + struct sway_xwayland_unmanaged *unmanaged_surface; + wl_list_for_each(unmanaged_surface, unmanaged, link) { + struct wlr_xwayland_surface *xsurface = + unmanaged_surface->wlr_xwayland_surface; + double ox = unmanaged_surface->lx - output->swayc->x; + double oy = unmanaged_surface->ly - output->swayc->y; + + surface_for_each_surface(xsurface->surface, ox, oy, geo, + iterator, user_data); + } +} + static void scale_box(struct wlr_box *box, float scale) { box->x *= scale; box->y *= scale; @@ -129,7 +161,6 @@ static void scale_box(struct wlr_box *box, float scale) { struct render_data { struct root_geometry root_geo; struct sway_output *output; - struct timespec *when; float alpha; }; @@ -137,7 +168,6 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, void *_data) { struct render_data *data = _data; struct wlr_output *wlr_output = data->output->wlr_output; - struct timespec *when = data->when; float rotation = data->root_geo.rotation; float alpha = data->alpha; @@ -169,59 +199,52 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, wlr_render_texture_with_matrix(renderer, surface->texture, matrix, alpha); - - // TODO: don't send the frame done event now - wlr_surface_send_frame_done(surface, when); } -static void render_surface(struct sway_output *output, struct timespec *when, - struct wlr_surface *surface, double ox, double oy) { - struct render_data data = { - .output = output, - .when = when, - .alpha = 1.0f, - }; - - output_surface_for_each_surface(surface, ox, oy, &data.root_geo, - render_surface_iterator, &data); -} - -static void render_view(struct sway_output *output, struct timespec *when, - struct sway_view *view) { - struct render_data data = { - .output = output, - .when = when, - .alpha = view->swayc->alpha, - }; - - output_view_for_each_surface(view, &data.root_geo, - render_surface_iterator, &data); -} - -static void render_layer(struct sway_output *output, struct timespec *when, +static void render_layer(struct sway_output *output, struct wl_list *layer_surfaces) { - struct sway_layer_surface *layer_surface; - wl_list_for_each(layer_surface, layer_surfaces, link) { - struct wlr_layer_surface *wlr_layer_surface = - layer_surface->layer_surface; - render_surface(output, when, wlr_layer_surface->surface, - layer_surface->geo.x, layer_surface->geo.y); - } + struct render_data data = { .output = output, .alpha = 1.0f }; + layer_for_each_surface(layer_surfaces, &data.root_geo, + render_surface_iterator, &data); } -struct render_view_data { - struct sway_output *output; - struct timespec *when; -}; - -static void render_view_iterator(struct sway_container *con, void *_data) { - struct render_view_data *data = _data; +static void render_unmanaged(struct sway_output *output, + struct wl_list *unmanaged) { + struct render_data data = { .output = output, .alpha = 1.0f }; + unmanaged_for_each_surface(unmanaged, output, &data.root_geo, + render_surface_iterator, &data); +} +static void render_container_iterator(struct sway_container *con, + void *_data) { + struct sway_output *output = _data; if (!sway_assert(con->type == C_VIEW, "expected a view")) { return; } + struct render_data data = { .output = output, .alpha = con->alpha }; + output_view_for_each_surface(con->sway_view, &data.root_geo, + render_surface_iterator, &data); +} - render_view(data->output, data->when, con->sway_view); +static void render_container(struct sway_output *output, + struct sway_container *con) { + container_descendants(con, C_VIEW, render_container_iterator, output); +} + +static struct sway_container *output_get_active_workspace( + struct sway_output *output) { + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = + seat_get_focus_inactive(seat, output->swayc); + if (!focus) { + // We've never been to this output before + focus = output->swayc->children->items[0]; + } + struct sway_container *workspace = focus; + if (workspace->type != C_WORKSPACE) { + workspace = container_parent(workspace, C_WORKSPACE); + } + return workspace; } static void render_output(struct sway_output *output, struct timespec *when, @@ -250,40 +273,17 @@ static void render_output(struct sway_output *output, struct timespec *when, float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; wlr_renderer_clear(renderer, clear_color); - render_layer(output, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - render_layer(output, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); + render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); - // Render all views in the current workspace - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = - seat_get_focus_inactive(seat, output->swayc); - if (!focus) { - // We've never been to this output before - focus = output->swayc->children->items[0]; - } - struct sway_container *workspace = focus->type == C_WORKSPACE ? - focus : container_parent(focus, C_WORKSPACE); - struct render_view_data data = { .output = output, .when = when }; - container_descendants(workspace, C_VIEW, render_view_iterator, &data); + struct sway_container *workspace = output_get_active_workspace(output); + render_container(output, workspace); - // Render unmanaged views on top - struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; - struct sway_xwayland_unmanaged *unmanaged_surface; - wl_list_for_each(unmanaged_surface, unmanaged, link) { - struct wlr_xwayland_surface *xsurface = - unmanaged_surface->wlr_xwayland_surface; - double ox = unmanaged_surface->lx - output->swayc->x; - double oy = unmanaged_surface->ly - output->swayc->y; - render_surface(output, when, xsurface->surface, ox, oy); - } + render_unmanaged(output, &root_container.sway_root->xwayland_unmanaged); // TODO: consider revising this when fullscreen windows are supported - render_layer(output, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); - render_layer(output, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); + render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); + render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); renderer_end: if (root_container.sway_root->debug_tree) { @@ -298,6 +298,74 @@ renderer_end: output->last_frame = *when; } +struct send_frame_done_data { + struct root_geometry root_geo; + struct sway_output *output; + struct timespec *when; +}; + +static void send_frame_done_iterator(struct wlr_surface *surface, + int sx, int sy, void *_data) { + struct send_frame_done_data *data = _data; + + bool intersects = get_surface_box(&data->root_geo, data->output, surface, + sx, sy, NULL); + if (intersects) { + wlr_surface_send_frame_done(surface, data->when); + } +} + +static void send_frame_done_layer(struct send_frame_done_data *data, + struct wl_list *layer_surfaces) { + layer_for_each_surface(layer_surfaces, &data->root_geo, + send_frame_done_iterator, data); +} + +static void send_frame_done_unmanaged(struct send_frame_done_data *data, + struct wl_list *unmanaged) { + unmanaged_for_each_surface(unmanaged, data->output, &data->root_geo, + send_frame_done_iterator, data); +} + +static void send_frame_done_container_iterator(struct sway_container *con, + void *_data) { + struct send_frame_done_data *data = _data; + if (!sway_assert(con->type == C_VIEW, "expected a view")) { + return; + } + output_view_for_each_surface(con->sway_view, &data->root_geo, + send_frame_done_iterator, data); +} + +static void send_frame_done_container(struct send_frame_done_data *data, + struct sway_container *con) { + container_descendants(con, C_VIEW, + send_frame_done_container_iterator, data); +} + +static void send_frame_done(struct sway_output *output, struct timespec *when) { + struct send_frame_done_data data = { + .output = output, + .when = when, + }; + + send_frame_done_layer(&data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); + send_frame_done_layer(&data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + + struct sway_container *workspace = output_get_active_workspace(output); + send_frame_done_container(&data, workspace); + + send_frame_done_unmanaged(&data, + &root_container.sway_root->xwayland_unmanaged); + + send_frame_done_layer(&data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); + send_frame_done_layer(&data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); +} + static void damage_handle_frame(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, damage_frame); @@ -322,7 +390,8 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) { pixman_region32_fini(&damage); - // TODO: send frame done events here instead of inside render_surface + // Send frame done to all visible surfaces + send_frame_done(output, &now); } void output_damage_whole(struct sway_output *output) { @@ -342,10 +411,6 @@ static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, float rotation = data->root_geo.rotation; bool whole = data->whole; - if (!wlr_surface_has_buffer(surface)) { - return; - } - struct wlr_box box; bool intersects = get_surface_box(&data->root_geo, data->output, surface, sx, sy, &box); @@ -387,7 +452,7 @@ void output_damage_surface(struct sway_output *output, double ox, double oy, .whole = whole, }; - output_surface_for_each_surface(surface, ox, oy, &data.root_geo, + surface_for_each_surface(surface, ox, oy, &data.root_geo, damage_surface_iterator, &data); } From 61abd56ca4949db5e2dab4806656d814e1cb423d Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 7 Apr 2018 12:44:02 -0400 Subject: [PATCH 491/522] Fix output containers position --- sway/tree/layout.c | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 78af8b8cc..e81facc60 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -30,26 +30,7 @@ static void output_layout_handle_change(struct wl_listener *listener, 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]; - if (output_container->type != C_OUTPUT) { - continue; - } - struct sway_output *output = output_container->sway_output; - - const struct wlr_box *output_box = - wlr_output_layout_get_box(output_layout, output->wlr_output); - if (!output_box) { - continue; - } - output_container->x = output_box->x; - output_container->y = output_box->y; - output_container->width = output_box->width; - output_container->height = output_box->height; - } - - arrange_windows(&root_container, -1, -1); + arrange_windows(&root_container, layout_box->width, layout_box->height); } struct sway_container *container_set_layout(struct sway_container *container, @@ -551,19 +532,19 @@ void arrange_windows(struct sway_container *container, case C_ROOT: for (i = 0; i < container->children->length; ++i) { struct sway_container *output = container->children->items[i]; + const struct wlr_box *output_box = wlr_output_layout_get_box( + container->sway_root->output_layout, + output->sway_output->wlr_output); + output->x = output_box->x; + output->y = output_box->y; + output->width = output_box->width; + output->height = output_box->height; wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); - arrange_windows(output, -1, -1); + arrange_windows(output, output_box->width, output_box->height); } return; case C_OUTPUT: - { - int _width, _height; - wlr_output_effective_resolution( - container->sway_output->wlr_output, &_width, &_height); - width = container->width = _width; - height = container->height = _height; - } // arrange all workspaces: for (i = 0; i < container->children->length; ++i) { struct sway_container *child = container->children->items[i]; From 5d34e4531f03c194fd2b3717fd4cc4a802ada7aa Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 7 Apr 2018 13:21:07 -0400 Subject: [PATCH 492/522] Add basic server decorations support --- sway/server.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/server.c b/sway/server.c index dfd017985..0e98b5f92 100644 --- a/sway/server.c +++ b/sway/server.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -104,6 +105,12 @@ bool server_init(struct sway_server *server) { image->hotspot_y); } + // TODO: Integration with sway borders + struct wlr_server_decoration_manager *deco_manager = + wlr_server_decoration_manager_create(server->wl_display); + wlr_server_decoration_manager_set_default_mode( + deco_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + struct wlr_egl *egl = wlr_backend_get_egl(server->backend); wlr_linux_dmabuf_create(server->wl_display, egl); From 2b357af7eed9c7dd3a8f9b5bb589c352cabd6406 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 7 Apr 2018 14:03:30 -0400 Subject: [PATCH 493/522] Give keyboard focus to unmanaged xwayland surfaces This fixes dmenu --- include/sway/input/seat.h | 3 ++ sway/desktop/xwayland.c | 7 ++++ sway/input/input-manager.c | 2 +- sway/input/seat.c | 82 ++++++++++++++++++++++---------------- 4 files changed, 58 insertions(+), 36 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index d1cfbe4c2..c7be58b59 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -64,6 +64,9 @@ void seat_set_focus(struct sway_seat *seat, struct sway_container *container); void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp); +void seat_set_focus_surface(struct sway_seat *seat, + struct wlr_surface *surface); + void seat_set_focus_layer(struct sway_seat *seat, struct wlr_layer_surface *layer); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 6de1365d5..413dbf8b2 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -59,6 +59,13 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) { surface->ly = xsurface->y; desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true); + if (!wlr_xwayland_surface_is_unmanaged(xsurface)) { + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct wlr_xwayland *xwayland = seat->input->server->xwayland; + wlr_xwayland_set_seat(xwayland, seat->wlr_seat); + seat_set_focus_surface(seat, xsurface->surface); + } + // TODO: we don't send surface enter/leave events to xwayland unmanaged // surfaces, but xwayland doesn't support HiDPI anyway } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index f71a06e49..ae55d2a14 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -333,7 +333,7 @@ bool input_manager_has_focus(struct sway_input_manager *input, void input_manager_set_focus(struct sway_input_manager *input, struct sway_container *container) { - struct sway_seat *seat ; + struct sway_seat *seat; wl_list_for_each(seat, &input->seats, link) { seat_set_focus(seat, container); } diff --git a/sway/input/seat.c b/sway/input/seat.c index e8cf98245..b94e32913 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -84,7 +84,6 @@ static void seat_send_focus(struct sway_seat *seat, wlr_seat_keyboard_notify_enter( seat->wlr_seat, view->surface, NULL, 0, NULL); } - } static void handle_seat_container_destroy(struct wl_listener *listener, @@ -405,23 +404,29 @@ void seat_set_focus_warp(struct sway_seat *seat, container_destroy(last_ws); } } - struct sway_container *last_output = last_focus; - if (last_output && last_output->type != C_OUTPUT) { - last_output = container_parent(last_output, C_OUTPUT); - } - struct sway_container *new_output = container; - if (new_output && new_output->type != C_OUTPUT) { - new_output = container_parent(new_output, C_OUTPUT); - } - if (new_output && last_output && new_output != last_output - && config->mouse_warping && warp) { - struct wlr_output *output = new_output->sway_output->wlr_output; - double x = container->x + output->lx + container->width / 2.0; - double y = container->y + output->ly + container->height / 2.0; - if (!wlr_output_layout_contains_point( - root_container.sway_root->output_layout, - output, seat->cursor->cursor->x, seat->cursor->cursor->y)) { - wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + + if (config->mouse_warping && warp) { + struct sway_container *last_output = last_focus; + if (last_output && last_output->type != C_OUTPUT) { + last_output = container_parent(last_output, C_OUTPUT); + } + struct sway_container *new_output = container; + if (new_output && new_output->type != C_OUTPUT) { + new_output = container_parent(new_output, C_OUTPUT); + } + if (new_output && last_output && new_output != last_output) { + double x = new_output->x + container->x + + container->width / 2.0; + double y = new_output->y + container->y + + container->height / 2.0; + struct wlr_output *wlr_output = + new_output->sway_output->wlr_output; + if (!wlr_output_layout_contains_point( + root_container.sway_root->output_layout, + wlr_output, seat->cursor->cursor->x, + seat->cursor->cursor->y)) { + wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + } } } } @@ -442,6 +447,29 @@ void seat_set_focus(struct sway_seat *seat, seat_set_focus_warp(seat, container, true); } +void seat_set_focus_surface(struct sway_seat *seat, + struct wlr_surface *surface) { + if (seat->focused_layer != NULL) { + return; + } + if (seat->has_focus) { + struct sway_container *focus = seat_get_focus(seat); + if (focus->type == C_VIEW) { + wlr_seat_keyboard_clear_focus(seat->wlr_seat); + view_set_activated(focus->sway_view, false); + } + seat->has_focus = false; + } + struct wlr_keyboard *keyboard = + wlr_seat_get_keyboard(seat->wlr_seat); + if (keyboard) { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface, + keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); + } else { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface, NULL, 0, NULL); + } +} + void seat_set_focus_layer(struct sway_seat *seat, struct wlr_layer_surface *layer) { if (!layer && seat->focused_layer) { @@ -458,26 +486,10 @@ void seat_set_focus_layer(struct sway_seat *seat, } else if (!layer || seat->focused_layer == layer) { return; } - if (seat->has_focus) { - struct sway_container *focus = seat_get_focus(seat); - if (focus->type == C_VIEW) { - wlr_seat_keyboard_clear_focus(seat->wlr_seat); - view_set_activated(focus->sway_view, false); - } - } + seat_set_focus_surface(seat, layer->surface); if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { seat->focused_layer = layer; } - struct wlr_keyboard *keyboard = - wlr_seat_get_keyboard(seat->wlr_seat); - if (keyboard) { - wlr_seat_keyboard_notify_enter(seat->wlr_seat, - layer->surface, keyboard->keycodes, - keyboard->num_keycodes, &keyboard->modifiers); - } else { - wlr_seat_keyboard_notify_enter(seat->wlr_seat, - layer->surface, NULL, 0, NULL); - } } void seat_set_exclusive_client(struct sway_seat *seat, From c0f9ee7bd1fc70672dcf64a19c9fbbf5a80b12b0 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 7 Apr 2018 16:06:36 -0400 Subject: [PATCH 494/522] seat get focus inactive view --- include/sway/input/seat.h | 8 +++++-- sway/input/seat.c | 45 ++++++++++++++++++++++----------------- sway/tree/layout.c | 4 ++-- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index c7be58b59..05fff6f7d 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -87,8 +87,12 @@ struct sway_container *seat_get_focus(struct sway_seat *seat); struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container); -struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, - struct sway_container *container, enum sway_container_type type); +/** + * Descend into the focus stack to find the focus-inactive view. Useful for + * container placement when they change position in the tree. + */ +struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, + struct sway_container *container); void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config); diff --git a/sway/input/seat.c b/sway/input/seat.c index b94e32913..1a6467152 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -86,6 +86,31 @@ static void seat_send_focus(struct sway_seat *seat, } } +static struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, + struct sway_container *container, enum sway_container_type type) { + if (container->type == C_VIEW || container->children->length == 0) { + return container; + } + + struct sway_seat_container *current = NULL; + wl_list_for_each(current, &seat->focus_stack, link) { + if (current->container->type != type && type != C_TYPES) { + continue; + } + + if (container_has_child(container, current->container)) { + return current->container; + } + } + + return NULL; +} + +struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, + struct sway_container *container) { + return seat_get_focus_by_type(seat, container, C_VIEW); +} + static void handle_seat_container_destroy(struct wl_listener *listener, void *data) { struct sway_seat_container *seat_con = @@ -549,26 +574,6 @@ struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { return seat_get_focus_inactive(seat, &root_container); } -struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, - struct sway_container *container, enum sway_container_type type) { - if (container->type == C_VIEW || container->children->length == 0) { - return container; - } - - struct sway_seat_container *current = NULL; - wl_list_for_each(current, &seat->focus_stack, link) { - if (current->container->type != type && type != C_TYPES) { - continue; - } - - if (container_has_child(container, current->container)) { - return current->container; - } - } - - return NULL; -} - struct sway_container *seat_get_focus(struct sway_seat *seat) { if (!seat->has_focus) { return NULL; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index e81facc60..ce4457b13 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -872,7 +872,7 @@ struct sway_container *container_get_in_direction( } if (next->children && next->children->length) { // TODO consider floating children as well - return seat_get_focus_by_type(seat, next, C_VIEW); + return seat_get_focus_inactive_view(seat, next); } else { return next; } @@ -910,7 +910,7 @@ struct sway_container *container_get_in_direction( wlr_log(L_DEBUG, "cont %d-%p dir %i sibling %d: %p", idx, container, dir, desired, desired_con); - struct sway_container *next = seat_get_focus_by_type(seat, desired_con, C_VIEW); + struct sway_container *next = seat_get_focus_inactive_view(seat, desired_con); return next; } } From de811823b60cc33fb6a65c6f1045e9d1fb497243 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 7 Apr 2018 16:14:12 -0400 Subject: [PATCH 495/522] seat focus inactive children foreach --- include/sway/input/seat.h | 7 +++++++ sway/input/seat.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 05fff6f7d..308f5c6d1 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -94,6 +94,13 @@ struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, struct sway_container *container); +/** + * Iterate over the focus-inactive children of the container calling the function on each. + */ +void seat_focus_inactive_children_for_each(struct sway_seat *seat, + struct sway_container *container, + void (*f)(struct sway_container *container, void *data), void *data); + void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config); struct seat_config *seat_get_config(struct sway_seat *seat); diff --git a/sway/input/seat.c b/sway/input/seat.c index 1a6467152..3656d6b67 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -106,6 +106,20 @@ static struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, return NULL; } +void seat_focus_inactive_children_for_each(struct sway_seat *seat, + struct sway_container *container, + void (*f)(struct sway_container *container, void *data), void *data) { + struct sway_seat_container *current = NULL; + wl_list_for_each(current, &seat->focus_stack, link) { + if (current->container->parent == NULL) { + continue; + } + if (current->container->parent == container) { + f(current->container, data); + } + } +} + struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, struct sway_container *container) { return seat_get_focus_by_type(seat, container, C_VIEW); From 0ff22c1755a906309e08c0c45f4732c842e4636e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 7 Apr 2018 16:23:53 -0400 Subject: [PATCH 496/522] implement ipc focus stack --- sway/ipc-json.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index f9c6c90bc..6158fc29a 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -166,6 +166,11 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object } } +static void focus_inactive_children_iterator(struct sway_container *c, void *data) { + json_object *focus = data; + json_object_array_add(focus, json_object_new_int(c->id)); +} + json_object *ipc_json_describe_container(struct sway_container *c) { if (!(sway_assert(c, "Container must not be null."))) { return NULL; @@ -183,6 +188,11 @@ json_object *ipc_json_describe_container(struct sway_container *c) { json_object_object_add(object, "focused", json_object_new_boolean(focused)); + json_object *focus = json_object_new_array(); + seat_focus_inactive_children_for_each(seat, c, + focus_inactive_children_iterator, focus); + json_object_object_add(object, "focus", focus); + switch (c->type) { case C_ROOT: ipc_json_describe_root(c, object); From 9db859585e79d468ff79f41db6bc0950fb285a5a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 7 Apr 2018 18:01:18 -0400 Subject: [PATCH 497/522] container_create_notify on split --- sway/commands/split.c | 1 + sway/tree/layout.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sway/commands/split.c b/sway/commands/split.c index ab8565a95..130ed31fd 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -11,6 +11,7 @@ static struct cmd_results *do_split(int layout) { struct sway_container *con = config->handler_context.current_container; struct sway_container *parent = container_split(con, layout); + container_create_notify(parent); arrange_windows(parent, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce4457b13..ae76ca26c 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -251,6 +251,7 @@ static void workspace_rejigger(struct sway_container *ws, container_flatten(ws); container_reap_empty_recursive(original_parent); wl_signal_emit(&child->events.reparent, original_parent); + container_create_notify(new_parent); arrange_windows(ws, -1, -1); } From b24b319bdfb3e94d16950d7fdeadba990bb91a2d Mon Sep 17 00:00:00 2001 From: Bruno Pinto Date: Sun, 8 Apr 2018 00:34:12 +0100 Subject: [PATCH 498/522] Improve dependency checks --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 5a37b0e22..bf266e5f9 100644 --- a/meson.build +++ b/meson.build @@ -35,7 +35,7 @@ pangocairo = dependency('pangocairo') gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false) pixman = dependency('pixman-1') libcap = dependency('libcap') -libinput = dependency('libinput') +libinput = dependency('libinput', version: '>=1.6.0') libpam = cc.find_library('libpam') math = cc.find_library('m') rt = cc.find_library('rt') From 257a831c726e7dadb23eca224ef405f374961695 Mon Sep 17 00:00:00 2001 From: db Date: Sun, 8 Apr 2018 15:48:59 +0200 Subject: [PATCH 499/522] Use full ws->name in swaybar hotspot callback If strip_workspace_numbers option is enabled, we must preserve the right workspace name for hotspot. --- swaybar/render.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/swaybar/render.c b/swaybar/render.c index 53e578f0f..1c24e01f0 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -352,6 +352,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, struct swaybar_workspace *ws, double *x, uint32_t surface_height) { const char *name = ws->name; + const char *whole_name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); } @@ -411,7 +412,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, hotspot->height = height; hotspot->callback = workspace_hotspot_callback; hotspot->destroy = free; - hotspot->data = strdup(name); + hotspot->data = strdup(whole_name); wl_list_insert(&output->hotspots, &hotspot->link); *x += width; From 4ba6545c650712b1ec18854fa7f94995d0176637 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 8 Apr 2018 10:04:23 -0400 Subject: [PATCH 500/522] Fixup for #1773 --- swaybar/render.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index 1c24e01f0..d2175f0a0 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -352,7 +352,6 @@ static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, struct swaybar_workspace *ws, double *x, uint32_t surface_height) { const char *name = ws->name; - const char *whole_name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); } @@ -412,7 +411,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, hotspot->height = height; hotspot->callback = workspace_hotspot_callback; hotspot->destroy = free; - hotspot->data = strdup(whole_name); + hotspot->data = strdup(ws->name); wl_list_insert(&output->hotspots, &hotspot->link); *x += width; From 042b80b9faef72c36451eecb5c803223fda3264a Mon Sep 17 00:00:00 2001 From: db Date: Sun, 8 Apr 2018 16:44:59 +0200 Subject: [PATCH 501/522] Add workspace_auto_back_and_forth command This is the only missing piece - other code regarding this functionality has already been ported from pre-wlroots source. --- sway/commands.c | 1 + sway/commands/ws_auto_back_and_forth.c | 12 ++++++++++++ sway/meson.build | 1 + 3 files changed, 14 insertions(+) create mode 100644 sway/commands/ws_auto_back_and_forth.c diff --git a/sway/commands.c b/sway/commands.c index 22decef36..20b8a2aa0 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -106,6 +106,7 @@ static struct cmd_handler handlers[] = { { "output", cmd_output }, { "seat", cmd_seat }, { "workspace", cmd_workspace }, + { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth }, }; static struct cmd_handler bar_handlers[] = { diff --git a/sway/commands/ws_auto_back_and_forth.c b/sway/commands/ws_auto_back_and_forth.c new file mode 100644 index 000000000..2485db350 --- /dev/null +++ b/sway/commands/ws_auto_back_and_forth.c @@ -0,0 +1,12 @@ +#include +#include +#include "sway/commands.h" + +struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1))) { + return error; + } + config->auto_back_and_forth = !strcasecmp(argv[0], "yes"); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index 1fe0f29a0..2521069fd 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -52,6 +52,7 @@ sway_sources = files( 'commands/split.c', 'commands/swaybg_command.c', 'commands/workspace.c', + 'commands/ws_auto_back_and_forth.c', 'commands/bar/activate_button.c', 'commands/bar/binding_mode_indicator.c', From 9114d3b84cf4e5ba0513a8f4d4a018a6de3d6223 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 8 Apr 2018 10:48:13 -0400 Subject: [PATCH 502/522] Implement tablet tool support --- include/sway/input/cursor.h | 4 ++- sway/input/cursor.c | 67 ++++++++++++++++++++++++++++++++----- sway/input/seat.c | 12 +++++-- 3 files changed, 72 insertions(+), 11 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 64917ce5b..8f907dcd1 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -1,6 +1,6 @@ #ifndef _SWAY_INPUT_CURSOR_H #define _SWAY_INPUT_CURSOR_H - +#include #include "sway/input/seat.h" struct sway_cursor { @@ -22,6 +22,8 @@ struct sway_cursor { struct wl_listener tool_axis; struct wl_listener tool_tip; + struct wl_listener tool_button; + uint32_t tool_buttons; struct wl_listener request_set_cursor; }; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 6db615b1d..cdded1c76 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -179,10 +179,8 @@ static void handle_cursor_motion_absolute( cursor_send_pointer_motion(cursor, event->time_msec); } -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; - +static void dispatch_cursor_button(struct sway_cursor *cursor, + uint32_t time_msec, uint32_t button, enum wlr_button_state state) { struct wlr_surface *surface = NULL; double sx, sy; struct sway_container *cont = @@ -215,8 +213,15 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { seat_set_focus(cursor->seat, cont); } - wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, - event->button, event->state); + wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, + time_msec, button, state); +} + +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; + dispatch_cursor_button(cursor, + event->time_msec, event->button, event->state); } static void handle_cursor_axis(struct wl_listener *listener, void *data) { @@ -248,13 +253,53 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { static void handle_tool_axis(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); struct wlr_event_tablet_tool_axis *event = data; - wlr_log(L_DEBUG, "TODO: handle tool axis event: %p", event); + + if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) && + (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { + wlr_cursor_warp_absolute(cursor->cursor, event->device, + event->x, event->y); + cursor_update_position(cursor); + cursor_send_pointer_motion(cursor, event->time_msec); + } else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) { + wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, -1); + cursor_update_position(cursor); + cursor_send_pointer_motion(cursor, event->time_msec); + } else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { + wlr_cursor_warp_absolute(cursor->cursor, event->device, -1, event->y); + cursor_update_position(cursor); + cursor_send_pointer_motion(cursor, event->time_msec); + } } static void handle_tool_tip(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); struct wlr_event_tablet_tool_tip *event = data; - wlr_log(L_DEBUG, "TODO: handle tool tip event: %p", event); + dispatch_cursor_button(cursor, event->time_msec, + BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ? + WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED); +} + +static void handle_tool_button(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); + struct wlr_event_tablet_tool_button *event = data; + // TODO: the user may want to configure which tool buttons are mapped to + // which simulated pointer buttons + switch (event->state) { + case WLR_BUTTON_PRESSED: + if (cursor->tool_buttons == 0) { + dispatch_cursor_button(cursor, + event->time_msec, BTN_RIGHT, event->state); + } + cursor->tool_buttons++; + break; + case WLR_BUTTON_RELEASED: + if (cursor->tool_buttons == 1) { + dispatch_cursor_button(cursor, + event->time_msec, BTN_RIGHT, event->state); + } + cursor->tool_buttons--; + break; + } } static void handle_request_set_cursor(struct wl_listener *listener, @@ -332,6 +377,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { &cursor->touch_motion); cursor->touch_motion.notify = handle_touch_motion; + // TODO: tablet protocol support + // Note: We should emulate pointer events for clients that don't support the + // tablet protocol when the time comes wl_signal_add(&wlr_cursor->events.tablet_tool_axis, &cursor->tool_axis); cursor->tool_axis.notify = handle_tool_axis; @@ -339,6 +387,9 @@ 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(&wlr_cursor->events.tablet_tool_button, &cursor->tool_button); + cursor->tool_button.notify = handle_tool_button; + 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/seat.c b/sway/input/seat.c index b94e32913..c34da5e50 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -245,6 +245,12 @@ static void seat_configure_keyboard(struct sway_seat *seat, } } +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); +} + static struct sway_seat_device *seat_get_device(struct sway_seat *seat, struct sway_input_device *input_device) { struct sway_seat_device *seat_device = NULL; @@ -272,9 +278,11 @@ void seat_configure_device(struct sway_seat *seat, case WLR_INPUT_DEVICE_KEYBOARD: seat_configure_keyboard(seat, seat_device); break; - case WLR_INPUT_DEVICE_TOUCH: - case WLR_INPUT_DEVICE_TABLET_PAD: case WLR_INPUT_DEVICE_TABLET_TOOL: + seat_configure_tablet_tool(seat, seat_device); + break; + case WLR_INPUT_DEVICE_TABLET_PAD: + case WLR_INPUT_DEVICE_TOUCH: wlr_log(L_DEBUG, "TODO: configure other devices"); break; } From 9570e37016ff6d2d6fa9ac85b576b8cc17f04e8c Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 8 Apr 2018 11:19:14 -0400 Subject: [PATCH 503/522] Update for wlroots#850 --- sway/server.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/server.c b/sway/server.c index 0e98b5f92..c1125f142 100644 --- a/sway/server.c +++ b/sway/server.c @@ -111,8 +111,7 @@ bool server_init(struct sway_server *server) { wlr_server_decoration_manager_set_default_mode( deco_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); - struct wlr_egl *egl = wlr_backend_get_egl(server->backend); - wlr_linux_dmabuf_create(server->wl_display, egl); + wlr_linux_dmabuf_create(server->wl_display, renderer); server->socket = wl_display_add_socket_auto(server->wl_display); if (!server->socket) { From 46280460a58e6517b81e55eb0b027ad12aaed834 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 8 Apr 2018 11:34:38 -0400 Subject: [PATCH 504/522] push all parents of focused container in focus stack --- sway/input/seat.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 3656d6b67..9f44955c3 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -413,10 +413,23 @@ void seat_set_focus_warp(struct sway_seat *seat, if (container) { struct sway_seat_container *seat_con = seat_container_from_container(seat, container); - if (!seat_con) { + if (seat_con == NULL) { return; } + // put all the anscestors of this container on top of the focus stack + struct sway_seat_container *parent = + seat_container_from_container(seat, + seat_con->container->parent); + while (parent) { + wl_list_remove(&parent->link); + wl_list_insert(&seat->focus_stack, &parent->link); + + parent = + seat_container_from_container(seat, + parent->container->parent); + } + wl_list_remove(&seat_con->link); wl_list_insert(&seat->focus_stack, &seat_con->link); From 5ebc99253ae04ee31d31b3f01bc0ce35f6ea5979 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 8 Apr 2018 11:43:18 -0400 Subject: [PATCH 505/522] Use wlr_surface_point_accepts_input for unmanaged surfaces --- sway/input/cursor.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index cdded1c76..4bcf72fce 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -52,17 +52,13 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { struct wlr_xwayland_surface *xsurface = unmanaged_surface->wlr_xwayland_surface; - struct wlr_box box = { - .x = unmanaged_surface->lx, - .y = unmanaged_surface->ly, - .width = xsurface->width, - .height = xsurface->height, - }; - if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { + double _sx = cursor->x - unmanaged_surface->lx; + double _sy = cursor->y - unmanaged_surface->ly; + if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { *surface = xsurface->surface; - *sx = cursor->x - box.x; - *sy = cursor->y - box.y; + *sx = _sx; + *sy = _sy; return NULL; } } From 70b33342fec0e0cc720cbb62a059c40a34c5314f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 8 Apr 2018 12:13:09 -0400 Subject: [PATCH 506/522] criteria match containers --- sway/criteria.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/criteria.c b/sway/criteria.c index 5fee18881..53461c74a 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -273,7 +273,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) { - if (cont->type != C_VIEW) { + if (cont->type < C_CONTAINER) { return false; } int matches = 0; From 9c5a88a7bd57dc9710c0fe779d8403a87ddc0b6a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 8 Apr 2018 12:42:56 -0400 Subject: [PATCH 507/522] Fix cursor motion issues Use only one canonical cursor x/y position and send cursor enter when mouse is warped. Tangentally related to #1714 --- include/sway/input/cursor.h | 2 +- sway/input/cursor.c | 28 ++++++++-------------------- sway/input/seat.c | 3 +++ 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 8f907dcd1..daf7d4eef 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -8,7 +8,6 @@ struct sway_cursor { struct wlr_cursor *cursor; struct wlr_xcursor_manager *xcursor_manager; - double x, y; struct wl_client *image_client; struct wl_listener motion; @@ -30,5 +29,6 @@ struct sway_cursor { void sway_cursor_destroy(struct sway_cursor *cursor); struct sway_cursor *sway_cursor_create(struct sway_seat *seat); +void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time); #endif diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 4bcf72fce..0df015043 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -14,14 +14,6 @@ #include "sway/tree/view.h" #include "wlr-layer-shell-unstable-v1-protocol.h" -static void cursor_update_position(struct sway_cursor *cursor) { - double x = cursor->cursor->x; - double y = cursor->cursor->y; - - cursor->x = x; - cursor->y = y; -} - static struct wlr_surface *layer_surface_at(struct sway_output *output, struct wl_list *layer, double ox, double oy, double *sx, double *sy) { struct sway_layer_surface *sway_layer; @@ -53,8 +45,8 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, struct wlr_xwayland_surface *xsurface = unmanaged_surface->wlr_xwayland_surface; - double _sx = cursor->x - unmanaged_surface->lx; - double _sy = cursor->y - unmanaged_surface->ly; + double _sx = cursor->cursor->x - unmanaged_surface->lx; + double _sy = cursor->cursor->y - unmanaged_surface->ly; if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { *surface = xsurface->surface; *sx = _sx; @@ -67,12 +59,13 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, struct wlr_output_layout *output_layout = root_container.sway_root->output_layout; struct wlr_output *wlr_output = - wlr_output_layout_output_at(output_layout, cursor->x, cursor->y); + wlr_output_layout_output_at(output_layout, + cursor->cursor->x, cursor->cursor->y); if (wlr_output == NULL) { return NULL; } struct sway_output *output = wlr_output->data; - double ox = cursor->x, oy = cursor->y; + double ox = cursor->cursor->x, oy = cursor->cursor->y; wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); // find the focused workspace on the output for this seat @@ -97,7 +90,8 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, } struct sway_container *c; - if ((c = container_at(ws, cursor->x, cursor->y, surface, sx, sy))) { + if ((c = container_at(ws, cursor->cursor->x, cursor->cursor->y, + surface, sx, sy))) { return c; } @@ -124,8 +118,7 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, return output->swayc; } -static void cursor_send_pointer_motion(struct sway_cursor *cursor, - uint32_t time) { +void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time) { struct wlr_seat *seat = cursor->seat->wlr_seat; struct wlr_surface *surface = NULL; double sx, sy; @@ -161,7 +154,6 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { struct wlr_event_pointer_motion *event = data; wlr_cursor_move(cursor->cursor, event->device, event->delta_x, event->delta_y); - cursor_update_position(cursor); cursor_send_pointer_motion(cursor, event->time_msec); } @@ -171,7 +163,6 @@ static void handle_cursor_motion_absolute( wl_container_of(listener, cursor, motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); - cursor_update_position(cursor); cursor_send_pointer_motion(cursor, event->time_msec); } @@ -254,15 +245,12 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); - cursor_update_position(cursor); cursor_send_pointer_motion(cursor, event->time_msec); } else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) { wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, -1); - cursor_update_position(cursor); cursor_send_pointer_motion(cursor, event->time_msec); } else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { wlr_cursor_warp_absolute(cursor->cursor, event->device, -1, event->y); - cursor_update_position(cursor); cursor_send_pointer_motion(cursor, event->time_msec); } } diff --git a/sway/input/seat.c b/sway/input/seat.c index c34da5e50..d9b42828f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -434,6 +434,9 @@ void seat_set_focus_warp(struct sway_seat *seat, wlr_output, seat->cursor->cursor->x, seat->cursor->cursor->y)) { wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + cursor_send_pointer_motion(seat->cursor, now.tv_nsec / 1000); } } } From 16e363e3e23e11674d06324efb4374320de40e63 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 8 Apr 2018 13:49:11 -0400 Subject: [PATCH 508/522] Fix swaybar HiDPI rounding issue --- swaybar/render.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index d2175f0a0..28296f311 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -37,8 +37,9 @@ static uint32_t render_status_line_error(cairo_t *cairo, &text_width, &text_height, output->scale, false, "%s", error); uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } *x -= text_width + margin; @@ -46,7 +47,7 @@ static uint32_t render_status_line_error(cairo_t *cairo, cairo_move_to(cairo, *x, (int)floor(text_y)); pango_printf(cairo, config->font, output->scale, false, "%s", error); *x -= margin; - return ideal_height / output->scale; + return surface_height; } static uint32_t render_status_line_text(cairo_t *cairo, @@ -69,8 +70,9 @@ static uint32_t render_status_line_text(cairo_t *cairo, int margin = 3 * output->scale; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } *x -= text_width + margin; @@ -79,7 +81,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, pango_printf(cairo, config->font, output->scale, config->pango_markup, "%s", text); *x -= margin; - return ideal_height / output->scale; + return surface_height; } static void render_sharp_line(cairo_t *cairo, uint32_t color, @@ -137,8 +139,9 @@ static uint32_t render_status_block(cairo_t *cairo, double block_width = width; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } *x -= width; @@ -249,7 +252,7 @@ static uint32_t render_status_block(cairo_t *cairo, cairo_stroke(cairo); } } - return ideal_height / output->scale; + return surface_height; } static uint32_t render_status_line_i3bar(cairo_t *cairo, @@ -291,7 +294,6 @@ static uint32_t render_status_line(cairo_t *cairo, static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, const char *mode, double x, uint32_t surface_height) { - uint32_t height = surface_height * output->scale; int text_width, text_height; @@ -304,8 +306,9 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; @@ -327,7 +330,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, cairo_set_source_u32(cairo, config->colors.binding_mode.text); cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); pango_printf(cairo, config->font, output->scale, true, "%s", mode); - return ideal_height / output->scale; + return surface_height; } static const char *strip_workspace_number(const char *ws_name) { @@ -379,8 +382,9 @@ static uint32_t render_workspace_button(cairo_t *cairo, uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; @@ -415,7 +419,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, wl_list_insert(&output->hotspots, &hotspot->link); *x += width; - return height / output->scale; + return surface_height; } static uint32_t render_to_cairo(cairo_t *cairo, @@ -484,8 +488,7 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { } if (height != output->height) { // Reconfigure surface - zwlr_layer_surface_v1_set_size( - output->layer_surface, 0, height); + zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); // TODO: this could infinite loop if the compositor assigns us a // different height than what we asked for From 8ecd89b7efad46efa17c3275c5daa3de5943254b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 8 Apr 2018 14:22:20 -0400 Subject: [PATCH 509/522] address feedback --- sway/criteria.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/criteria.c b/sway/criteria.c index 53461c74a..22e9a49b6 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -273,7 +273,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) { - if (cont->type < C_CONTAINER) { + if (cont->type != C_CONTAINER && cont->type != C_VIEW) { return false; } int matches = 0; From 0e3ddf255ef56b7fe2b868232b80d04ea961120b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 8 Apr 2018 14:15:13 -0400 Subject: [PATCH 510/522] 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 diff --git a/include/sway/commands.h b/include/sway/commands.h index edb5a2135..bc5d5412f 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 91f772b5b..ed49fbbd2 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 20b8a2aa0..55929659b 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 000000000..60e4608e9 --- /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 c4f6211da..5e657c439 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 d9b42828f..7b01fe880 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 2521069fd..d0730296d 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 0603616bb..057253606 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 ~~~~~~~~~~~~~~~~~~~~~~ From e7771c507a6f482cc66c482d167af2d2beaff31b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 8 Apr 2018 15:32:19 -0400 Subject: [PATCH 511/522] 80char --- include/sway/input/seat.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 308f5c6d1..ff76841ef 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -95,7 +95,8 @@ struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, struct sway_container *container); /** - * Iterate over the focus-inactive children of the container calling the function on each. + * Iterate over the focus-inactive children of the container calling the + * function on each. */ void seat_focus_inactive_children_for_each(struct sway_seat *seat, struct sway_container *container, From bac65078a28323ced0d25d7decea783c157028d4 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Mon, 9 Apr 2018 17:25:39 +1000 Subject: [PATCH 512/522] Fix buffer issues in swaybar status line. --- swaybar/i3bar.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index ed134a016..6f67ba3aa 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -125,9 +125,12 @@ bool i3bar_handle_readable(struct status_line *status) { status_error(status, "[failed to allocate buffer]"); return -1; } + state->current_node += new_buffer - state->buffer; + cur += new_buffer - state->buffer; state->buffer = new_buffer; } + cur[n] = '\0'; bool redraw = false; while (*cur) { if (state->nodes[state->depth] == JSON_NODE_STRING) { From ac3be29517ead2188e43ab1bdb8de31f17633c94 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 9 Apr 2018 08:07:54 -0400 Subject: [PATCH 513/522] Fix some more bugs --- swaybar/i3bar.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 6f67ba3aa..923ad7558 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -113,8 +113,9 @@ bool i3bar_handle_readable(struct status_line *status) { char *cur = &state->buffer[state->buffer_index]; ssize_t n = read(status->read_fd, cur, state->buffer_size - state->buffer_index); - if (n == 0) { - return 0; + if (n == -1) { + status_error(status, "[failed to read from status command]"); + return false; } if (n == (ssize_t)(state->buffer_size - state->buffer_index)) { @@ -123,7 +124,7 @@ bool i3bar_handle_readable(struct status_line *status) { if (!new_buffer) { free(state->buffer); status_error(status, "[failed to allocate buffer]"); - return -1; + return true; } state->current_node += new_buffer - state->buffer; cur += new_buffer - state->buffer; From 63b2543749e57e4340f539a2742fd13e89d96d94 Mon Sep 17 00:00:00 2001 From: db Date: Sun, 8 Apr 2018 22:49:06 +0200 Subject: [PATCH 514/522] Add workspace_auto_back_and_forth for move cmd --- sway/commands/move.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index 15a5ebc49..a5273ba43 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -1,3 +1,4 @@ +#define _XOPEN_SOURCE 500 #include #include #include @@ -63,18 +64,29 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, "Can only move containers and views."); } struct sway_container *ws; - const char *num_name = NULL; char *ws_name = NULL; if (argc == 5 && strcasecmp(argv[3], "number") == 0) { // move "container to workspace number x" - num_name = argv[4]; - ws = workspace_by_number(num_name); + ws_name = strdup(argv[4]); + ws = workspace_by_number(ws_name); } else { ws_name = join_args(argv + 3, argc - 3); ws = workspace_by_name(ws_name); } + + if (config->auto_back_and_forth && prev_workspace_name) { + // auto back and forth move + struct sway_container *curr_ws = container_parent(current, C_WORKSPACE); + if (curr_ws->name && strcmp(curr_ws->name, ws_name) == 0) { + // if target workspace is the current one + free(ws_name); + ws_name = strdup(prev_workspace_name); + ws = workspace_by_name(ws_name); + } + } + if (!ws) { - ws = workspace_create(NULL, ws_name ? ws_name : num_name); + ws = workspace_create(NULL, ws_name); } free(ws_name); struct sway_container *old_parent = current->parent; From c38de1672255e9906623c133598ac7fded10640a Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 10 Apr 2018 13:38:15 +1000 Subject: [PATCH 515/522] Fix swaybar output config. --- swaybar/bar.c | 70 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/swaybar/bar.c b/swaybar/bar.c index f1a701b91..d51c4ec71 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -264,6 +264,19 @@ struct wl_output_listener output_listener = { .scale = output_scale, }; +static bool bar_uses_output(struct swaybar *bar, size_t output_index) { + if (bar->config->all_outputs) { + return true; + } + struct config_output *coutput; + wl_list_for_each(coutput, &bar->config->outputs, link) { + if (coutput->index == output_index) { + return true; + } + } + return false; +} + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct swaybar *bar = data; @@ -278,19 +291,22 @@ static void handle_global(void *data, struct wl_registry *registry, bar->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { - static size_t index = 0; - struct swaybar_output *output = - calloc(1, sizeof(struct swaybar_output)); - output->bar = bar; - output->output = wl_registry_bind(registry, name, - &wl_output_interface, 3); - wl_output_add_listener(output->output, &output_listener, output); - output->scale = 1; - output->index = index++; - output->wl_name = name; - wl_list_init(&output->workspaces); - wl_list_init(&output->hotspots); - wl_list_insert(&bar->outputs, &output->link); + static size_t output_index = 0; + if (bar_uses_output(bar, output_index)) { + struct swaybar_output *output = + calloc(1, sizeof(struct swaybar_output)); + output->bar = bar; + output->output = wl_registry_bind(registry, name, + &wl_output_interface, 3); + wl_output_add_listener(output->output, &output_listener, output); + output->scale = 1; + output->index = output_index; + output->wl_name = name; + wl_list_init(&output->workspaces); + wl_list_init(&output->hotspots); + wl_list_insert(&bar->outputs, &output->link); + } + ++output_index; } 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); @@ -362,26 +378,24 @@ void bar_setup(struct swaybar *bar, pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); assert(pointer->cursor_surface); - // TODO: we might not necessarily be meant to do all of the outputs wl_list_for_each(output, &bar->outputs, link) { struct config_output *coutput; wl_list_for_each(coutput, &bar->config->outputs, link) { - if (coutput->index != output->index) { - continue; + if (coutput->index == output->index) { + output->name = strdup(coutput->name); + break; } - output->name = strdup(coutput->name); - output->surface = wl_compositor_create_surface(bar->compositor); - assert(output->surface); - 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); - break; } + output->surface = wl_compositor_create_surface(bar->compositor); + assert(output->surface); + 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); } ipc_get_workspaces(bar); render_all_frames(bar); From 1a0d367f227fddd026ddf2a1bd21c5edbb111b00 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 10 Apr 2018 16:08:08 +1000 Subject: [PATCH 516/522] Fix swaybar not showing all status blocks. --- swaybar/render.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index 28296f311..8681532a1 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -154,15 +154,14 @@ static uint32_t render_status_block(cairo_t *cairo, block_width += block->border_right + margin; } - int sep_width; + int sep_width, sep_height; if (!edge) { if (config->sep_symbol) { - int _height; - get_text_size(cairo, config->font, &sep_width, &_height, + get_text_size(cairo, config->font, &sep_width, &sep_height, output->scale, false, "%s", config->sep_symbol); - uint32_t _ideal_height = _height + ws_vertical_padding * 2; - if ((uint32_t)_height < _ideal_height / output->scale) { - return _height / output->scale; + uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; + if (_ideal_height * output->scale > height) { + return _ideal_height; } if (sep_width > block->separator_block_width) { block->separator_block_width = sep_width + margin * 2; @@ -240,7 +239,7 @@ static uint32_t render_status_block(cairo_t *cairo, } if (config->sep_symbol) { offset = pos + (block->separator_block_width - sep_width) / 2; - cairo_move_to(cairo, offset, margin); + cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0); pango_printf(cairo, config->font, output->scale, false, "%s", config->sep_symbol); } else { From 1edb2bd89254069066bab51d316962e85d4445b4 Mon Sep 17 00:00:00 2001 From: Danny Bautista Date: Tue, 10 Apr 2018 11:32:37 -0400 Subject: [PATCH 517/522] Implement cursor event simulation with sway commands. --- include/sway/commands.h | 3 +- include/sway/input/cursor.h | 1 + sway/commands.c | 1 + sway/commands/seat.c | 2 + sway/commands/seat/cursor.c | 83 +++++++++++++++++++++++++++++++++++++ sway/input/cursor.c | 2 +- sway/meson.build | 1 + 7 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 sway/commands/seat/cursor.c diff --git a/include/sway/commands.h b/include/sway/commands.h index bc5d5412f..dbebaa491 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -204,8 +204,9 @@ 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 seat_cmd_fallback; +sway_cmd seat_cmd_cursor; sway_cmd cmd_ipc_cmd; sway_cmd cmd_ipc_events; diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index daf7d4eef..30169aa13 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -30,5 +30,6 @@ struct sway_cursor { void sway_cursor_destroy(struct sway_cursor *cursor); struct sway_cursor *sway_cursor_create(struct sway_seat *seat); void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time); +void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, uint32_t button, enum wlr_button_state state); #endif diff --git a/sway/commands.c b/sway/commands.c index 55929659b..54d84450e 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -203,6 +203,7 @@ static struct cmd_handler input_handlers[] = { // must be in order for the bsearch static struct cmd_handler seat_handlers[] = { { "attach", seat_cmd_attach }, + { "cursor", seat_cmd_cursor }, { "fallback", seat_cmd_fallback }, }; diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 819b769cd..5916015fa 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -40,6 +40,8 @@ struct cmd_results *cmd_seat(int argc, char **argv) { struct cmd_results *res; if (strcasecmp("attach", argv[1]) == 0) { res = seat_cmd_attach(argc_new, argv_new); + } else if (strcasecmp("cursor", argv[1]) == 0) { + res = seat_cmd_cursor(argc_new, argv_new); } else if (strcasecmp("fallback", argv[1]) == 0) { res = seat_cmd_fallback(argc_new, argv_new); } else { diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c new file mode 100644 index 000000000..2f2aa5ca0 --- /dev/null +++ b/sway/commands/seat/cursor.c @@ -0,0 +1,83 @@ +#define _XOPEN_SOURCE 700 +#ifdef __linux__ +#include +#elif __FreeBSD__ +#include +#endif + +#include +#include +#include "sway/commands.h" +#include "sway/input/cursor.h" + +static struct cmd_results *press_or_release(struct sway_cursor *cursor, char *action, char *button_str); + +static const char *expected_syntax = "Expected 'cursor ' or " + "'cursor ' or " + "'curor '"; + +struct cmd_results *seat_cmd_cursor(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "cursor", EXPECTED_AT_LEAST, 2))) { + return error; + } + struct sway_seat *seat = config->handler_context.seat; + if (!seat) { + return cmd_results_new(CMD_FAILURE, "cursor", "No seat defined"); + } + + struct sway_cursor *cursor = seat->cursor; + + if (strcasecmp(argv[0], "move") == 0) { + if (argc < 3) { + return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); + } + int delta_x = strtol(argv[1], NULL, 10); + int delta_y = strtol(argv[2], NULL, 10); + wlr_cursor_move(cursor->cursor, NULL, delta_x, delta_y); + cursor_send_pointer_motion(cursor, 1); + } else if (strcasecmp(argv[0], "set") == 0) { + if (argc < 3) { + return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); + } + // map absolute coords (0..1,0..1) to root container coords + float x = strtof(argv[1], NULL) / root_container.width; + float y = strtof(argv[2], NULL) / root_container.height; + wlr_cursor_warp_absolute(cursor->cursor, NULL, x, y); + cursor_send_pointer_motion(cursor, 0); + } else { + if (argc < 2) { + return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); + } + if ((error = press_or_release(cursor, argv[0], argv[1]))) { + return error; + } + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +static struct cmd_results *press_or_release(struct sway_cursor *cursor, char *action, char *button_str) { + enum wlr_button_state state; + uint32_t button; + if (strcasecmp(action, "press") == 0) { + state = WLR_BUTTON_PRESSED; + } else if (strcasecmp(action, "release") == 0) { + state = WLR_BUTTON_RELEASED; + } else { + return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); + } + + if (strcasecmp(button_str, "left") == 0) { + button = BTN_LEFT; + } else if (strcasecmp(button_str, "right") == 0) { + button = BTN_RIGHT; + } else { + button = strtol(button_str, NULL, 10); + if (button == 0) { + return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); + } + } + dispatch_cursor_button(cursor, 1, button, state); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 0df015043..15a61cbf8 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -166,7 +166,7 @@ static void handle_cursor_motion_absolute( cursor_send_pointer_motion(cursor, event->time_msec); } -static void dispatch_cursor_button(struct sway_cursor *cursor, +void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, uint32_t button, enum wlr_button_state state) { struct wlr_surface *surface = NULL; double sx, sy; diff --git a/sway/meson.build b/sway/meson.build index d0730296d..9e55e335f 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -47,6 +47,7 @@ sway_sources = files( 'commands/resize.c', 'commands/seat.c', 'commands/seat/attach.c', + 'commands/seat/cursor.c', 'commands/seat/fallback.c', 'commands/set.c', 'commands/split.c', From c355d680e9a009e09e027a79b27ad21763fa67ea Mon Sep 17 00:00:00 2001 From: Danny Bautista Date: Tue, 10 Apr 2018 15:40:27 -0400 Subject: [PATCH 518/522] Clean up cursor simulation code. --- include/sway/input/cursor.h | 3 ++- sway/commands/seat/cursor.c | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 30169aa13..fcd94437c 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -30,6 +30,7 @@ struct sway_cursor { void sway_cursor_destroy(struct sway_cursor *cursor); struct sway_cursor *sway_cursor_create(struct sway_seat *seat); void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time); -void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, uint32_t button, enum wlr_button_state state); +void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, + uint32_t button, enum wlr_button_state state); #endif diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c index 2f2aa5ca0..5dad97f1a 100644 --- a/sway/commands/seat/cursor.c +++ b/sway/commands/seat/cursor.c @@ -10,7 +10,8 @@ #include "sway/commands.h" #include "sway/input/cursor.h" -static struct cmd_results *press_or_release(struct sway_cursor *cursor, char *action, char *button_str); +static struct cmd_results *press_or_release(struct sway_cursor *cursor, + char *action, char *button_str, uint32_t time); static const char *expected_syntax = "Expected 'cursor ' or " "'cursor ' or " @@ -28,6 +29,10 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) { struct sway_cursor *cursor = seat->cursor; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + uint32_t time = now.tv_nsec / 1000; + if (strcasecmp(argv[0], "move") == 0) { if (argc < 3) { return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); @@ -35,7 +40,7 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) { int delta_x = strtol(argv[1], NULL, 10); int delta_y = strtol(argv[2], NULL, 10); wlr_cursor_move(cursor->cursor, NULL, delta_x, delta_y); - cursor_send_pointer_motion(cursor, 1); + cursor_send_pointer_motion(cursor, time); } else if (strcasecmp(argv[0], "set") == 0) { if (argc < 3) { return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); @@ -44,12 +49,12 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) { float x = strtof(argv[1], NULL) / root_container.width; float y = strtof(argv[2], NULL) / root_container.height; wlr_cursor_warp_absolute(cursor->cursor, NULL, x, y); - cursor_send_pointer_motion(cursor, 0); + cursor_send_pointer_motion(cursor, time); } else { if (argc < 2) { return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); } - if ((error = press_or_release(cursor, argv[0], argv[1]))) { + if ((error = press_or_release(cursor, argv[0], argv[1], time))) { return error; } } @@ -57,7 +62,8 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -static struct cmd_results *press_or_release(struct sway_cursor *cursor, char *action, char *button_str) { +static struct cmd_results *press_or_release(struct sway_cursor *cursor, + char *action, char *button_str, uint32_t time) { enum wlr_button_state state; uint32_t button; if (strcasecmp(action, "press") == 0) { @@ -78,6 +84,6 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor, char *ac return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); } } - dispatch_cursor_button(cursor, 1, button, state); + dispatch_cursor_button(cursor, time, button, state); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From c53b2edd41babec9c5d214eab383107509f20353 Mon Sep 17 00:00:00 2001 From: Danny Bautista Date: Tue, 10 Apr 2018 15:44:02 -0400 Subject: [PATCH 519/522] Add documentation for seat cursor command. --- sway/sway.5.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/sway.5.txt b/sway/sway.5.txt index 59c3295aa..039753493 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -328,6 +328,13 @@ The default colors are: the named seat, and _}_ on its own line will close the block. See **sway-input**(5) for details. +**seat** cursor :: + Move cursor relatively to current position or set to absolute screen position. + A value of 0 causes the axis to be ignored in both commands. + +**seat** cursor :: + Simulate press of mouse button specified by left, right, or numerical code. + **kill**:: Kills (force-closes) the currently-focused container and all of its children. From 39e33193940d008310341beb44697c4c61ef5752 Mon Sep 17 00:00:00 2001 From: db Date: Tue, 10 Apr 2018 22:01:22 +0200 Subject: [PATCH 520/522] fix swaybar ipc handling Swap return with break in IPC_EVENT_WORKSPACE case to free resp. Change default return value to true. This causes IPC_EVENT_MODE changes to be rendered instantly. --- swaybar/ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swaybar/ipc.c b/swaybar/ipc.c index e6231bd2a..ed5d9a315 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -331,7 +331,7 @@ bool handle_ipc_readable(struct swaybar *bar) { switch (resp->type) { case IPC_EVENT_WORKSPACE: ipc_get_workspaces(bar); - return true; + break; case IPC_EVENT_MODE: { json_object *result = json_tokener_parse(resp->payload); if (!result) { @@ -367,5 +367,5 @@ bool handle_ipc_readable(struct swaybar *bar) { return false; } free_ipc_response(resp); - return false; + return true; } From 7dfc0409ebd14f256294118ded769cf4df56e758 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 11 Apr 2018 08:34:21 +1000 Subject: [PATCH 521/522] Check height in surface local coordinates and rename some variables. --- swaybar/render.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index 8681532a1..3fd8da0b3 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -159,9 +159,10 @@ static uint32_t render_status_block(cairo_t *cairo, if (config->sep_symbol) { get_text_size(cairo, config->font, &sep_width, &sep_height, output->scale, false, "%s", config->sep_symbol); - uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; - if (_ideal_height * output->scale > height) { - return _ideal_height; + uint32_t _ideal_surface_height = ws_vertical_padding * 2 + + sep_height; + if (_ideal_surface_height > surface_height) { + return _ideal_surface_height; } if (sep_width > block->separator_block_width) { block->separator_block_width = sep_width + margin * 2; From 5785170421dc38437acde8bb61068cd16fda716c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 10 Apr 2018 22:18:54 -0400 Subject: [PATCH 522/522] Fix separator height calculation Fixes #1796 Also rearranged this code to more closely mirror the similar code above so future discrepancies are easier to spot. --- swaybar/render.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index 3fd8da0b3..26248d350 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -159,9 +159,9 @@ static uint32_t render_status_block(cairo_t *cairo, if (config->sep_symbol) { get_text_size(cairo, config->font, &sep_width, &sep_height, output->scale, false, "%s", config->sep_symbol); - uint32_t _ideal_surface_height = ws_vertical_padding * 2 - + sep_height; - if (_ideal_surface_height > surface_height) { + uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; + uint32_t _ideal_surface_height = _ideal_height / output->scale; + if (surface_height < _ideal_surface_height) { return _ideal_surface_height; } if (sep_width > block->separator_block_width) {