diff --git a/.builds/alpine.yml b/.builds/alpine.yml index 34f780e9e..59df7737c 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -4,6 +4,7 @@ packages: - eudev-dev - gdk-pixbuf-dev - json-c-dev + - libdisplay-info-dev - libevdev-dev - libinput-dev - libseat-dev diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index 19bd2e594..9972c01ad 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -3,6 +3,7 @@ packages: - cairo - gdk-pixbuf2 - json-c + - libdisplay-info - libegl - libinput - libxcb diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 861aa2553..29c6312af 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -20,6 +20,7 @@ packages: - devel/libudev-devd - graphics/libdrm - graphics/mesa-libs +- sysutils/libdisplay-info - sysutils/seatd - x11/libinput - x11/libX11 diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 828ac3704..4a3774d97 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -108,6 +108,10 @@ void cursor_unhide(struct sway_cursor *cursor); int cursor_get_timeout(struct sway_cursor *cursor); void cursor_notify_key_press(struct sway_cursor *cursor); +void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, + struct wlr_input_device *device, double dx, double dy, + double dx_unaccel, double dy_unaccel); + void dispatch_cursor_button(struct sway_cursor *cursor, struct wlr_input_device *device, uint32_t time_msec, uint32_t button, enum wlr_button_state state); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 4abe91f71..7b2d3d075 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -4,6 +4,7 @@ #include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h> #include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_seat.h> +#include <wlr/types/wlr_touch.h> #include <wlr/util/edges.h> #include "sway/config.h" #include "sway/input/input-manager.h" @@ -36,6 +37,12 @@ struct sway_seatop_impl { void (*swipe_end)(struct sway_seat *seat, struct wlr_pointer_swipe_end_event *event); void (*rebase)(struct sway_seat *seat, uint32_t time_msec); + void (*touch_motion)(struct sway_seat *seat, + struct wlr_touch_motion_event *event, double lx, double ly); + void (*touch_up)(struct sway_seat *seat, + struct wlr_touch_up_event *event); + void (*touch_down)(struct sway_seat *seat, + struct wlr_touch_down_event *event, double lx, double ly); void (*tablet_tool_motion)(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec); void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool, @@ -43,7 +50,7 @@ struct sway_seatop_impl { void (*end)(struct sway_seat *seat); void (*unref)(struct sway_seat *seat, struct sway_container *con); void (*render)(struct sway_seat *seat, struct sway_output *output, - pixman_region32_t *damage); + const pixman_region32_t *damage); bool allow_set_cursor; }; @@ -256,10 +263,13 @@ enum wlr_edges find_resize_edge(struct sway_container *cont, void seatop_begin_default(struct sway_seat *seat); void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, - uint32_t time_msec, double sx, double sy); + double sx, double sy); void seatop_begin_down_on_surface(struct sway_seat *seat, - struct wlr_surface *surface, uint32_t time_msec, double sx, double sy); + struct wlr_surface *surface, double sx, double sy); + +void seatop_begin_touch_down(struct sway_seat *seat, struct wlr_surface *surface, + struct wlr_touch_down_event *event, double sx, double sy, double lx, double ly); void seatop_begin_move_floating(struct sway_seat *seat, struct sway_container *con); @@ -319,6 +329,15 @@ void seatop_swipe_update(struct sway_seat *seat, void seatop_swipe_end(struct sway_seat *seat, struct wlr_pointer_swipe_end_event *event); +void seatop_touch_motion(struct sway_seat *seat, + struct wlr_touch_motion_event *event, double lx, double ly); + +void seatop_touch_up(struct sway_seat *seat, + struct wlr_touch_up_event *event); + +void seatop_touch_down(struct sway_seat *seat, + struct wlr_touch_down_event *event, double lx, double ly); + void seatop_rebase(struct sway_seat *seat, uint32_t time_msec); /** @@ -338,7 +357,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con); * (eg. dropzone for move-tiling) */ void seatop_render(struct sway_seat *seat, struct sway_output *output, - pixman_region32_t *damage); + const pixman_region32_t *damage); bool seatop_allows_set_cursor(struct sway_seat *seat); diff --git a/include/sway/output.h b/include/sway/output.h index 28be6a1e9..2aa1b2788 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -112,8 +112,7 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output); struct sway_workspace *output_get_active_workspace(struct sway_output *output); -void output_render(struct sway_output *output, struct timespec *when, - pixman_region32_t *damage); +void output_render(struct sway_output *output, pixman_region32_t *damage); void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, @@ -167,7 +166,7 @@ enum sway_container_layout output_get_default_layout( struct sway_output *output); void render_rect(struct sway_output *output, - pixman_region32_t *output_damage, const struct wlr_box *_box, + const pixman_region32_t *output_damage, const struct wlr_box *_box, float color[static 4]); void premultiply_alpha(float color[4], float opacity); diff --git a/include/sway/surface.h b/include/sway/surface.h index 506818976..a7a8ec3ff 100644 --- a/include/sway/surface.h +++ b/include/sway/surface.h @@ -15,6 +15,7 @@ struct sway_surface { struct wl_event_source *frame_done_timer; }; +void surface_update_outputs(struct wlr_surface *surface); void surface_enter_output(struct wlr_surface *surface, struct sway_output *output); void surface_leave_output(struct wlr_surface *surface, diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 9355944d9..b457f121c 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -5,6 +5,7 @@ #include "sway/commands.h" #include "sway/output.h" #include "sway/tree/arrange.h" +#include "sway/tree/container.h" #include "sway/tree/root.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" @@ -13,180 +14,6 @@ static const char expected_syntax[] = "Expected 'swap container with id|con_id|mark <arg>'"; -static void swap_places(struct sway_container *con1, - struct sway_container *con2) { - struct sway_container *temp = malloc(sizeof(struct sway_container)); - temp->pending.x = con1->pending.x; - temp->pending.y = con1->pending.y; - temp->pending.width = con1->pending.width; - temp->pending.height = con1->pending.height; - temp->width_fraction = con1->width_fraction; - temp->height_fraction = con1->height_fraction; - temp->pending.parent = con1->pending.parent; - temp->pending.workspace = con1->pending.workspace; - bool temp_floating = container_is_floating(con1); - - con1->pending.x = con2->pending.x; - con1->pending.y = con2->pending.y; - con1->pending.width = con2->pending.width; - con1->pending.height = con2->pending.height; - con1->width_fraction = con2->width_fraction; - con1->height_fraction = con2->height_fraction; - - con2->pending.x = temp->pending.x; - con2->pending.y = temp->pending.y; - con2->pending.width = temp->pending.width; - con2->pending.height = temp->pending.height; - con2->width_fraction = temp->width_fraction; - con2->height_fraction = temp->height_fraction; - - int temp_index = container_sibling_index(con1); - if (con2->pending.parent) { - container_insert_child(con2->pending.parent, con1, - container_sibling_index(con2)); - } else if (container_is_floating(con2)) { - workspace_add_floating(con2->pending.workspace, con1); - } else { - workspace_insert_tiling(con2->pending.workspace, con1, - container_sibling_index(con2)); - } - if (temp->pending.parent) { - container_insert_child(temp->pending.parent, con2, temp_index); - } else if (temp_floating) { - workspace_add_floating(temp->pending.workspace, con2); - } else { - workspace_insert_tiling(temp->pending.workspace, con2, temp_index); - } - - free(temp); -} - -static void swap_focus(struct sway_container *con1, - struct sway_container *con2, struct sway_seat *seat, - struct sway_container *focus) { - if (focus == con1 || focus == con2) { - struct sway_workspace *ws1 = con1->pending.workspace; - struct sway_workspace *ws2 = con2->pending.workspace; - enum sway_container_layout layout1 = container_parent_layout(con1); - enum sway_container_layout layout2 = container_parent_layout(con2); - if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) { - if (workspace_is_visible(ws2)) { - seat_set_focus(seat, &con2->node); - } - seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1); - } else if (focus == con2 && (layout1 == L_TABBED - || layout1 == L_STACKED)) { - if (workspace_is_visible(ws1)) { - seat_set_focus(seat, &con1->node); - } - seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2); - } else if (ws1 != ws2) { - seat_set_focus_container(seat, focus == con1 ? con2 : con1); - } else { - seat_set_focus_container(seat, focus); - } - } else { - seat_set_focus_container(seat, focus); - } - - if (root->fullscreen_global) { - seat_set_focus(seat, - seat_get_focus_inactive(seat, &root->fullscreen_global->node)); - } -} - -void container_swap(struct sway_container *con1, struct sway_container *con2) { - if (!sway_assert(con1 && con2, "Cannot swap with nothing")) { - return; - } - if (!sway_assert(!container_has_ancestor(con1, con2) - && !container_has_ancestor(con2, con1), - "Cannot swap ancestor and descendant")) { - return; - } - - sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu", - con1->node.id, con2->node.id); - - bool scratch1 = con1->scratchpad; - bool hidden1 = container_is_scratchpad_hidden(con1); - bool scratch2 = con2->scratchpad; - bool hidden2 = container_is_scratchpad_hidden(con2); - if (scratch1) { - if (hidden1) { - root_scratchpad_show(con1); - } - root_scratchpad_remove_container(con1); - } - if (scratch2) { - if (hidden2) { - root_scratchpad_show(con2); - } - root_scratchpad_remove_container(con2); - } - - enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode; - if (fs1) { - container_fullscreen_disable(con1); - } - enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode; - if (fs2) { - container_fullscreen_disable(con2); - } - - struct sway_seat *seat = config->handler_context.seat; - struct sway_container *focus = seat_get_focused_container(seat); - struct sway_workspace *vis1 = - output_get_active_workspace(con1->pending.workspace->output); - struct sway_workspace *vis2 = - output_get_active_workspace(con2->pending.workspace->output); - if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a" - "workspace. This should not happen")) { - return; - } - - char *stored_prev_name = NULL; - if (seat->prev_workspace_name) { - stored_prev_name = strdup(seat->prev_workspace_name); - } - - swap_places(con1, con2); - - if (!workspace_is_visible(vis1)) { - seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node)); - } - if (!workspace_is_visible(vis2)) { - seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node)); - } - - swap_focus(con1, con2, seat, focus); - - if (stored_prev_name) { - free(seat->prev_workspace_name); - seat->prev_workspace_name = stored_prev_name; - } - - if (scratch1) { - root_scratchpad_add_container(con2, NULL); - if (!hidden1) { - root_scratchpad_show(con2); - } - } - if (scratch2) { - root_scratchpad_add_container(con1, NULL); - if (!hidden2) { - root_scratchpad_show(con1); - } - } - - if (fs1) { - container_set_fullscreen(con2, fs1); - } - if (fs2) { - container_set_fullscreen(con1, fs2); - } -} - static bool test_con_id(struct sway_container *container, void *data) { size_t *con_id = data; return container->node.id == *con_id; diff --git a/sway/config/output.c b/sway/config/output.c index e2e48e4cc..3b524433c 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -460,6 +460,16 @@ static void queue_output_config(struct output_config *oc, float scale; if (oc && oc->scale > 0) { scale = oc->scale; + + // The factional-scale-v1 protocol uses increments of 120ths to send + // the scale factor to the client. Adjust the scale so that we use the + // same value as the clients'. + float adjusted_scale = round(scale * 120) / 120; + if (scale != adjusted_scale) { + sway_log(SWAY_INFO, "Adjusting output scale from %f to %f", + scale, adjusted_scale); + scale = adjusted_scale; + } } else { scale = compute_default_scale(wlr_output, pending); sway_log(SWAY_DEBUG, "Auto-detected output scale: %f", scale); diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 795eb4cd7..e16bee78d 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -383,7 +383,6 @@ static void handle_map(struct wl_listener *listener, void *data) { 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); - surface_enter_output(sway_layer->layer_surface->surface, output); cursor_rebase_all(); } @@ -679,6 +678,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_list_insert(&output->layers[layer_surface->pending.layer], &sway_layer->link); + surface_enter_output(layer_surface->surface, output); + // Temporarily set the layer's current state to pending // So that we can easily arrange it struct wlr_layer_surface_v1_state old_state = layer_surface->current; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 141edb491..0c8a5fd41 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -496,6 +496,12 @@ static bool scan_out_fullscreen_view(struct sway_output *output, if (n_surfaces != 1) { return false; } + size_t n_popups = 0; + output_view_for_each_popup_surface(output, view, + count_surface_iterator, &n_popups); + if (n_popups > 0) { + return false; + } if (surface->buffer == NULL) { return false; @@ -517,13 +523,34 @@ static bool scan_out_fullscreen_view(struct sway_output *output, return wlr_output_commit(wlr_output); } +static void get_frame_damage(struct sway_output *output, + pixman_region32_t *frame_damage) { + struct wlr_output *wlr_output = output->wlr_output; + + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + + pixman_region32_init(frame_damage); + + enum wl_output_transform transform = + wlr_output_transform_invert(wlr_output->transform); + wlr_region_transform(frame_damage, &output->damage_ring.current, + transform, width, height); + + if (debug.damage != DAMAGE_DEFAULT) { + pixman_region32_union_rect(frame_damage, frame_damage, + 0, 0, wlr_output->width, wlr_output->height); + } +} + static int output_repaint_timer_handler(void *data) { struct sway_output *output = data; - if (output->wlr_output == NULL) { + struct wlr_output *wlr_output = output->wlr_output; + if (wlr_output == NULL) { return 0; } - output->wlr_output->frame_pending = false; + wlr_output->frame_pending = false; struct sway_workspace *workspace = output->current.active_workspace; if (workspace == NULL) { @@ -557,6 +584,11 @@ static int output_repaint_timer_handler(void *data) { } } + if (!output->wlr_output->needs_frame && + !pixman_region32_not_empty(&output->damage_ring.current)) { + return 0; + } + int buffer_age; if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { return 0; @@ -565,20 +597,26 @@ static int output_repaint_timer_handler(void *data) { pixman_region32_t damage; pixman_region32_init(&damage); wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage); - if (!output->wlr_output->needs_frame && - !pixman_region32_not_empty(&output->damage_ring.current)) { - pixman_region32_fini(&damage); - wlr_output_rollback(output->wlr_output); - return 0; - } struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - output_render(output, &now, &damage); + output_render(output, &damage); pixman_region32_fini(&damage); + pixman_region32_t frame_damage; + get_frame_damage(output, &frame_damage); + wlr_output_set_damage(wlr_output, &frame_damage); + pixman_region32_fini(&frame_damage); + + if (!wlr_output_commit(wlr_output)) { + return 0; + } + + wlr_damage_ring_rotate(&output->damage_ring); + output->last_frame = now; + return 0; } @@ -859,6 +897,12 @@ static void update_textures(struct sway_container *con, void *data) { container_update_marks_textures(con); } +static void update_output_scale_iterator(struct sway_output *output, + struct sway_view *view, struct wlr_surface *surface, + struct wlr_box *box, void *user_data) { + surface_update_outputs(surface); +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, commit); struct wlr_output_event_commit *event = data; @@ -873,6 +917,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { if (event->committed & WLR_OUTPUT_STATE_SCALE) { output_for_each_container(output, update_textures, NULL); + output_for_each_surface(output, update_output_scale_iterator, NULL); } if (event->committed & (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 2b7214c35..a4d633e09 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -32,7 +32,7 @@ #endif struct render_data { - pixman_region32_t *damage; + const pixman_region32_t *damage; float alpha; struct wlr_box *clip_box; }; @@ -102,7 +102,7 @@ static void set_scale_filter(struct wlr_output *wlr_output, } static void render_texture(struct wlr_output *wlr_output, - pixman_region32_t *output_damage, struct wlr_texture *texture, + const pixman_region32_t *output_damage, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], float alpha) { struct wlr_renderer *renderer = wlr_output->renderer; @@ -139,7 +139,7 @@ static void render_surface_iterator(struct sway_output *output, struct wlr_box *_box, void *_data) { struct render_data *data = _data; struct wlr_output *wlr_output = output->wlr_output; - pixman_region32_t *output_damage = data->damage; + const pixman_region32_t *output_damage = data->damage; float alpha = data->alpha; struct wlr_texture *texture = wlr_surface_get_texture(surface); @@ -175,7 +175,7 @@ static void render_surface_iterator(struct sway_output *output, } static void render_layer_toplevel(struct sway_output *output, - pixman_region32_t *damage, struct wl_list *layer_surfaces) { + const pixman_region32_t *damage, struct wl_list *layer_surfaces) { struct render_data data = { .damage = damage, .alpha = 1.0f, @@ -185,7 +185,7 @@ static void render_layer_toplevel(struct sway_output *output, } static void render_layer_popups(struct sway_output *output, - pixman_region32_t *damage, struct wl_list *layer_surfaces) { + const pixman_region32_t *damage, struct wl_list *layer_surfaces) { struct render_data data = { .damage = damage, .alpha = 1.0f, @@ -196,7 +196,7 @@ static void render_layer_popups(struct sway_output *output, #if HAVE_XWAYLAND static void render_unmanaged(struct sway_output *output, - pixman_region32_t *damage, struct wl_list *unmanaged) { + const pixman_region32_t *damage, struct wl_list *unmanaged) { struct render_data data = { .damage = damage, .alpha = 1.0f, @@ -207,7 +207,7 @@ static void render_unmanaged(struct sway_output *output, #endif static void render_drag_icons(struct sway_output *output, - pixman_region32_t *damage, struct wl_list *drag_icons) { + const pixman_region32_t *damage, struct wl_list *drag_icons) { struct render_data data = { .damage = damage, .alpha = 1.0f, @@ -219,7 +219,7 @@ static void render_drag_icons(struct sway_output *output, // _box.x and .y are expected to be layout-local // _box.width and .height are expected to be output-buffer-local void render_rect(struct sway_output *output, - pixman_region32_t *output_damage, const struct wlr_box *_box, + const pixman_region32_t *output_damage, const struct wlr_box *_box, float color[static 4]) { struct wlr_output *wlr_output = output->wlr_output; struct wlr_renderer *renderer = wlr_output->renderer; @@ -259,7 +259,7 @@ void premultiply_alpha(float color[4], float opacity) { } static void render_view_toplevels(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct sway_output *output, const pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, @@ -282,7 +282,7 @@ static void render_view_toplevels(struct sway_view *view, } static void render_view_popups(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct sway_output *output, const pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, @@ -292,7 +292,7 @@ static void render_view_popups(struct sway_view *view, } static void render_saved_view(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct sway_output *output, const pixman_region32_t *damage, float alpha) { struct wlr_output *wlr_output = output->wlr_output; if (wl_list_empty(&view->saved_buffers)) { @@ -355,7 +355,7 @@ static void render_saved_view(struct sway_view *view, /** * Render a view's surface and left/bottom/right borders. */ -static void render_view(struct sway_output *output, pixman_region32_t *damage, +static void render_view(struct sway_output *output, const pixman_region32_t *damage, struct sway_container *con, struct border_colors *colors) { struct sway_view *view = con->view; if (!wl_list_empty(&view->saved_buffers)) { @@ -429,7 +429,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, * The left side is: 1px border, 2px padding, title */ static void render_titlebar(struct sway_output *output, - pixman_region32_t *output_damage, struct sway_container *con, + const pixman_region32_t *output_damage, struct sway_container *con, int x, int y, int width, struct border_colors *colors, struct wlr_texture *title_texture, struct wlr_texture *marks_texture) { @@ -684,7 +684,7 @@ static void render_titlebar(struct sway_output *output, * Render the top border line for a view using "border pixel". */ static void render_top_border(struct sway_output *output, - pixman_region32_t *output_damage, struct sway_container *con, + const pixman_region32_t *output_damage, struct sway_container *con, struct border_colors *colors) { struct sway_container_state *state = &con->current; if (!state->border_top) { @@ -714,7 +714,7 @@ struct parent_data { }; static void render_container(struct sway_output *output, - pixman_region32_t *damage, struct sway_container *con, bool parent_focused); + const pixman_region32_t *damage, struct sway_container *con, bool parent_focused); /** * Render a container's children using a L_HORIZ or L_VERT layout. @@ -723,7 +723,7 @@ static void render_container(struct sway_output *output, * they'll apply their own borders to their children. */ static void render_containers_linear(struct sway_output *output, - pixman_region32_t *damage, struct parent_data *parent) { + const pixman_region32_t *damage, struct parent_data *parent) { for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; @@ -779,7 +779,7 @@ static bool container_has_focused_child(struct sway_container *con) { * Render a container's children using the L_TABBED layout. */ static void render_containers_tabbed(struct sway_output *output, - pixman_region32_t *damage, struct parent_data *parent) { + const pixman_region32_t *damage, struct parent_data *parent) { if (!parent->children->length) { return; } @@ -848,7 +848,7 @@ static void render_containers_tabbed(struct sway_output *output, * Render a container's children using the L_STACKED layout. */ static void render_containers_stacked(struct sway_output *output, - pixman_region32_t *damage, struct parent_data *parent) { + const pixman_region32_t *damage, struct parent_data *parent) { if (!parent->children->length) { return; } @@ -908,7 +908,7 @@ static void render_containers_stacked(struct sway_output *output, } static void render_containers(struct sway_output *output, - pixman_region32_t *damage, struct parent_data *parent) { + const pixman_region32_t *damage, struct parent_data *parent) { if (config->hide_lone_tab && parent->children->length == 1) { struct sway_container *child = parent->children->items[0]; if (child->view) { @@ -933,7 +933,7 @@ static void render_containers(struct sway_output *output, } static void render_container(struct sway_output *output, - pixman_region32_t *damage, struct sway_container *con, bool focused) { + const pixman_region32_t *damage, struct sway_container *con, bool focused) { struct parent_data data = { .layout = con->current.layout, .box = { @@ -950,7 +950,7 @@ static void render_container(struct sway_output *output, } static void render_workspace(struct sway_output *output, - pixman_region32_t *damage, struct sway_workspace *ws, bool focused) { + const pixman_region32_t *damage, struct sway_workspace *ws, bool focused) { struct parent_data data = { .layout = ws->current.layout, .box = { @@ -967,7 +967,7 @@ static void render_workspace(struct sway_output *output, } static void render_floating_container(struct sway_output *soutput, - pixman_region32_t *damage, struct sway_container *con) { + const pixman_region32_t *damage, struct sway_container *con) { if (con->view) { struct sway_view *view = con->view; struct border_colors *colors; @@ -1002,7 +1002,7 @@ static void render_floating_container(struct sway_output *soutput, } static void render_floating(struct sway_output *soutput, - pixman_region32_t *damage) { + const pixman_region32_t *damage) { for (int i = 0; i < root->outputs->length; ++i) { struct sway_output *output = root->outputs->items[i]; for (int j = 0; j < output->current.workspaces->length; ++j) { @@ -1022,15 +1022,14 @@ static void render_floating(struct sway_output *soutput, } static void render_seatops(struct sway_output *output, - pixman_region32_t *damage) { + const pixman_region32_t *damage) { struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { seatop_render(seat, output, damage); } } -void output_render(struct sway_output *output, struct timespec *when, - pixman_region32_t *damage) { +void output_render(struct sway_output *output, pixman_region32_t *damage) { struct wlr_output *wlr_output = output->wlr_output; struct wlr_renderer *renderer = output->server->renderer; @@ -1184,30 +1183,4 @@ renderer_end: wlr_renderer_scissor(renderer, NULL); wlr_output_render_software_cursors(wlr_output, damage); wlr_renderer_end(renderer); - - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - - pixman_region32_t frame_damage; - pixman_region32_init(&frame_damage); - - enum wl_output_transform transform = - wlr_output_transform_invert(wlr_output->transform); - wlr_region_transform(&frame_damage, &output->damage_ring.current, - transform, width, height); - - if (debug.damage != DAMAGE_DEFAULT) { - pixman_region32_union_rect(&frame_damage, &frame_damage, - 0, 0, wlr_output->width, wlr_output->height); - } - - wlr_output_set_damage(wlr_output, &frame_damage); - pixman_region32_fini(&frame_damage); - - if (!wlr_output_commit(wlr_output)) { - return; - } - - wlr_damage_ring_rotate(&output->damage_ring); - output->last_frame = *when; } diff --git a/sway/desktop/surface.c b/sway/desktop/surface.c index 949cfdc26..68772ee0f 100644 --- a/sway/desktop/surface.c +++ b/sway/desktop/surface.c @@ -47,7 +47,7 @@ void handle_compositor_new_surface(struct wl_listener *listener, void *data) { } } -static void surface_update_outputs(struct wlr_surface *surface) { +void surface_update_outputs(struct wlr_surface *surface) { float scale = 1; struct wlr_surface_output *surface_output; wl_list_for_each(surface_output, &surface->current_outputs, link) { diff --git a/sway/input/cursor.c b/sway/input/cursor.c index ad69e7c39..15687993b 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -364,7 +364,7 @@ void cursor_unhide(struct sway_cursor *cursor) { wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor)); } -static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, +void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, struct wlr_input_device *device, double dx, double dy, double dx_unaccel, double dy_unaccel) { wlr_relative_pointer_manager_v1_send_relative_motion( @@ -479,43 +479,16 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { cursor_hide(cursor); struct sway_seat *seat = cursor->seat; - struct wlr_seat *wlr_seat = seat->wlr_seat; - struct wlr_surface *surface = NULL; double lx, ly; wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, event->x, event->y, &lx, &ly); - double sx, sy; - struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy); seat->touch_id = event->touch_id; seat->touch_x = lx; seat->touch_y = ly; - if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { - if (seat_is_input_allowed(seat, surface)) { - wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec, - event->touch_id, sx, sy); - - if (focused_node) { - seat_set_focus(seat, focused_node); - } - } - } else if (!cursor->simulating_pointer_from_touch && - (!surface || seat_is_input_allowed(seat, surface))) { - // Fallback to cursor simulation. - // The pointer_touch_id state is needed, so drags are not aborted when over - // a surface supporting touch and multi touch events don't interfere. - cursor->simulating_pointer_from_touch = true; - cursor->pointer_touch_id = seat->touch_id; - double dx, dy; - dx = lx - cursor->cursor->x; - dy = ly - cursor->cursor->y; - pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, - dx, dy); - dispatch_cursor_button(cursor, &event->touch->base, event->time_msec, - BTN_LEFT, WLR_BUTTON_PRESSED); - } + seatop_touch_down(seat, event, lx, ly); } static void handle_touch_up(struct wl_listener *listener, void *data) { @@ -523,7 +496,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { struct wlr_touch_up_event *event = data; cursor_handle_activity_from_device(cursor, &event->touch->base); - struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; + struct sway_seat *seat = cursor->seat; if (cursor->simulating_pointer_from_touch) { if (cursor->pointer_touch_id == cursor->seat->touch_id) { @@ -532,7 +505,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); } } else { - wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); + seatop_touch_up(seat, event); } } @@ -543,19 +516,14 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { cursor_handle_activity_from_device(cursor, &event->touch->base); struct sway_seat *seat = cursor->seat; - struct wlr_seat *wlr_seat = seat->wlr_seat; - struct wlr_surface *surface = NULL; double lx, ly; wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, event->x, event->y, &lx, &ly); - double sx, sy; - node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy); if (seat->touch_id == event->touch_id) { seat->touch_x = lx; seat->touch_y = ly; - struct sway_drag_icon *drag_icon; wl_list_for_each(drag_icon, &root->drag_icons, link) { if (drag_icon->seat == seat) { @@ -572,9 +540,8 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, dx, dy); } - } else if (surface) { - wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, - event->touch_id, sx, sy); + } else { + seatop_touch_motion(seat, event, lx, ly); } } diff --git a/sway/input/libinput.c b/sway/input/libinput.c index 10bd0e35a..dd4fc0be9 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c @@ -220,7 +220,8 @@ bool sway_input_configure_libinput_device(struct sway_input_device *input_device bool changed = false; if (ic->mapped_to_output && - !output_by_name_or_id(ic->mapped_to_output)) { + strcmp("*", ic->mapped_to_output) != 0 && + !output_by_name_or_id(ic->mapped_to_output)) { sway_log(SWAY_DEBUG, "%s '%s' is mapped to offline output '%s'; disabling input", ic->input_type, ic->identifier, ic->mapped_to_output); diff --git a/sway/input/seat.c b/sway/input/seat.c index 090a4d3ca..14931ce0f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1618,6 +1618,26 @@ void seatop_pointer_axis(struct sway_seat *seat, } } +void seatop_touch_motion(struct sway_seat *seat, struct wlr_touch_motion_event *event, + double lx, double ly) { + if (seat->seatop_impl->touch_motion) { + seat->seatop_impl->touch_motion(seat, event, lx, ly); + } +} + +void seatop_touch_up(struct sway_seat *seat, struct wlr_touch_up_event *event) { + if (seat->seatop_impl->touch_up) { + seat->seatop_impl->touch_up(seat, event); + } +} + +void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *event, + double lx, double ly) { + if (seat->seatop_impl->touch_down) { + seat->seatop_impl->touch_down(seat, event, lx, ly); + } +} + void seatop_tablet_tool_tip(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec, enum wlr_tablet_tool_tip_state state) { @@ -1707,7 +1727,7 @@ void seatop_end(struct sway_seat *seat) { } void seatop_render(struct sway_seat *seat, struct sway_output *output, - pixman_region32_t *damage) { + const pixman_region32_t *damage) { if (seat->seatop_impl->render) { seat->seatop_impl->render(seat, output, damage); } diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 0dcb87ab0..5a55c1866 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -261,7 +261,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, // Handle tapping on a container surface seat_set_focus_container(seat, cont); - seatop_begin_down(seat, node->sway_container, time_msec, sx, sy); + seatop_begin_down(seat, node->sway_container, sx, sy); } #if HAVE_XWAYLAND // Handle tapping on an xwayland unmanaged view @@ -374,7 +374,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, transaction_commit_dirty(); } if (state == WLR_BUTTON_PRESSED) { - seatop_begin_down_on_surface(seat, surface, time_msec, sx, sy); + seatop_begin_down_on_surface(seat, surface, sx, sy); } seat_pointer_notify_button(seat, time_msec, button, state); return; @@ -499,7 +499,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, // Handle mousedown on a container surface if (surface && cont && state == WLR_BUTTON_PRESSED) { - seatop_begin_down(seat, cont, time_msec, sx, sy); + seatop_begin_down(seat, cont, sx, sy); seat_pointer_notify_button(seat, time_msec, button, WLR_BUTTON_PRESSED); return; } @@ -649,6 +649,36 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, e->previous_node = node; } +static void handle_touch_down(struct sway_seat *seat, + struct wlr_touch_down_event *event, double lx, double ly) { + struct wlr_surface *surface = NULL; + struct wlr_seat *wlr_seat = seat->wlr_seat; + struct sway_cursor *cursor = seat->cursor; + double sx, sy; + node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy); + + if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { + if (seat_is_input_allowed(seat, surface)) { + cursor->simulating_pointer_from_touch = false; + seatop_begin_touch_down(seat, surface, event, sx, sy, lx, ly); + } + } else if (!cursor->simulating_pointer_from_touch && + (!surface || seat_is_input_allowed(seat, surface))) { + // Fallback to cursor simulation. + // The pointer_touch_id state is needed, so drags are not aborted when over + // a surface supporting touch and multi touch events don't interfere. + cursor->simulating_pointer_from_touch = true; + cursor->pointer_touch_id = seat->touch_id; + double dx, dy; + dx = seat->touch_x - cursor->cursor->x; + dy = seat->touch_y - cursor->cursor->y; + pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, + dx, dy); + dispatch_cursor_button(cursor, &event->touch->base, event->time_msec, + BTN_LEFT, WLR_BUTTON_PRESSED); + } +} + /*----------------------------------------\ * Functions used by handle_pointer_axis / *--------------------------------------*/ @@ -1096,6 +1126,7 @@ static const struct sway_seatop_impl seatop_impl = { .swipe_begin = handle_swipe_begin, .swipe_update = handle_swipe_update, .swipe_end = handle_swipe_end, + .touch_down = handle_touch_down, .rebase = handle_rebase, .allow_set_cursor = true, }; diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 3f880ccf9..6447134ec 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -2,12 +2,20 @@ #include <float.h> #include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_tablet_v2.h> +#include <wlr/types/wlr_touch.h> #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/tree/view.h" #include "sway/desktop/transaction.h" #include "log.h" +struct seatop_touch_point_event { + double ref_lx, ref_ly; // touch's x/y at start of op + double ref_con_lx, ref_con_ly; // container's x/y at start of op + int32_t touch_id; + struct wl_list link; +}; + struct seatop_down_event { struct sway_container *con; struct sway_seat *seat; @@ -15,8 +23,87 @@ struct seatop_down_event { struct wlr_surface *surface; double ref_lx, ref_ly; // cursor's x/y at start of op double ref_con_lx, ref_con_ly; // container's x/y at start of op + struct wl_list point_events; // seatop_touch_point_event::link }; +static void handle_touch_motion(struct sway_seat *seat, + struct wlr_touch_motion_event *event, double lx, double ly) { + struct seatop_down_event *e = seat->seatop_data; + + struct seatop_touch_point_event *point_event; + bool found = false; + wl_list_for_each(point_event, &e->point_events, link) { + if (point_event->touch_id == event->touch_id) { + found = true; + break; + } + } + if (!found) { + return; // Probably not a point_event from this seatop_down + } + + double moved_x = lx - point_event->ref_lx; + double moved_y = ly - point_event->ref_ly; + double sx = point_event->ref_con_lx + moved_x; + double sy = point_event->ref_con_ly + moved_y; + + wlr_seat_touch_notify_motion(seat->wlr_seat, event->time_msec, + event->touch_id, sx, sy); +} + +static void handle_touch_up(struct sway_seat *seat, + struct wlr_touch_up_event *event) { + struct seatop_down_event *e = seat->seatop_data; + struct seatop_touch_point_event *point_event, *tmp; + + wl_list_for_each_safe(point_event, tmp, &e->point_events, link) { + if (point_event->touch_id == event->touch_id) { + wl_list_remove(&point_event->link); + free(point_event); + break; + } + } + + if (wl_list_empty(&e->point_events)) { + seatop_begin_default(seat); + } + + wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id); +} + +static void handle_touch_down(struct sway_seat *seat, + struct wlr_touch_down_event *event, double lx, double ly) { + struct seatop_down_event *e = seat->seatop_data; + double sx, sy; + struct wlr_surface *surface = NULL; + struct sway_node *focused_node = node_at_coords(seat, seat->touch_x, + seat->touch_y, &surface, &sx, &sy); + + if (!surface || surface != e->surface) { // Must start from the initial surface + return; + } + + struct seatop_touch_point_event *point_event = + calloc(1, sizeof(struct seatop_touch_point_event)); + if (!sway_assert(point_event, "Unable to allocate point_event")) { + return; + } + point_event->touch_id = event->touch_id; + point_event->ref_lx = lx; + point_event->ref_ly = ly; + point_event->ref_con_lx = sx; + point_event->ref_con_ly = sy; + + wl_list_insert(&e->point_events, &point_event->link); + + wlr_seat_touch_notify_down(seat->wlr_seat, surface, event->time_msec, + event->touch_id, sx, sy); + + if (focused_node) { + seat_set_focus(seat, focused_node); + } +} + static void handle_pointer_axis(struct sway_seat *seat, struct wlr_pointer_axis_event *event) { struct sway_input_device *input_device = @@ -99,14 +186,17 @@ static const struct sway_seatop_impl seatop_impl = { .pointer_axis = handle_pointer_axis, .tablet_tool_tip = handle_tablet_tool_tip, .tablet_tool_motion = handle_tablet_tool_motion, + .touch_motion = handle_touch_motion, + .touch_up = handle_touch_up, + .touch_down = handle_touch_down, .unref = handle_unref, .end = handle_end, .allow_set_cursor = true, }; void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, - uint32_t time_msec, double sx, double sy) { - seatop_begin_down_on_surface(seat, con->view->surface, time_msec, sx, sy); + double sx, double sy) { + seatop_begin_down_on_surface(seat, con->view->surface, sx, sy); struct seatop_down_event *e = seat->seatop_data; e->con = con; @@ -114,13 +204,20 @@ void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, transaction_commit_dirty(); } +void seatop_begin_touch_down(struct sway_seat *seat, + struct wlr_surface *surface, struct wlr_touch_down_event *event, + double sx, double sy, double lx, double ly) { + seatop_begin_down_on_surface(seat, surface, sx, sy); + handle_touch_down(seat, event, lx, ly); +} + void seatop_begin_down_on_surface(struct sway_seat *seat, - struct wlr_surface *surface, uint32_t time_msec, double sx, double sy) { + struct wlr_surface *surface, double sx, double sy) { seatop_end(seat); struct seatop_down_event *e = calloc(1, sizeof(struct seatop_down_event)); - if (!e) { + if (!sway_assert(e, "Unable to allocate e")) { return; } e->con = NULL; @@ -132,6 +229,7 @@ void seatop_begin_down_on_surface(struct sway_seat *seat, e->ref_ly = seat->cursor->cursor->y; e->ref_con_lx = sx; e->ref_con_ly = sy; + wl_list_init(&e->point_events); seat->seatop_impl = &seatop_impl; seat->seatop_data = e; diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 223c6c08c..5498e9092 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -32,7 +32,7 @@ struct seatop_move_tiling_event { }; static void handle_render(struct sway_seat *seat, - struct sway_output *output, pixman_region32_t *damage) { + struct sway_output *output, const pixman_region32_t *damage) { struct seatop_move_tiling_event *e = seat->seatop_data; if (!e->threshold_reached) { return; diff --git a/sway/tree/container.c b/sway/tree/container.c index 207010814..8222a5069 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -508,7 +508,6 @@ static void render_titlebar_text_texture(struct sway_output *output, cairo_t *c = cairo_create(dummy_surface); cairo_set_antialias(c, CAIRO_ANTIALIAS_BEST); cairo_font_options_t *fo = cairo_font_options_create(); - cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); if (output->wlr_output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) { cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); } else { @@ -1764,3 +1763,177 @@ int container_squash(struct sway_container *con) { } return change; } + +static void swap_places(struct sway_container *con1, + struct sway_container *con2) { + struct sway_container *temp = malloc(sizeof(struct sway_container)); + temp->pending.x = con1->pending.x; + temp->pending.y = con1->pending.y; + temp->pending.width = con1->pending.width; + temp->pending.height = con1->pending.height; + temp->width_fraction = con1->width_fraction; + temp->height_fraction = con1->height_fraction; + temp->pending.parent = con1->pending.parent; + temp->pending.workspace = con1->pending.workspace; + bool temp_floating = container_is_floating(con1); + + con1->pending.x = con2->pending.x; + con1->pending.y = con2->pending.y; + con1->pending.width = con2->pending.width; + con1->pending.height = con2->pending.height; + con1->width_fraction = con2->width_fraction; + con1->height_fraction = con2->height_fraction; + + con2->pending.x = temp->pending.x; + con2->pending.y = temp->pending.y; + con2->pending.width = temp->pending.width; + con2->pending.height = temp->pending.height; + con2->width_fraction = temp->width_fraction; + con2->height_fraction = temp->height_fraction; + + int temp_index = container_sibling_index(con1); + if (con2->pending.parent) { + container_insert_child(con2->pending.parent, con1, + container_sibling_index(con2)); + } else if (container_is_floating(con2)) { + workspace_add_floating(con2->pending.workspace, con1); + } else { + workspace_insert_tiling(con2->pending.workspace, con1, + container_sibling_index(con2)); + } + if (temp->pending.parent) { + container_insert_child(temp->pending.parent, con2, temp_index); + } else if (temp_floating) { + workspace_add_floating(temp->pending.workspace, con2); + } else { + workspace_insert_tiling(temp->pending.workspace, con2, temp_index); + } + + free(temp); +} + +static void swap_focus(struct sway_container *con1, + struct sway_container *con2, struct sway_seat *seat, + struct sway_container *focus) { + if (focus == con1 || focus == con2) { + struct sway_workspace *ws1 = con1->pending.workspace; + struct sway_workspace *ws2 = con2->pending.workspace; + enum sway_container_layout layout1 = container_parent_layout(con1); + enum sway_container_layout layout2 = container_parent_layout(con2); + if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) { + if (workspace_is_visible(ws2)) { + seat_set_focus(seat, &con2->node); + } + seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1); + } else if (focus == con2 && (layout1 == L_TABBED + || layout1 == L_STACKED)) { + if (workspace_is_visible(ws1)) { + seat_set_focus(seat, &con1->node); + } + seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2); + } else if (ws1 != ws2) { + seat_set_focus_container(seat, focus == con1 ? con2 : con1); + } else { + seat_set_focus_container(seat, focus); + } + } else { + seat_set_focus_container(seat, focus); + } + + if (root->fullscreen_global) { + seat_set_focus(seat, + seat_get_focus_inactive(seat, &root->fullscreen_global->node)); + } +} + +void container_swap(struct sway_container *con1, struct sway_container *con2) { + if (!sway_assert(con1 && con2, "Cannot swap with nothing")) { + return; + } + if (!sway_assert(!container_has_ancestor(con1, con2) + && !container_has_ancestor(con2, con1), + "Cannot swap ancestor and descendant")) { + return; + } + + sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu", + con1->node.id, con2->node.id); + + bool scratch1 = con1->scratchpad; + bool hidden1 = container_is_scratchpad_hidden(con1); + bool scratch2 = con2->scratchpad; + bool hidden2 = container_is_scratchpad_hidden(con2); + if (scratch1) { + if (hidden1) { + root_scratchpad_show(con1); + } + root_scratchpad_remove_container(con1); + } + if (scratch2) { + if (hidden2) { + root_scratchpad_show(con2); + } + root_scratchpad_remove_container(con2); + } + + enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode; + if (fs1) { + container_fullscreen_disable(con1); + } + enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode; + if (fs2) { + container_fullscreen_disable(con2); + } + + struct sway_seat *seat = input_manager_current_seat(); + struct sway_container *focus = seat_get_focused_container(seat); + struct sway_workspace *vis1 = + output_get_active_workspace(con1->pending.workspace->output); + struct sway_workspace *vis2 = + output_get_active_workspace(con2->pending.workspace->output); + if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a" + "workspace. This should not happen")) { + return; + } + + char *stored_prev_name = NULL; + if (seat->prev_workspace_name) { + stored_prev_name = strdup(seat->prev_workspace_name); + } + + swap_places(con1, con2); + + if (!workspace_is_visible(vis1)) { + seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node)); + } + if (!workspace_is_visible(vis2)) { + seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node)); + } + + swap_focus(con1, con2, seat, focus); + + if (stored_prev_name) { + free(seat->prev_workspace_name); + seat->prev_workspace_name = stored_prev_name; + } + + if (scratch1) { + root_scratchpad_add_container(con2, NULL); + if (!hidden1) { + root_scratchpad_show(con2); + } + } + if (scratch2) { + root_scratchpad_add_container(con1, NULL); + if (!hidden2) { + root_scratchpad_show(con1); + } + } + + if (fs1) { + container_set_fullscreen(con2, fs1); + } + if (fs2) { + container_set_fullscreen(con1, fs2); + } +} diff --git a/sway/tree/view.c b/sway/tree/view.c index fcb78de36..ec54fed81 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -369,16 +369,13 @@ void view_set_activated(struct sway_view *view, bool activated) { void view_request_activate(struct sway_view *view, struct sway_seat *seat) { struct sway_workspace *ws = view->container->pending.workspace; - if (!ws) { // hidden scratchpad container - return; - } if (!seat) { seat = input_manager_current_seat(); } switch (config->focus_on_window_activation) { case FOWA_SMART: - if (workspace_is_visible(ws)) { + if (ws && workspace_is_visible(ws)) { seat_set_focus_container(seat, view->container); container_raise_floating(view->container); } else { @@ -389,8 +386,12 @@ void view_request_activate(struct sway_view *view, struct sway_seat *seat) { view_set_urgent(view, true); break; case FOWA_FOCUS: - seat_set_focus_container(seat, view->container); - container_raise_floating(view->container); + if (container_is_scratchpad_hidden_or_child(view->container)) { + root_scratchpad_show(view->container); + } else { + seat_set_focus_container(seat, view->container); + container_raise_floating(view->container); + } break; case FOWA_NONE: break; diff --git a/swaybar/render.c b/swaybar/render.c index ccf365637..6a983e97d 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -774,14 +774,12 @@ void render_frame(struct swaybar_output *output) { ctx.cairo = cairo; cairo_font_options_t *fo = cairo_font_options_create(); - cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); ctx.textaa_safe = fo; if (output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) { ctx.textaa_sharp = ctx.textaa_safe; } else { fo = cairo_font_options_create(); - cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->subpixel)); diff --git a/swaymsg/main.c b/swaymsg/main.c index 4d3fa68c2..db9346c4b 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -60,7 +60,7 @@ static void pretty_print_cmd(json_object *r) { if (!success_object(r)) { json_object *error; if (!json_object_object_get_ex(r, "error", &error)) { - printf("An unknkown error occurred"); + printf("An unknown error occurred"); } else { printf("Error: %s\n", json_object_get_string(error)); }