diff --git a/.mailmap b/.mailmap new file mode 100644 index 000000000..35ee25b0c --- /dev/null +++ b/.mailmap @@ -0,0 +1 @@ +Ronan Pigott diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 751612e2c..fe3ee8a8b 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -113,6 +113,11 @@ struct sway_container { // Hidden scratchpad containers have a NULL parent. bool scratchpad; + // Stores last output size and position for adjusting coordinates of + // scratchpad windows. + // Unused for non-scratchpad windows. + struct wlr_box transform; + float alpha; struct wlr_texture *title_focused; @@ -196,6 +201,9 @@ size_t container_titlebar_height(void); void floating_calculate_constraints(int *min_width, int *max_width, int *min_height, int *max_height); +void floating_fix_coordinates(struct sway_container *con, + struct wlr_box *old, struct wlr_box *new); + void container_floating_resize_and_center(struct sway_container *con); void container_floating_set_default_size(struct sway_container *con); diff --git a/meson.build b/meson.build index 84e7c6c56..d1fbfa38a 100644 --- a/meson.build +++ b/meson.build @@ -117,6 +117,11 @@ conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind') conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu') conf_data.set10('HAVE_TRAY', have_tray) +conf_data.set10('HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', cc.has_header_symbol( + 'libinput.h', + 'LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', + dependencies: libinput, +)) scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) if scdoc.found() diff --git a/sway/commands/move.c b/sway/commands/move.c index 7bd1fe3e1..9e40a3b47 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -206,9 +206,17 @@ static void container_move_to_workspace(struct sway_container *container, container_detach(container); workspace_add_floating(workspace, container); container_handle_fullscreen_reparent(container); - // If changing output, center it within the workspace + // If changing output, adjust the coordinates of the window. if (old_output != workspace->output && !container->pending.fullscreen_mode) { - container_floating_move_to_center(container); + struct wlr_box workspace_box, old_workspace_box; + workspace_get_box(workspace, &workspace_box); + workspace_get_box(old_workspace, &old_workspace_box); + floating_fix_coordinates(container, &old_workspace_box, &workspace_box); + if (container->scratchpad && workspace->output) { + struct wlr_box output_box; + output_get_box(workspace->output, &output_box); + container->transform = workspace_box; + } } } else { container_detach(container); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0c8a5fd41..09fc64627 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -999,6 +999,9 @@ void handle_new_output(struct wl_listener *listener, void *data) { } output->server = server; wlr_damage_ring_init(&output->damage_ring); + int width, height; + wlr_output_transformed_resolution(output->wlr_output, &width, &height); + wlr_damage_ring_set_bounds(&output->damage_ring, width, height); wl_signal_add(&wlr_output->events.destroy, &output->destroy); output->destroy.notify = handle_destroy; diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 51e6a9951..c7cbea013 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -935,6 +935,11 @@ static json_object *describe_libinput_device(struct libinput_device *device) { case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE: accel_profile = "adaptive"; break; +#if HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM + case LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM: + accel_profile = "custom"; + break; +#endif } json_object_object_add(object, "accel_profile", json_object_new_string(accel_profile)); diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 91c978d64..1662d55a3 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -228,6 +228,8 @@ correct seat. absolute coordinates (with respect to the global coordinate space). Specifying either value as 0 will not update that coordinate. + Deprecated: use the virtual-pointer Wayland protocol instead. + *seat* cursor press|release button[1-9]| Simulate pressing (or releasing) the specified mouse button on the specified seat. The button can either be provided as a button event name or @@ -236,6 +238,8 @@ correct seat. event will be simulated, however _press_ and _release_ will be ignored and both will occur. + Deprecated: use the virtual-pointer Wayland protocol instead. + *seat* fallback true|false Set this seat as the fallback seat. A fallback seat will attach any device not explicitly attached to another seat (similar to a "default" seat). @@ -251,6 +255,10 @@ correct seat. If _when-typing_ is enabled, then the cursor will be hidden whenever a key is pressed. + Be aware that this setting can interfere with input handling in games and + certain types of software (Gimp, Blender etc) that rely on simultaneous + input from mouse and keyboard. + *seat* idle_inhibit Sets the set of input event sources which can prevent the seat from becoming idle, as a space separated list of source names. Valid names are diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index 9c1a11e55..af925d054 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -264,6 +264,9 @@ void arrange_workspace(struct sway_workspace *workspace) { area->width, area->height, area->x, area->y); bool first_arrange = workspace->width == 0 && workspace->height == 0; + struct wlr_box prev_box; + workspace_get_box(workspace, &prev_box); + double prev_x = workspace->x - workspace->current_gaps.left; double prev_y = workspace->y - workspace->current_gaps.top; workspace->width = area->width; @@ -277,13 +280,14 @@ void arrange_workspace(struct sway_workspace *workspace) { if (!first_arrange && (diff_x != 0 || diff_y != 0)) { for (int i = 0; i < workspace->floating->length; ++i) { struct sway_container *floater = workspace->floating->items[i]; - container_floating_translate(floater, diff_x, diff_y); - double center_x = floater->pending.x + floater->pending.width / 2; - double center_y = floater->pending.y + floater->pending.height / 2; struct wlr_box workspace_box; workspace_get_box(workspace, &workspace_box); - if (!wlr_box_contains_point(&workspace_box, center_x, center_y)) { - container_floating_move_to_center(floater); + floating_fix_coordinates(floater, &prev_box, &workspace_box); + // Set transformation for scratchpad windows. + if (floater->scratchpad) { + struct wlr_box output_box; + output_get_box(output, &output_box); + floater->transform = output_box; } } } diff --git a/sway/tree/container.c b/sway/tree/container.c index 8222a5069..d2c4ffc44 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -712,6 +712,21 @@ void floating_calculate_constraints(int *min_width, int *max_width, } +void floating_fix_coordinates(struct sway_container *con, struct wlr_box *old, struct wlr_box *new) { + if (!old->width || !old->height) { + // Fall back to centering on the workspace. + container_floating_move_to_center(con); + } else { + int rel_x = con->pending.x - old->x + (con->pending.width / 2); + int rel_y = con->pending.y - old->y + (con->pending.height / 2); + + con->pending.x = new->x + (double)(rel_x * new->width) / old->width - (con->pending.width / 2); + con->pending.y = new->y + (double)(rel_y * new->height) / old->height - (con->pending.height / 2); + + sway_log(SWAY_DEBUG, "Transformed container %p to coords (%f, %f)", con, con->pending.x, con->pending.y); + } +} + static void floating_natural_resize(struct sway_container *con) { int min_width, max_width, min_height, max_height; floating_calculate_constraints(&min_width, &max_width, @@ -1025,6 +1040,13 @@ void container_floating_move_to(struct sway_container *con, workspace_add_floating(new_workspace, con); arrange_workspace(old_workspace); arrange_workspace(new_workspace); + // If the moved container was a visible scratchpad container, then + // update its transform. + if (con->scratchpad) { + struct wlr_box output_box; + output_get_box(new_output, &output_box); + con->transform = output_box; + } workspace_detect_urgent(old_workspace); workspace_detect_urgent(new_workspace); } diff --git a/sway/tree/root.c b/sway/tree/root.c index 95129a88f..831c75a58 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -56,6 +56,16 @@ void root_destroy(struct sway_root *root) { free(root); } +static void set_container_transform(struct sway_workspace *ws, + struct sway_container *con) { + struct sway_output *output = ws->output; + struct wlr_box box = {0}; + if (output) { + output_get_box(output, &box); + } + con->transform = box; +} + void root_scratchpad_add_container(struct sway_container *con, struct sway_workspace *ws) { if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { return; @@ -64,6 +74,8 @@ void root_scratchpad_add_container(struct sway_container *con, struct sway_works struct sway_container *parent = con->pending.parent; struct sway_workspace *workspace = con->pending.workspace; + set_container_transform(workspace, con); + // Clear the fullscreen mode when sending to the scratchpad if (con->pending.fullscreen_mode != FULLSCREEN_NONE) { container_fullscreen_disable(con); @@ -133,7 +145,10 @@ void root_scratchpad_show(struct sway_container *con) { // Show the container if (old_ws) { container_detach(con); - workspace_consider_destroy(old_ws); + // Make sure the last inactive container on the old workspace is above + // the workspace itself in the focus stack. + struct sway_node *node = seat_get_focus_inactive(seat, &old_ws->node); + seat_set_raw_focus(seat, node); } else { // Act on the ancestor of scratchpad hidden split containers while (con->pending.parent) { @@ -142,18 +157,18 @@ void root_scratchpad_show(struct sway_container *con) { } workspace_add_floating(new_ws, con); - // Make sure the container's center point overlaps this workspace - double center_lx = con->pending.x + con->pending.width / 2; - double center_ly = con->pending.y + con->pending.height / 2; - - struct wlr_box workspace_box; - workspace_get_box(new_ws, &workspace_box); - if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { - container_floating_resize_and_center(con); + if (new_ws->output) { + struct wlr_box output_box; + output_get_box(new_ws->output, &output_box); + floating_fix_coordinates(con, &con->transform, &output_box); } + set_container_transform(new_ws, con); arrange_workspace(new_ws); seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node)); + if (old_ws) { + workspace_consider_destroy(old_ws); + } } static void disable_fullscreen(struct sway_container *con, void *data) { @@ -173,6 +188,8 @@ void root_scratchpad_hide(struct sway_container *con) { return; } + set_container_transform(con->pending.workspace, con); + disable_fullscreen(con, NULL); container_for_each_child(con, disable_fullscreen, NULL); container_detach(con); diff --git a/swaybar/render.c b/swaybar/render.c index 6a983e97d..1113ca44a 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -693,15 +693,6 @@ static uint32_t render_to_cairo(struct render_context *ctx) { struct swaybar_output *output = ctx->output; struct swaybar *bar = output->bar; struct swaybar_config *config = bar->config; - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - if (output->focused) { - ctx->background_color = config->colors.focused_background; - } else { - ctx->background_color = config->colors.background; - } - - cairo_set_source_u32(cairo, ctx->background_color); - cairo_paint(cairo); int th; get_text_size(cairo, config->font_description, NULL, &th, NULL, 1, false, ""); @@ -763,8 +754,17 @@ void render_frame(struct swaybar_output *output) { free_hotspots(&output->hotspots); + uint32_t background_color; + if (output->focused) { + background_color = output->bar->config->colors.focused_background; + } else { + background_color = output->bar->config->colors.background; + } + struct render_context ctx = { 0 }; ctx.output = output; + // initial background color used for deciding the best way to antialias text + ctx.background_color = background_color; cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); @@ -786,10 +786,11 @@ void render_frame(struct swaybar_output *output) { ctx.textaa_sharp = fo; } - cairo_save(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); + + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_set_source_u32(cairo, background_color); cairo_paint(cairo); - cairo_restore(cairo); + uint32_t height = render_to_cairo(&ctx); int config_height = output->bar->config->height; if (config_height > 0) { @@ -834,13 +835,15 @@ void render_frame(struct swaybar_output *output) { wl_surface_damage(output->surface, 0, 0, output->width, output->height); - uint32_t bg_alpha = ctx.background_color & 0xFF; + uint32_t bg_alpha = background_color & 0xFF; if (bg_alpha == 0xFF) { struct wl_region *region = wl_compositor_create_region(output->bar->compositor); wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX); wl_surface_set_opaque_region(output->surface, region); wl_region_destroy(region); + } else { + wl_surface_set_opaque_region(output->surface, NULL); } struct wl_callback *frame_callback = wl_surface_frame(output->surface);