diff --git a/README.fr.md b/README.fr.md index c4ef699a4..a751a52cb 100644 --- a/README.fr.md +++ b/README.fr.md @@ -57,7 +57,7 @@ Si vous utilisez déjà i3, copiez votre configuration i3 vers `~/.config/sway/config` et sway fonctionnera directement. Sinon, copiez l'exemple de fichier de configuration vers `~/.config/sway/config`. Il se trouve généralement dans `/etc/sway/config`. Exécutez `man 5 sway` pour lire la -documentation pour la configuration de sway. +documentation sur la configuration de sway. ## Exécution diff --git a/include/sway/server.h b/include/sway/server.h index 168d9ee85..64419de03 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -176,7 +176,7 @@ void handle_new_output(struct wl_listener *listener, void *data); void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data); void handle_layer_shell_surface(struct wl_listener *listener, void *data); -void sway_session_lock_init(void); +bool sway_session_lock_init(void); void sway_session_lock_add_output(struct sway_session_lock *lock, struct sway_output *output); bool sway_session_lock_has_surface(struct sway_session_lock *lock, diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 12a53c843..d8780544d 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -91,10 +91,6 @@ struct sway_container { } border; struct wlr_scene_tree *content_tree; - struct wlr_scene_buffer *output_handler; - - struct wl_listener outputs_update; - struct wl_listener output_handler_destroy; struct sway_container_state current; struct sway_container_state pending; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index ae81c5bbf..26148a92a 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -69,6 +69,9 @@ struct sway_view { struct wlr_scene_tree *scene_tree; struct wlr_scene_tree *content_tree; struct wlr_scene_tree *saved_surface_tree; + struct wlr_scene_buffer *output_handler; + + struct wl_listener outputs_update; struct wlr_scene *image_capture_scene; struct wlr_ext_image_capture_source_v1 *image_capture_source; diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 7ce48f173..50bf02cd1 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -162,7 +162,7 @@ void workspace_squash(struct sway_workspace *workspace); void workspace_move_to_output(struct sway_workspace *workspace, struct sway_output *output); -void sway_ext_workspace_init(void); +bool sway_ext_workspace_init(void); void sway_ext_workspace_output_enable(struct sway_output *output); void sway_ext_workspace_output_disable(struct sway_output *output); diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index d912b39bb..082fe20ce 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -59,7 +59,7 @@ static void transaction_destroy(struct sway_transaction *transaction) { if (node->instruction == instruction) { node->instruction = NULL; } - if (node->destroying && node->ntxnrefs == 0) { + if (node->destroying && node->ntxnrefs == 0 && !node->dirty) { switch (node->type) { case N_ROOT: sway_assert(false, "Never reached"); @@ -395,10 +395,6 @@ static void arrange_container(struct sway_container *con, // make sure it's enabled for viewing wlr_scene_node_set_enabled(&con->scene_tree->node, true); - if (con->output_handler) { - wlr_scene_buffer_set_dest_size(con->output_handler, width, height); - } - if (con->view) { int border_top = container_titlebar_height(); int border_width = con->current.border_thickness; @@ -456,6 +452,13 @@ static void arrange_container(struct sway_container *con, wlr_scene_node_reparent(&con->view->scene_tree->node, con->content_tree); wlr_scene_node_set_position(&con->view->scene_tree->node, border_left, border_top); + + // the output handler for the view wants to detect events for the entire + // container so give it negative coordinates to move it back over the + // decorations + wlr_scene_node_set_position(&con->view->output_handler->node, + -border_left, -border_top); + wlr_scene_buffer_set_dest_size(con->view->output_handler, width, height); } else { // make sure to disable the title bar if the parent is not managing it if (title_bar) { @@ -495,6 +498,11 @@ static void arrange_fullscreen(struct wlr_scene_tree *tree, // if we only care about the view, disable any decorations wlr_scene_node_set_enabled(&fs->scene_tree->node, false); + + // reconfigure the output handler (for foreign toplevel) to cover the + // view without container decorations + wlr_scene_node_set_position(&fs->view->output_handler->node, 0, 0); + wlr_scene_buffer_set_dest_size(fs->view->output_handler, width, height); } else { fs_node = &fs->scene_tree->node; arrange_container(fs, width, height, true, container_get_gaps(fs)); diff --git a/sway/input/seat.c b/sway/input/seat.c index 30c2e1490..24e663f1a 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -14,7 +14,6 @@ #include #include #include -#include "config.h" #include "list.h" #include "log.h" #include "sway/config.h" @@ -1072,6 +1071,7 @@ bool seat_is_input_allowed(struct sway_seat *seat, static void send_unfocus(struct sway_container *con, void *data) { if (con->view) { + view_close_popups(con->view); view_set_activated(con->view, false); } } @@ -1133,13 +1133,7 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n return; } - struct sway_workspace *last_workspace = seat_get_focused_workspace(seat); - if (node == NULL) { - // Close any popups on the old focus - if (node_is_view(last_focus)) { - view_close_popups(last_focus->sway_container->view); - } seat_send_unfocus(last_focus, seat); sway_input_method_relay_set_focus(&seat->im_relay, NULL); seat->has_focus = false; @@ -1161,17 +1155,15 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n return; } + // Find the output's last workspace, which might have to be removed if empty struct sway_output *new_output = new_workspace ? new_workspace->output : NULL; - + struct sway_workspace *last_workspace = + new_output ? output_get_active_workspace(new_output) : NULL; if (last_workspace != new_workspace && new_output) { node_set_dirty(&new_output->node); } - // find new output's old workspace, which might have to be removed if empty - struct sway_workspace *new_output_last_ws = - new_output ? output_get_active_workspace(new_output) : NULL; - // Unfocus the previous focus if (last_focus) { seat_send_unfocus(last_focus, seat); @@ -1215,11 +1207,11 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n } // Move sticky containers to new workspace - if (new_workspace && new_output_last_ws - && new_workspace != new_output_last_ws) { - for (int i = 0; i < new_output_last_ws->floating->length; ++i) { + if (new_workspace && last_workspace + && new_workspace != last_workspace) { + for (int i = 0; i < last_workspace->floating->length; ++i) { struct sway_container *floater = - new_output_last_ws->floating->items[i]; + last_workspace->floating->items[i]; if (container_is_sticky(floater)) { container_detach(floater); workspace_add_floating(new_workspace, floater); @@ -1228,11 +1220,6 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n } } - // Close any popups on the old focus - if (last_focus && node_is_view(last_focus)) { - view_close_popups(last_focus->sway_container->view); - } - // If urgent, either unset the urgency or start a timer to unset it if (container && container->view && view_is_urgent(container->view) && !container->view->urgent_timer) { @@ -1253,13 +1240,9 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n } } - if (new_output_last_ws) { - workspace_consider_destroy(new_output_last_ws); - } - if (last_workspace && last_workspace != new_output_last_ws) { + if (last_workspace) { workspace_consider_destroy(last_workspace); } - seat->has_focus = true; if (config->smart_gaps && new_workspace) { diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index c525b77a9..3a764d9ac 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -234,18 +234,22 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { if (layout == L_HORIZ || layout == L_TABBED) { if (cursor->cursor->y < thresh_top) { edge = WLR_EDGE_TOP; + if (thresh_top < box.y) thresh_top = box.y; box.height = thresh_top - box.y; } else if (cursor->cursor->y > thresh_bottom) { edge = WLR_EDGE_BOTTOM; + if (thresh_bottom > box.y + box.height) thresh_bottom = box.y + box.height; box.height = box.y + box.height - thresh_bottom; box.y = thresh_bottom; } } else if (layout == L_VERT || layout == L_STACKED) { if (cursor->cursor->x < thresh_left) { edge = WLR_EDGE_LEFT; + if (thresh_left < box.x) thresh_left = box.x; box.width = thresh_left - box.x; } else if (cursor->cursor->x > thresh_right) { edge = WLR_EDGE_RIGHT; + if (thresh_right > box.x + box.width) thresh_right = box.x + box.width; box.width = box.x + box.width - thresh_right; box.x = thresh_right; } @@ -373,7 +377,7 @@ static void finalize_move(struct sway_seat *seat) { enum sway_container_layout new_layout = edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM ? L_VERT : L_HORIZ; workspace_split(new_ws, new_layout); - workspace_insert_tiling(new_ws, con, after); + workspace_insert_tiling(new_ws, con, after ? new_ws->tiling->length : 0); } if (old_parent) { diff --git a/sway/lock.c b/sway/lock.c index 2b9b74b03..6f7d4c206 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -370,8 +370,12 @@ bool sway_session_lock_has_surface(struct sway_session_lock *lock, return false; } -void sway_session_lock_init(void) { +bool sway_session_lock_init(void) { server.session_lock.manager = wlr_session_lock_manager_v1_create(server.wl_display); + if (!server.session_lock.manager) { + sway_log(SWAY_ERROR, "Failed to create session lock manager"); + return false; + } server.session_lock.new_lock.notify = handle_session_lock; server.session_lock.manager_destroy.notify = handle_session_lock_destroy; @@ -379,4 +383,5 @@ void sway_session_lock_init(void) { &server.session_lock.new_lock); wl_signal_add(&server.session_lock.manager->events.destroy, &server.session_lock.manager_destroy); + return true; } diff --git a/sway/server.c b/sway/server.c index a49017424..8c55c0395 100644 --- a/sway/server.c +++ b/sway/server.c @@ -126,7 +126,8 @@ static bool is_privileged(const struct wl_global *global) { global == server.input->virtual_keyboard->global || global == server.input->virtual_pointer->global || global == server.input->transient_seat_manager->global || - global == server.xdg_output_manager_v1->global; + global == server.xdg_output_manager_v1->global || + global == server.workspace_manager_v1->global; } static bool filter_global(const struct wl_client *client, @@ -227,7 +228,7 @@ static void handle_renderer_lost(struct wl_listener *listener, void *data) { } static void handle_new_foreign_toplevel_capture_request(struct wl_listener *listener, void *data) { - struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request = data; + struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_event *request = data; struct sway_view *view = request->toplevel_handle->data; if (view->image_capture_source == NULL) { @@ -244,13 +245,25 @@ static void handle_new_foreign_toplevel_capture_request(struct wl_listener *list bool server_init(struct sway_server *server) { sway_log(SWAY_DEBUG, "Initializing Wayland server"); server->wl_display = wl_display_create(); + if (!server->wl_display) { + sway_log(SWAY_ERROR, "Failed to create wl_display"); + return false; + } server->wl_event_loop = wl_display_get_event_loop(server->wl_display); wl_display_set_global_filter(server->wl_display, filter_global, NULL); wl_display_set_default_max_buffer_size(server->wl_display, 1024 * 1024); - wlr_fixes_create(server->wl_display, 1); + if (!wlr_fixes_create(server->wl_display, 1)) { + sway_log(SWAY_ERROR, "Failed to create wp_fixes global"); + return false; + } root = root_create(server->wl_display); + if (!root) { + sway_log(SWAY_ERROR, "Failed to create root"); + wl_display_destroy(server->wl_display); + return false; + } server->backend = wlr_backend_autocreate(server->wl_event_loop, &server->session); if (!server->backend) { @@ -271,15 +284,20 @@ bool server_init(struct sway_server *server) { wlr_renderer_init_wl_shm(server->renderer, server->wl_display); - if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) { + if (wlr_renderer_get_drm_fd(server->renderer) >= 0 && + wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) { server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer( server->wl_display, 5, server->renderer); + if (!server->linux_dmabuf_v1) { + sway_log(SWAY_ERROR, "Failed to create linux-dmabuf v1"); + return false; + } } if (wlr_renderer_get_drm_fd(server->renderer) >= 0 && server->renderer->features.timeline && server->backend->features.timeline) { wlr_linux_drm_syncobj_manager_v1_create(server->wl_display, 1, - wlr_renderer_get_drm_fd(server->renderer)); + wlr_renderer_get_drm_fd(server->renderer)); } server->allocator = wlr_allocator_autocreate(server->backend, @@ -291,14 +309,29 @@ bool server_init(struct sway_server *server) { server->compositor = wlr_compositor_create(server->wl_display, 6, server->renderer); + if (!server->compositor) { + sway_log(SWAY_ERROR, "Failed to create compositor"); + return false; + } - wlr_subcompositor_create(server->wl_display); + if (!wlr_subcompositor_create(server->wl_display)) { + sway_log(SWAY_ERROR, "Failed to create subcompositor"); + return false; + } server->data_device_manager = wlr_data_device_manager_create(server->wl_display); + if (!server->data_device_manager) { + sway_log(SWAY_ERROR, "Failed to create data device manager"); + return false; + } server->gamma_control_manager_v1 = wlr_gamma_control_manager_v1_create(server->wl_display); + if (!server->gamma_control_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create gamma control manager"); + return false; + } wlr_scene_set_gamma_control_manager_v1(root->root_scene, server->gamma_control_manager_v1); @@ -307,26 +340,53 @@ bool server_init(struct sway_server *server) { server->xdg_output_manager_v1 = wlr_xdg_output_manager_v1_create(server->wl_display, root->output_layout); + if (!server->xdg_output_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create XDG output manager"); + return false; + } server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display); - sway_idle_inhibit_manager_v1_init(); + if (!server->idle_notifier_v1) { + sway_log(SWAY_ERROR, "Failed to create idle notifier"); + return false; + } + if (!sway_idle_inhibit_manager_v1_init()) { + sway_log(SWAY_ERROR, "Failed to init idle inhibit manager"); + return false; + } server->layer_shell = wlr_layer_shell_v1_create(server->wl_display, SWAY_LAYER_SHELL_VERSION); + if (!server->layer_shell) { + sway_log(SWAY_ERROR, "Failed to create layer shell"); + return false; + } 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 = wlr_xdg_shell_create(server->wl_display, SWAY_XDG_SHELL_VERSION); + if (!server->xdg_shell) { + sway_log(SWAY_ERROR, "Failed to create XDG shell"); + return false; + } wl_signal_add(&server->xdg_shell->events.new_toplevel, &server->xdg_shell_toplevel); server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel; server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); + if (!server->tablet_v2) { + sway_log(SWAY_ERROR, "Failed to create tablet manager"); + return false; + } server->server_decoration_manager = wlr_server_decoration_manager_create(server->wl_display); + if (!server->server_decoration_manager) { + sway_log(SWAY_ERROR, "Failed to create server decoration manager"); + return false; + } wlr_server_decoration_manager_set_default_mode( server->server_decoration_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); @@ -337,6 +397,10 @@ bool server_init(struct sway_server *server) { server->xdg_decoration_manager = wlr_xdg_decoration_manager_v1_create(server->wl_display); + if (!server->xdg_decoration_manager) { + sway_log(SWAY_ERROR, "Failed to create XDG decoration manager"); + return false; + } wl_signal_add( &server->xdg_decoration_manager->events.new_toplevel_decoration, &server->xdg_decoration); @@ -345,18 +409,36 @@ bool server_init(struct sway_server *server) { server->relative_pointer_manager = wlr_relative_pointer_manager_v1_create(server->wl_display); + if (!server->relative_pointer_manager) { + sway_log(SWAY_ERROR, "Failed to create relative pointer manager"); + return false; + } server->pointer_constraints = wlr_pointer_constraints_v1_create(server->wl_display); + if (!server->pointer_constraints) { + sway_log(SWAY_ERROR, "Failed to create pointer constraints"); + return false; + } server->pointer_constraint.notify = handle_pointer_constraint; wl_signal_add(&server->pointer_constraints->events.new_constraint, &server->pointer_constraint); - wlr_presentation_create(server->wl_display, server->backend, SWAY_PRESENTATION_VERSION); - wlr_alpha_modifier_v1_create(server->wl_display); + if (!wlr_presentation_create(server->wl_display, server->backend, SWAY_PRESENTATION_VERSION)) { + sway_log(SWAY_ERROR, "Failed to create presentation"); + return false; + } + if (!wlr_alpha_modifier_v1_create(server->wl_display)) { + sway_log(SWAY_ERROR, "Failed to create alpha modifier"); + return false; + } server->output_manager_v1 = wlr_output_manager_v1_create(server->wl_display); + if (!server->output_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create output manager"); + return false; + } server->output_manager_apply.notify = handle_output_manager_apply; wl_signal_add(&server->output_manager_v1->events.apply, &server->output_manager_apply); @@ -366,19 +448,43 @@ bool server_init(struct sway_server *server) { server->output_power_manager_v1 = wlr_output_power_manager_v1_create(server->wl_display); + if (!server->output_power_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create output power manager"); + return false; + } server->output_power_manager_set_mode.notify = handle_output_power_manager_set_mode; wl_signal_add(&server->output_power_manager_v1->events.set_mode, &server->output_power_manager_set_mode); server->input_method = wlr_input_method_manager_v2_create(server->wl_display); + if (!server->input_method) { + sway_log(SWAY_ERROR, "Failed to create input method manager"); + return false; + } server->text_input = wlr_text_input_manager_v3_create(server->wl_display); + if (!server->text_input) { + sway_log(SWAY_ERROR, "Failed to create text input manager"); + return false; + } server->foreign_toplevel_list = wlr_ext_foreign_toplevel_list_v1_create(server->wl_display, SWAY_FOREIGN_TOPLEVEL_LIST_VERSION); + if (!server->foreign_toplevel_list) { + sway_log(SWAY_ERROR, "Failed to create foreign toplevel list"); + return false; + } server->foreign_toplevel_manager = wlr_foreign_toplevel_manager_v1_create(server->wl_display); + if (!server->foreign_toplevel_manager) { + sway_log(SWAY_ERROR, "Failed to create foreign toplevel manager"); + return false; + } - sway_session_lock_init(); - sway_ext_workspace_init(); + if (!sway_session_lock_init()) { + return false; + } + if (!sway_ext_workspace_init()) { + return false; + } #if WLR_HAS_DRM_BACKEND server->drm_lease_manager= @@ -394,26 +500,74 @@ bool server_init(struct sway_server *server) { #endif server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display); + if (!server->export_dmabuf_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create export dmabuf manager"); + return false; + } server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display); + if (!server->screencopy_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create screencopy manager"); + return false; + } server->ext_image_copy_capture_manager_v1 = wlr_ext_image_copy_capture_manager_v1_create(server->wl_display, 1); - wlr_ext_output_image_capture_source_manager_v1_create(server->wl_display, 1); + if (!server->ext_image_copy_capture_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create ext image copy capture manager"); + return false; + } + if (!wlr_ext_output_image_capture_source_manager_v1_create(server->wl_display, 1)) { + sway_log(SWAY_ERROR, "Failed to create ext output image capture source manager"); + return false; + } server->wlr_data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display); + if (!server->wlr_data_control_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create data control manager"); + return false; + } server->ext_data_control_manager_v1 = wlr_ext_data_control_manager_v1_create(server->wl_display, 1); + if (!server->ext_data_control_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create ext data control manager"); + return false; + } server->security_context_manager_v1 = wlr_security_context_manager_v1_create(server->wl_display); - wlr_viewporter_create(server->wl_display); - wlr_single_pixel_buffer_manager_v1_create(server->wl_display); + if (!server->security_context_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create security context manager"); + return false; + } + if (!wlr_viewporter_create(server->wl_display)) { + sway_log(SWAY_ERROR, "Failed to create viewporter"); + return false; + } + if (!wlr_single_pixel_buffer_manager_v1_create(server->wl_display)) { + sway_log(SWAY_ERROR, "Failed to create single pixel buffer manager"); + return false; + } server->content_type_manager_v1 = wlr_content_type_manager_v1_create(server->wl_display, 1); - wlr_fractional_scale_manager_v1_create(server->wl_display, 1); + if (!server->content_type_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create content type manager"); + return false; + } + if (!wlr_fractional_scale_manager_v1_create(server->wl_display, 1)) { + sway_log(SWAY_ERROR, "Failed to create fractional scale manager"); + return false; + } server->ext_foreign_toplevel_image_capture_source_manager_v1 = wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(server->wl_display, 1); + if (!server->ext_foreign_toplevel_image_capture_source_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create ext foreign toplevel image capture source manager"); + return false; + } server->new_foreign_toplevel_capture_request.notify = handle_new_foreign_toplevel_capture_request; - wl_signal_add(&server->ext_foreign_toplevel_image_capture_source_manager_v1->events.new_request, + wl_signal_add(&server->ext_foreign_toplevel_image_capture_source_manager_v1->events.capture_request, &server->new_foreign_toplevel_capture_request); server->tearing_control_v1 = wlr_tearing_control_manager_v1_create(server->wl_display, 1); + if (!server->tearing_control_v1) { + sway_log(SWAY_ERROR, "Failed to create tearing control manager"); + return false; + } server->tearing_control_new_object.notify = handle_new_tearing_hint; wl_signal_add(&server->tearing_control_v1->events.new_object, &server->tearing_control_new_object); @@ -421,10 +575,24 @@ bool server_init(struct sway_server *server) { struct wlr_xdg_foreign_registry *foreign_registry = wlr_xdg_foreign_registry_create(server->wl_display); - wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry); - wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry); + if (!foreign_registry) { + sway_log(SWAY_ERROR, "Failed to create XDG foreign registry"); + return false; + } + if (!wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry)) { + sway_log(SWAY_ERROR, "Failed to create XDG foreign v1"); + return false; + } + if (!wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry)) { + sway_log(SWAY_ERROR, "Failed to create XDG foreign v2"); + return false; + } server->xdg_activation_v1 = wlr_xdg_activation_v1_create(server->wl_display); + if (!server->xdg_activation_v1) { + sway_log(SWAY_ERROR, "Failed to create XDG activation"); + return false; + } server->xdg_activation_v1_request_activate.notify = xdg_activation_v1_handle_request_activate; wl_signal_add(&server->xdg_activation_v1->events.request_activate, @@ -436,6 +604,10 @@ bool server_init(struct sway_server *server) { struct wlr_xdg_toplevel_tag_manager_v1 *xdg_toplevel_tag_manager_v1 = wlr_xdg_toplevel_tag_manager_v1_create(server->wl_display, 1); + if (!xdg_toplevel_tag_manager_v1) { + sway_log(SWAY_ERROR, "Failed to create XDG toplevel tag manager"); + return false; + } server->xdg_toplevel_tag_manager_v1_set_tag.notify = xdg_toplevel_tag_manager_v1_handle_set_tag; wl_signal_add(&xdg_toplevel_tag_manager_v1->events.set_tag, @@ -443,6 +615,10 @@ bool server_init(struct sway_server *server) { struct wlr_cursor_shape_manager_v1 *cursor_shape_manager = wlr_cursor_shape_manager_v1_create(server->wl_display, 2); + if (!cursor_shape_manager) { + sway_log(SWAY_ERROR, "Failed to create cursor shape manager"); + return false; + } server->request_set_cursor_shape.notify = handle_request_set_cursor_shape; wl_signal_add(&cursor_shape_manager->events.request_set_shape, &server->request_set_cursor_shape); @@ -471,11 +647,18 @@ bool server_init(struct sway_server *server) { }); free(transfer_functions); free(primaries); + if (!cm) { + sway_log(SWAY_ERROR, "Failed to create color manager"); + return false; + } wlr_scene_set_color_manager_v1(root->root_scene, cm); } - wlr_color_representation_manager_v1_create_with_renderer( - server->wl_display, 1, server->renderer); + if (!wlr_color_representation_manager_v1_create_with_renderer( + server->wl_display, 1, server->renderer)) { + sway_log(SWAY_ERROR, "Failed to create color representation manager"); + return false; + } wl_list_init(&server->pending_launcher_ctxs); @@ -515,8 +698,16 @@ bool server_init(struct sway_server *server) { } server->dirty_nodes = create_list(); + if (!server->dirty_nodes) { + sway_log(SWAY_ERROR, "Failed to create dirty nodes list"); + return false; + } server->input = input_manager_create(server); + if (!server->input) { + sway_log(SWAY_ERROR, "Failed to create input manager"); + return false; + } input_manager_get_default_seat(); // create seat0 return true; diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 18744a22a..389b20570 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -154,7 +154,7 @@ The following commands may only be used in the configuration file. *input* drag_lock enabled|disabled|enabled_sticky Enables or disables drag lock for specified input device. The default is - _enabled_sticky_. + _disabled_. *input* dwt enabled|disabled Enables or disables disable-while-typing for the specified input device. diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index 2658228a1..70c831375 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd @@ -802,7 +802,7 @@ node and will have the following properties: Retrieve the currently set marks *REPLY*++ -An array of marks current set. Since each mark can only be set for one +An array of marks currently set. Since each mark can only be set for one container, this is a set so each value is unique and the order is undefined. *Example Reply:* @@ -833,13 +833,13 @@ An array of bar IDs, which are strings *MESSAGE*++ When sent with a bar ID as the payload, this retrieves the config associated -with the specified by the bar ID in the payload. This is used by swaybar, but -could also be used for third party bars +with the bar ID specified in the payload. This is used by swaybar, but could +also be used for third-party bars *REPLY*++ An object that represents the configuration for the bar with the bar ID sent as -the payload. The following properties exists and more information about what -their value mean can be found in *sway-bar*(5): +the payload. The following properties exist, with more information about their +values in *sway-bar*(5): [- *PROPERTY* :- *DATA TYPE* @@ -1040,7 +1040,7 @@ An object containing the following properties: ## 8. GET_BINDING_MODES *MESSAGE*++ -Retrieve the list of binding modes that currently configured +Retrieve the list of binding modes that are currently configured *REPLY*++ An array of strings, with each string being the name of a binding mode. This @@ -1154,13 +1154,13 @@ following properties: _tablet\_tool_, _tablet\_pad_, or _switch_ |- xkb_active_layout_name : string -: (Only keyboards) The name of the active keyboard layout in use +: (Only keyboards) The name of the active keyboard layout |- xkb_layout_names : array : (Only keyboards) A list a layout names configured for the keyboard |- xkb_active_layout_index : integer -: (Only keyboards) The index of the active keyboard layout in use +: (Only keyboards) The index of the active keyboard layout |- scroll_factor : floating : (Only pointers) Multiplier applied on scroll event values. @@ -1467,7 +1467,7 @@ one seat. Each object has the following properties: # EVENTS -Events are a way for client to get notified of changes to sway. A client can +Events are a way for clients to get notified of changes to sway. A client can subscribe to any events it wants to be notified of changes for. The event is sent in the same format as a reply. The following events are currently available: @@ -1478,7 +1478,7 @@ available: |- 0x80000000 : workspace :[ Sent whenever an event involving a workspace occurs such as initialization - of a new workspace or a different workspace gains focus + of a new workspace or another workspace gaining focus |- 0x80000001 : output : Sent when outputs are updated @@ -1487,7 +1487,7 @@ available: : Sent whenever the binding mode changes |- 0x80000003 : window -: Sent whenever an event involving a window occurs such as being reparented, +: Sent whenever an event involving a window occurs such as it being reparented, focused, or closed |- 0x80000004 : barconfig_update @@ -1503,7 +1503,7 @@ available: : Sent when an ipc client sends a _SEND\_TICK_ message |- 0x80000014 : bar_state_update -: Send when the visibility of a bar should change due to a modifier +: Sent when the visibility of a bar should change due to a modifier |- 0x80000015 : input : Sent when something related to input devices changes @@ -1522,10 +1522,10 @@ single object with the following properties: :[ The type of change that occurred. See below for more information |- current : object -: An object representing the workspace effected or _null_ for _reload_ changes +: An object representing the affected workspace or _null_ for _reload_ changes |- old : object -: For a _focus_ change, this is will be an object representing the workspace +: For a _focus_ change, this will be an object representing the workspace being switched from. Otherwise, it is _null_ @@ -1543,7 +1543,7 @@ The following change types are currently available: |- rename : The workspace was renamed |- urgent -: A window on the workspace has had their urgency hint set or all urgency hints +: A window on the workspace has had its urgency hint set or all urgency hints for windows on the workspace have been cleared |- reload : The configuration file has been reloaded @@ -1653,7 +1653,7 @@ object with the following properties: :[ The type of change that occurred. See below for more information |- container : object -: An object representing the window effected +: An object representing the affected window The following change types are currently available: @@ -1816,7 +1816,7 @@ event is a single object with the following properties: : Whether this event was triggered by subscribing to the tick events |- payload : string -: The payload given with a _SEND\_TICK_ message, if any. Otherwise, an empty +: The payload provided in a _SEND\_TICK_ message, if any. Otherwise, an empty string @@ -1838,7 +1838,7 @@ event is a single object with the following properties: :- *DESCRIPTION* |- id : string -:[ The bar ID effected +:[ The bar ID affected |- visible_by_modifier : boolean : Whether the bar should be made visible due to a modifier being pressed @@ -1854,7 +1854,7 @@ event is a single object with the following properties: ## 0x80000015. INPUT -Sent when something related to the input devices changes. The event is a single +Sent when something related to input devices changes. The event is a single object with the following properties: [- *PROPERTY* @@ -1865,7 +1865,7 @@ object with the following properties: :[ What has changed |- input : object -: An object representing the input that is identical the ones GET_INPUTS gives +: An object representing the input that is identical to the ones GET_INPUTS gives The following change types are currently available: [- *TYPE* diff --git a/sway/tree/container.c b/sway/tree/container.c index fd9abadc6..6880841bd 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -25,50 +25,6 @@ #include "log.h" #include "stringop.h" -static void handle_outputs_update( - struct wl_listener *listener, void *data) { - struct sway_container *con = wl_container_of( - listener, con, outputs_update); - struct wlr_scene_outputs_update_event *event = data; - - struct wlr_foreign_toplevel_handle_v1 *toplevel = con->view->foreign_toplevel; - if (toplevel) { - struct wlr_foreign_toplevel_handle_v1_output *toplevel_output, *tmp; - wl_list_for_each_safe(toplevel_output, tmp, &toplevel->outputs, link) { - bool active = false; - for (size_t i = 0; i < event->size; i++) { - struct wlr_scene_output *scene_output = event->active[i]; - if (scene_output->output == toplevel_output->output) { - active = true; - break; - } - } - - if (!active) { - wlr_foreign_toplevel_handle_v1_output_leave(toplevel, toplevel_output->output); - } - } - - for (size_t i = 0; i < event->size; i++) { - struct wlr_scene_output *scene_output = event->active[i]; - wlr_foreign_toplevel_handle_v1_output_enter(toplevel, scene_output->output); - } - } -} - -static void handle_destroy( - struct wl_listener *listener, void *data) { - struct sway_container *con = wl_container_of( - listener, con, output_handler_destroy); - - container_begin_destroy(con); -} - -static bool handle_point_accepts_input( - struct wlr_scene_buffer *buffer, double *x, double *y) { - return false; -} - static struct wlr_scene_rect *alloc_rect_node(struct wlr_scene_tree *parent, bool *failed) { if (*failed) { @@ -135,22 +91,6 @@ struct sway_container *container_create(struct sway_view *view) { c->border.bottom = alloc_rect_node(c->border.tree, &failed); c->border.left = alloc_rect_node(c->border.tree, &failed); c->border.right = alloc_rect_node(c->border.tree, &failed); - - c->output_handler = wlr_scene_buffer_create(c->border.tree, NULL); - if (!c->output_handler) { - sway_log(SWAY_ERROR, "Failed to allocate a scene node"); - failed = true; - } - - if (!failed) { - c->outputs_update.notify = handle_outputs_update; - wl_signal_add(&c->output_handler->events.outputs_update, - &c->outputs_update); - c->output_handler_destroy.notify = handle_destroy; - wl_signal_add(&c->output_handler->node.events.destroy, - &c->output_handler_destroy); - c->output_handler->point_accepts_input = handle_point_accepts_input; - } } if (!failed && !scene_descriptor_assign(&c->scene_tree->node, @@ -522,7 +462,6 @@ void container_destroy(struct sway_container *con) { if (con->view && con->view->container == con) { con->view->container = NULL; - wlr_scene_node_destroy(&con->output_handler->node); if (con->view->destroying) { view_destroy(con->view); } @@ -564,11 +503,6 @@ void container_begin_destroy(struct sway_container *con) { if (con->pending.parent || con->pending.workspace) { container_detach(con); } - - if (con->view && con->view->container == con) { - wl_list_remove(&con->outputs_update.link); - wl_list_remove(&con->output_handler_destroy.link); - } } void container_reap_empty(struct sway_container *con) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 6dde3f63c..83b4972b1 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -38,6 +38,41 @@ #include "sway/xdg_decoration.h" #include "stringop.h" +static void handle_outputs_update( + struct wl_listener *listener, void *data) { + struct sway_view *view = wl_container_of(listener, view, outputs_update); + struct wlr_scene_outputs_update_event *event = data; + + struct wlr_foreign_toplevel_handle_v1 *toplevel = view->foreign_toplevel; + if (toplevel) { + struct wlr_foreign_toplevel_handle_v1_output *toplevel_output, *tmp; + wl_list_for_each_safe(toplevel_output, tmp, &toplevel->outputs, link) { + bool active = false; + for (size_t i = 0; i < event->size; i++) { + struct wlr_scene_output *scene_output = event->active[i]; + if (scene_output->output == toplevel_output->output) { + active = true; + break; + } + } + + if (!active) { + wlr_foreign_toplevel_handle_v1_output_leave(toplevel, toplevel_output->output); + } + } + + for (size_t i = 0; i < event->size; i++) { + struct wlr_scene_output *scene_output = event->active[i]; + wlr_foreign_toplevel_handle_v1_output_enter(toplevel, scene_output->output); + } + } +} + +static bool handle_point_accepts_input( + struct wlr_scene_buffer *buffer, double *x, double *y) { + return false; +} + bool view_init(struct sway_view *view, enum sway_view_type type, const struct sway_view_impl *impl) { bool failed = false; @@ -51,12 +86,23 @@ bool view_init(struct sway_view *view, enum sway_view_type type, goto err; } + view->output_handler = wlr_scene_buffer_create(view->scene_tree, NULL); + if (!view->output_handler) { + sway_log(SWAY_ERROR, "Failed to allocate a scene node"); + goto err; + } + view->image_capture_scene = wlr_scene_create(); if (view->image_capture_scene == NULL) { goto err; } view->image_capture_scene->restack_xwayland_surfaces = false; + view->outputs_update.notify = handle_outputs_update; + wl_signal_add(&view->output_handler->events.outputs_update, + &view->outputs_update); + view->output_handler->point_accepts_input = handle_point_accepts_input; + view->type = type; view->impl = impl; view->executed_criteria = create_list(); @@ -102,6 +148,7 @@ void view_begin_destroy(struct sway_view *view) { return; } view->destroying = true; + wl_list_remove(&view->outputs_update.link); if (!view->container) { view_destroy(view); @@ -1229,8 +1276,10 @@ void view_save_buffer(struct sway_view *view) { return; } - // Enable and disable the saved surface tree like so to atomitaclly update - // the tree. This will prevent over damaging or other weirdness. + // Make sure the output handler is placed above the saved surface so we don't send + // spurious events to the foreign toplevel handler. Also, make the saved surface tree + // is disabled until it is ready to replace the real surface. + wlr_scene_node_place_below(&view->saved_surface_tree->node, &view->output_handler->node); wlr_scene_node_set_enabled(&view->saved_surface_tree->node, false); wlr_scene_node_for_each_buffer(&view->content_tree->node, diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index d366d19aa..9d78d7080 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -97,17 +97,18 @@ static void handle_commit(struct wl_listener *listener, void *data) { } // Initialize ext-workspace. Must be called once at startup. -void sway_ext_workspace_init(void) { +bool sway_ext_workspace_init(void) { server.workspace_manager_v1 = wlr_ext_workspace_manager_v1_create(server.wl_display, 1); if (!server.workspace_manager_v1) { sway_log(SWAY_ERROR, "Failed to create ext_workspace_manager_v1"); - return; + return false; } server.workspace_manager_v1_commit.notify = handle_commit; wl_signal_add(&server.workspace_manager_v1->events.commit, &server.workspace_manager_v1_commit); + return true; } // Must be called whenever an output is enabled. @@ -919,7 +920,7 @@ void workspace_unwrap_children(struct sway_workspace *ws, while (wrap->pending.children->length) { struct sway_container *child = wrap->pending.children->items[0]; container_detach(child); - workspace_add_tiling(ws, child); + workspace_insert_tiling_direct(ws, child, ws->tiling->length); } } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 68d8dd32d..c3929a35f 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -417,6 +417,28 @@ void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) { } bool ipc_initialize(struct swaybar *bar) { + if (!bar->id) { + uint32_t len = 0; + char *res = ipc_single_command(bar->ipc_socketfd, + IPC_GET_BAR_CONFIG, "", &len); + json_object *bars = json_tokener_parse(res); + if (!json_object_is_type(bars, json_type_array) + || json_object_array_length(bars) == 0) { + sway_log(SWAY_ERROR, "No bar configuration found, " + "please configure a bar block in your sway config file."); + json_object_put(bars); + free(res); + return false; + } + json_object *first = json_object_array_get_idx(bars, 0); + bar->id = strdup(json_object_get_string(first)); + json_object_put(bars); + free(res); + sway_log(SWAY_INFO, "Using first bar config: %s. " + "Use --bar_id to manually select a different bar configuration.", + bar->id); + } + uint32_t len = strlen(bar->id); char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_BAR_CONFIG, bar->id, &len); diff --git a/swaybar/main.c b/swaybar/main.c index e1b0cecac..c2020ff09 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -72,12 +72,6 @@ int main(int argc, char **argv) { sway_log_init(SWAY_INFO, NULL); } - if (!swaybar.id) { - sway_log(SWAY_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) {