diff --git a/common/util.c b/common/util.c index 199f3ee1c..5d4c0673d 100644 --- a/common/util.c +++ b/common/util.c @@ -80,6 +80,12 @@ enum movement_unit parse_movement_unit(const char *unit) { int parse_movement_amount(int argc, char **argv, struct movement_amount *amount) { + if (!sway_assert(argc > 0, "Expected args in parse_movement_amount")) { + amount->amount = 0; + amount->unit = MOVEMENT_UNIT_INVALID; + return 0; + } + char *err; amount->amount = (int)strtol(argv[0], &err, 10); if (*err) { diff --git a/include/sway/desktop.h b/include/sway/desktop.h index c969a76be..7f2f5b3eb 100644 --- a/include/sway/desktop.h +++ b/include/sway/desktop.h @@ -1,4 +1,4 @@ -#include +#include struct sway_container; struct sway_view; diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 7d66e6997..853f88386 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "sway/input/seat.h" #include "config.h" diff --git a/include/sway/input/text_input.h b/include/sway/input/text_input.h index 37744266d..c70fd935b 100644 --- a/include/sway/input/text_input.h +++ b/include/sway/input/text_input.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include "sway/input/seat.h" /** diff --git a/include/sway/layers.h b/include/sway/layers.h index 224dc5e68..f85084934 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -1,7 +1,7 @@ #ifndef _SWAY_LAYERS_H #define _SWAY_LAYERS_H #include -#include +#include #include enum layer_parent { @@ -25,6 +25,8 @@ struct sway_layer_surface { bool mapped; struct wlr_box extent; enum zwlr_layer_shell_v1_layer layer; + + struct wl_list subsurfaces; }; struct sway_layer_popup { @@ -44,6 +46,7 @@ struct sway_layer_popup { struct sway_layer_subsurface { struct wlr_subsurface *wlr_subsurface; struct sway_layer_surface *layer_surface; + struct wl_list link; struct wl_listener map; struct wl_listener unmap; diff --git a/include/sway/surface.h b/include/sway/surface.h index 4da96c027..fb1cd7758 100644 --- a/include/sway/surface.h +++ b/include/sway/surface.h @@ -1,6 +1,6 @@ #ifndef _SWAY_SURFACE_H #define _SWAY_SURFACE_H -#include +#include struct sway_surface { struct wlr_surface *wlr_surface; diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 057611508..a5f74de94 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -2,7 +2,7 @@ #define _SWAY_CONTAINER_H #include #include -#include +#include #include "list.h" #include "sway/tree/node.h" diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 447dce84b..049ef46fb 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -1,7 +1,7 @@ #ifndef _SWAY_VIEW_H #define _SWAY_VIEW_H #include -#include +#include #include "config.h" #if HAVE_XWAYLAND #include diff --git a/meson.build b/meson.build index 4da9403b0..711830073 100644 --- a/meson.build +++ b/meson.build @@ -35,6 +35,15 @@ if is_freebsd add_project_arguments('-D_C11_SOURCE', language: 'c') endif +# Execute the wlroots subproject, if any +wlroots_version = ['>=0.16.0', '<0.17.0'] +subproject( + 'wlroots', + default_options: ['examples=false'], + required: false, + version: wlroots_version, +) + jsonc = dependency('json-c', version: '>=0.13') pcre = dependency('libpcre') wayland_server = dependency('wayland-server', version: '>=1.20.0') @@ -42,6 +51,7 @@ wayland_client = dependency('wayland-client') wayland_cursor = dependency('wayland-cursor') wayland_egl = dependency('wayland-egl') wayland_protos = dependency('wayland-protocols', version: '>=1.24') +wlroots = dependency('wlroots', version: wlroots_version) xkbcommon = dependency('xkbcommon') cairo = dependency('cairo') pango = dependency('pango') @@ -60,20 +70,6 @@ fish_comp = dependency('fish', required: false) math = cc.find_library('m') rt = cc.find_library('rt') -# Try first to find wlroots as a subproject, then as a system dependency -wlroots_version = ['>=0.16.0', '<0.17.0'] -wlroots_proj = subproject( - 'wlroots', - default_options: ['examples=false'], - required: false, - version: wlroots_version, -) -if wlroots_proj.found() - wlroots = wlroots_proj.get_variable('wlroots') -else - wlroots = dependency('wlroots', version: wlroots_version) -endif - wlroots_features = { 'xwayland': false, } @@ -92,15 +88,22 @@ if get_option('sd-bus-provider') == 'auto' if not get_option('tray').disabled() assert(get_option('auto_features').auto(), 'sd-bus-provider must not be set to auto since auto_features != auto') endif - sdbus = dependency(['libsystemd', 'libelogind', 'basu'], - required: get_option('tray'), + sdbus = dependency(['libsystemd', 'libelogind'], + required: false, version: '>=239', ) + if not sdbus.found() + sdbus = dependency('basu', required: false) + endif else sdbus = dependency(get_option('sd-bus-provider'), required: get_option('tray')) endif -have_tray = sdbus.found() +tray_deps_found = sdbus.found() +if get_option('tray').enabled() and not tray_deps_found + error('Building with -Dtray=enabled, but sd-bus has not been not found') +endif +have_tray = (not get_option('tray').disabled()) and tray_deps_found conf_data = configuration_data() @@ -156,8 +159,8 @@ add_project_arguments('-DSYSCONFDIR="/@0@"'.format(join_paths(prefix, sysconfdir version = '"@0@"'.format(meson.project_version()) git = find_program('git', native: true, required: false) if git.found() - git_commit = run_command([git, 'rev-parse', '--short', 'HEAD']) - git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD']) + git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'], check: false) + git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'], check: false) if git_commit.returncode() == 0 and git_branch.returncode() == 0 version = '"@0@-@1@ (" __DATE__ ", branch \'@2@\')"'.format( meson.project_version(), diff --git a/sway/commands/focus.c b/sway/commands/focus.c index ceb43d455..2e8584c91 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -54,7 +54,7 @@ static bool get_direction_from_next_prev(struct sway_container *container, } else { return false; } - + return true; } @@ -451,7 +451,8 @@ struct cmd_results *cmd_focus(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, ""); } struct sway_node *next_focus = NULL; - if (container_is_floating(container)) { + if (container_is_floating(container) && + container->pending.fullscreen_mode == FULLSCREEN_NONE) { next_focus = node_get_in_direction_floating(container, seat, direction); } else { next_focus = node_get_in_direction_tiling(container, seat, direction, descend); diff --git a/sway/commands/move.c b/sway/commands/move.c index f2702fa17..1a05a7a6f 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -874,6 +874,10 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "Invalid x position specified"); } + if (argc < 1) { + return cmd_results_new(CMD_FAILURE, expected_position_syntax); + } + struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID }; // Y direction num_consumed_args = parse_movement_amount(argc, argv, &ly); diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index da59016d5..1250415e5 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "log.h" #include "sway/desktop/transaction.h" #include "sway/input/cursor.h" @@ -352,6 +353,8 @@ static void unmap(struct sway_layer_surface *sway_layer) { sway_layer->layer_surface->surface, true); } +static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface); + static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_layer_surface *sway_layer = wl_container_of(listener, sway_layer, destroy); @@ -360,6 +363,12 @@ static void handle_destroy(struct wl_listener *listener, void *data) { if (sway_layer->layer_surface->mapped) { unmap(sway_layer); } + + struct sway_layer_subsurface *subsurface, *subsurface_tmp; + wl_list_for_each_safe(subsurface, subsurface_tmp, &sway_layer->subsurfaces, link) { + layer_subsurface_destroy(subsurface); + } + wl_list_remove(&sway_layer->link); wl_list_remove(&sway_layer->destroy.link); wl_list_remove(&sway_layer->map.link); @@ -428,11 +437,8 @@ static void subsurface_handle_commit(struct wl_listener *listener, void *data) { subsurface_damage(subsurface, false); } -static void subsurface_handle_destroy(struct wl_listener *listener, - void *data) { - struct sway_layer_subsurface *subsurface = - wl_container_of(listener, subsurface, destroy); - +static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface) { + wl_list_remove(&subsurface->link); wl_list_remove(&subsurface->map.link); wl_list_remove(&subsurface->unmap.link); wl_list_remove(&subsurface->destroy.link); @@ -440,6 +446,13 @@ static void subsurface_handle_destroy(struct wl_listener *listener, free(subsurface); } +static void subsurface_handle_destroy(struct wl_listener *listener, + void *data) { + struct sway_layer_subsurface *subsurface = + wl_container_of(listener, subsurface, destroy); + layer_subsurface_destroy(subsurface); +} + static struct sway_layer_subsurface *create_subsurface( struct wlr_subsurface *wlr_subsurface, struct sway_layer_surface *layer_surface) { @@ -451,6 +464,7 @@ static struct sway_layer_subsurface *create_subsurface( subsurface->wlr_subsurface = wlr_subsurface; subsurface->layer_surface = layer_surface; + wl_list_insert(&layer_surface->subsurfaces, &subsurface->link); subsurface->map.notify = subsurface_handle_map; wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); @@ -643,6 +657,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { return; } + wl_list_init(&sway_layer->subsurfaces); + sway_layer->surface_commit.notify = handle_surface_commit; wl_signal_add(&layer_surface->surface->events.commit, &sway_layer->surface_commit); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9f6df0cac..eb363f08b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include "config.h" #include "log.h" diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 57287b098..295393e39 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include "log.h" #include "config.h" diff --git a/sway/desktop/surface.c b/sway/desktop/surface.c index 767b20454..1d7b536da 100644 --- a/sway/desktop/surface.c +++ b/sway/desktop/surface.c @@ -1,7 +1,7 @@ #define _POSIX_C_SOURCE 200112L #include #include -#include +#include #include "sway/server.h" #include "sway/surface.h" diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index b1f3fb326..f5a3a053f 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -402,7 +402,7 @@ static void transaction_commit(struct sway_transaction *transaction) { struct sway_transaction_instruction *instruction = transaction->instructions->items[i]; struct sway_node *node = instruction->node; - bool hidden = node_is_view(node) && + bool hidden = node_is_view(node) && !node->destroying && !view_is_visible(node->sway_container->view); if (should_configure(node, instruction)) { instruction->serial = view_configure(node->sway_container->view, diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index c1e5bc681..5fae8296c 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -72,8 +72,8 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) { // the output box expressed in the coordinate system of the toplevel parent // of the popup struct wlr_box output_toplevel_sx_box = { - .x = output->lx - view->container->pending.content_x, - .y = output->ly - view->container->pending.content_y, + .x = output->lx - view->container->pending.content_x + view->geometry.x, + .y = output->ly - view->container->pending.content_y + view->geometry.y, .width = output->width, .height = output->height, }; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d8b1abeb4..6fddee900 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -927,6 +927,7 @@ static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_begin); struct wlr_event_pointer_pinch_begin *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_begin( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); @@ -936,6 +937,7 @@ static void handle_pointer_pinch_update(struct wl_listener *listener, void *data struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_update); struct wlr_event_pointer_pinch_update *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_update( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->dx, event->dy, @@ -946,6 +948,7 @@ static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_end); struct wlr_event_pointer_pinch_end *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_end( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); @@ -955,6 +958,7 @@ static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_begin); struct wlr_event_pointer_swipe_begin *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_begin( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); @@ -964,6 +968,7 @@ static void handle_pointer_swipe_update(struct wl_listener *listener, void *data struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_update); struct wlr_event_pointer_swipe_update *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_update( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->dx, event->dy); @@ -973,6 +978,7 @@ static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_end); struct wlr_event_pointer_swipe_end *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_end( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); diff --git a/sway/input/seat.c b/sway/input/seat.c index c5c8459eb..ce933b661 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -51,6 +51,16 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { static void seat_node_destroy(struct sway_seat_node *seat_node) { wl_list_remove(&seat_node->destroy.link); wl_list_remove(&seat_node->link); + + /* + * This is the only time we remove items from the focus stack without + * immediately re-adding them. If we just removed the last thing, + * mark that nothing has focus anymore. + */ + if (wl_list_empty(&seat_node->seat->focus_stack)) { + seat_node->seat->has_focus = false; + } + free(seat_node); } @@ -1415,9 +1425,8 @@ struct sway_node *seat_get_focus(struct sway_seat *seat) { if (!seat->has_focus) { return NULL; } - if (wl_list_empty(&seat->focus_stack)) { - return NULL; - } + sway_assert(!wl_list_empty(&seat->focus_stack), + "focus_stack is empty, but has_focus is true"); struct sway_seat_node *current = wl_container_of(seat->focus_stack.next, current, link); return current->node; diff --git a/sway/main.c b/sway/main.c index 6c71048b0..b6f8a8bf4 100644 --- a/sway/main.c +++ b/sway/main.c @@ -153,6 +153,9 @@ static void log_kernel(void) { static bool drop_permissions(void) { if (getuid() != geteuid() || getgid() != getegid()) { + sway_log(SWAY_ERROR, "!!! DEPRECATION WARNING: " + "SUID privilege drop will be removed in a future release, please migrate to seatd-launch"); + // Set the gid and uid in the correct order. if (setgid(getgid()) != 0) { sway_log(SWAY_ERROR, "Unable to drop root group, refusing to start"); diff --git a/sway/server.c b/sway/server.c index 381d4c0a3..3a94a9418 100644 --- a/sway/server.c +++ b/sway/server.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -101,6 +102,8 @@ bool server_init(struct sway_server *server) { wl_signal_add(&server->compositor->events.new_surface, &server->compositor_new_surface); + wlr_subcompositor_create(server->wl_display); + 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 e5149fb62..4756028c7 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "linux-dmabuf-unstable-v1-protocol.h" #include "cairo_util.h" @@ -80,10 +81,8 @@ void container_destroy(struct sway_container *con) { wlr_texture_destroy(con->marks_urgent); wlr_texture_destroy(con->marks_focused_tab_title); - if (con->view) { - if (con->view->container == con) { - con->view->container = NULL; - } + if (con->view && con->view->container == con) { + con->view->container = NULL; if (con->view->destroying) { view_destroy(con->view); } diff --git a/sway/tree/view.c b/sway/tree/view.c index 1318f5fb3..7d9e038d2 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "config.h" #if HAVE_XWAYLAND diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c index 19f4beaca..0cb5ee9df 100644 --- a/swaybar/tray/item.c +++ b/swaybar/tray/item.c @@ -466,6 +466,11 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x, sni->target_size = target_size; } + // Passive + if (sni->status && sni->status[0] == 'P') { + return 0; + } + int icon_size; cairo_surface_t *icon; if (sni->icon) { @@ -493,24 +498,36 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x, cairo_destroy(cairo_icon); } - int padded_size = icon_size + 2*padding; - *x -= padded_size; - int y = floor((height - padded_size) / 2.0); + double descaled_padding = (double)padding / output->scale; + double descaled_icon_size = (double)icon_size / output->scale; + + int size = descaled_icon_size + 2 * descaled_padding; + *x -= size; + int icon_y = floor((output->height - size) / 2.0); cairo_operator_t op = cairo_get_operator(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cairo, icon, *x + padding, y + padding); - cairo_rectangle(cairo, *x, y, padded_size, padded_size); + + cairo_matrix_t scale_matrix; + cairo_pattern_t *icon_pattern = cairo_pattern_create_for_surface(icon); + // TODO: check cairo_pattern_status for "ENOMEM" + cairo_matrix_init_scale(&scale_matrix, output->scale, output->scale); + cairo_matrix_translate(&scale_matrix, -(*x + descaled_padding), -(icon_y + descaled_padding)); + cairo_pattern_set_matrix(icon_pattern, &scale_matrix); + cairo_set_source(cairo, icon_pattern); + cairo_rectangle(cairo, *x, icon_y, size, size); cairo_fill(cairo); + cairo_set_operator(cairo, op); + cairo_pattern_destroy(icon_pattern); cairo_surface_destroy(icon); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; hotspot->y = 0; - hotspot->width = height; - hotspot->height = height; + hotspot->width = size; + hotspot->height = output->height; hotspot->callback = icon_hotspot_callback; hotspot->destroy = free; hotspot->data = strdup(sni->watcher_id); diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c index 5fe6f9c31..b0545f4a7 100644 --- a/swaybar/tray/tray.c +++ b/swaybar/tray/tray.c @@ -116,8 +116,8 @@ uint32_t render_tray(cairo_t *cairo, struct swaybar_output *output, double *x) { } } // else display on all - if ((int) output->height*output->scale <= 2*config->tray_padding) { - return 2*config->tray_padding + 1; + if ((int)(output->height * output->scale) <= 2 * config->tray_padding) { + return (2 * config->tray_padding + 1) / output->scale; } uint32_t max_height = 0;