Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: when clicking in gaps, redirect the input to the closest window #357

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/sway/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ sway_cmd cmd_rename;
sway_cmd cmd_resize;
sway_cmd cmd_scratchpad;
sway_cmd cmd_scratchpad_minimize;
sway_cmd cmd_gap_click_redirect;
sway_cmd cmd_seamless_mouse;
sway_cmd cmd_set;
sway_cmd cmd_shortcuts_inhibitor;
Expand Down
1 change: 1 addition & 0 deletions include/sway/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ struct sway_config {

bool titlebar_separator;
bool scratchpad_minimize;
bool gap_click_redirect;

list_t *layer_criteria;

Expand Down
4 changes: 4 additions & 0 deletions include/sway/tree/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ struct sway_container *tiling_container_at(
struct sway_node *parent, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy);

struct sway_container *closest_tiling_container_at(
struct sway_node *parent, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy, double *distanceSquared);

void container_for_each_child(struct sway_container *container,
void (*f)(struct sway_container *container, void *data), void *data);

Expand Down
1 change: 1 addition & 0 deletions sway/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ static const struct cmd_handler handlers[] = {
{ "force_display_urgency_hint", cmd_force_display_urgency_hint },
{ "force_focus_wrapping", cmd_force_focus_wrapping },
{ "fullscreen", cmd_fullscreen },
{ "gap_click_redirect", cmd_gap_click_redirect },
{ "gaps", cmd_gaps },
{ "hide_edge_borders", cmd_hide_edge_borders },
{ "input", cmd_input },
Expand Down
16 changes: 16 additions & 0 deletions sway/commands/gap_click_redirect.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <string.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "util.h"

struct cmd_results *cmd_gap_click_redirect(int argc, char **argv) {
struct cmd_results *error = checkarg(argc, "gap_click_redirect", EXPECTED_AT_LEAST, 1);

if (error) {
return error;
}

config->gap_click_redirect = parse_boolean(argv[0], config->gap_click_redirect);

return cmd_results_new(CMD_SUCCESS, NULL);
}
1 change: 1 addition & 0 deletions sway/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ static void config_defaults(struct sway_config *config) {

config->titlebar_separator = true;
config->scratchpad_minimize = false;
config->gap_click_redirect = false;

if (!(config->layer_criteria = create_list())) goto cleanup;

Expand Down
8 changes: 8 additions & 0 deletions sway/input/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,14 @@ struct sway_node *node_at_coords(
return NULL;
}

if(config->gap_click_redirect) {
double distanceSquared;
struct sway_container *closest_container = closest_tiling_container_at(&ws->node, lx, ly, surface, sx, sy, &distanceSquared);
if(closest_container) {
return &closest_container->node;
}
}

return &ws->node;
}

Expand Down
1 change: 1 addition & 0 deletions sway/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ sway_sources = files(
'commands/saturation.c',
'commands/scratchpad.c',
'commands/scratchpad_minimize.c',
'commands/gap_click_redirect.c',
'commands/seat.c',
'commands/seat/attach.c',
'commands/seat/cursor.c',
Expand Down
81 changes: 81 additions & 0 deletions sway/tree/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <drm_fourcc.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_linux_dmabuf_v1.h>
#include <wlr/types/wlr_output_layout.h>
Expand Down Expand Up @@ -438,6 +439,86 @@ struct sway_container *container_at(struct sway_workspace *workspace,
return NULL;
}


static struct sway_container *closest_view_container_at(struct sway_node *parent,
double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy, double *distanceSquared) {
if (!sway_assert(node_is_view(parent), "Expected a view")) {
return NULL;
}

struct sway_container* container = parent->sway_container;
struct wlr_box box = {
.x = container->pending.content_x,
.y = container->pending.content_y,
.width = container->pending.content_width,
.height = container->pending.content_height,
};

double closest_x, closest_y;
wlr_box_closest_point(&box, lx, ly, &closest_x, &closest_y);

double dx = fabs(closest_x - lx);
double dy = fabs(closest_y - ly);
*distanceSquared = dx * dx + dy * dy;

if (surface_at_view(container, closest_x, closest_y, surface, sx, sy)) {
return container;
}

return NULL;
}

static struct sway_container *closest_container_at_linear(struct sway_node *parent,
double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy, double *distanceSquared) {
list_t *children = node_get_children(parent);

*distanceSquared = DBL_MAX;
struct sway_container *closestContainer = NULL;

for (int i = 0; i < children->length; ++i) {
struct sway_container *child = children->items[i];

double containerDistance, containerSx, containerSy;
struct wlr_surface *containerSurface = NULL;
struct sway_container *container = closest_tiling_container_at(&child->node, lx, ly, &containerSurface, &containerSx, &containerSy, &containerDistance);
if (container && containerDistance < *distanceSquared) {
*distanceSquared = containerDistance;
*sx = containerSx;
*sy = containerSy;
*surface = containerSurface;
closestContainer = container;
}
}

return closestContainer;
}

struct sway_container *closest_tiling_container_at(struct sway_node *parent,
double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy, double *distanceSquared) {
if (node_is_view(parent)) {
return closest_view_container_at(parent, lx, ly, surface, sx, sy, distanceSquared);
}
if (!node_get_children(parent)) {
return NULL;
}

switch (node_get_layout(parent)) {
case L_HORIZ:
case L_VERT:
return closest_container_at_linear(parent, lx, ly, surface, sx, sy, distanceSquared);
case L_TABBED:
case L_STACKED:
case L_NONE:
return NULL;
}

return NULL;
}


void container_for_each_child(struct sway_container *container,
void (*f)(struct sway_container *container, void *data),
void *data) {
Expand Down