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

Add new "mouse_warping" setting: remembered. #5083

Open
wants to merge 1 commit into
base: next
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ typedef uint32_t i3_event_state_mask_t;
*/
typedef enum {
POINTER_WARPING_OUTPUT = 0,
POINTER_WARPING_NONE = 1
POINTER_WARPING_NONE = 1,
POINTER_WARPING_REMEMBERED = 2
} warping_t;

/**
Expand Down Expand Up @@ -384,6 +385,9 @@ struct xoutput {
/** x, y, width, height */
Rect rect;

/** remembered location of mouse pointer on this output */
int remembered_x, remembered_y;

TAILQ_ENTRY(xoutput) outputs;
};

Expand Down
2 changes: 1 addition & 1 deletion parser-specs/config.spec
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ state FOCUS_FOLLOWS_MOUSE:

# mouse_warping warping_t
state MOUSE_WARPING:
value = 'none', 'output'
value = 'none', 'output', 'remembered'
-> call cfg_mouse_warping($value)

# focus_wrapping
Expand Down
2 changes: 2 additions & 0 deletions src/config_directives.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,8 @@ CFGFUN(mouse_warping, const char *value) {
config.mouse_warping = POINTER_WARPING_NONE;
else if (strcmp(value, "output") == 0)
config.mouse_warping = POINTER_WARPING_OUTPUT;
else if (strcmp(value, "remembered") == 0)
config.mouse_warping = POINTER_WARPING_REMEMBERED;
}

CFGFUN(force_xinerama, const char *value) {
Expand Down
2 changes: 2 additions & 0 deletions src/fake_outputs.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ void fake_outputs_init(const char *output_spec) {
new_output->rect.y = y;
new_output->rect.width = width;
new_output->rect.height = height;
new_output->remembered_x = -1;
new_output->remembered_y = -1;
/* We always treat the screen at 0x0 as the primary screen */
if (new_output->rect.x == 0 && new_output->rect.y == 0)
TAILQ_INSERT_HEAD(&outputs, new_output, outputs);
Expand Down
8 changes: 8 additions & 0 deletions src/randr.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ Output *create_root_output(xcb_connection_t *conn) {
s->rect.y = 0;
s->rect.width = root_screen->width_in_pixels;
s->rect.height = root_screen->height_in_pixels;
s->remembered_x = -1;
s->remembered_y = -1;

struct output_name *output_name = scalloc(1, sizeof(struct output_name));
output_name->name = "xroot-0";
Expand Down Expand Up @@ -663,6 +665,9 @@ static bool randr_query_outputs_15(void) {
new->active = true;
new->to_be_disabled = false;

new->remembered_x = -1;
new->remembered_y = -1;

new->primary = monitor_info->primary;

const bool update_x = update_if_necessary(&(new->rect.x), monitor_info->x);
Expand Down Expand Up @@ -756,6 +761,9 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
return;
}

new->remembered_x = -1;
new->remembered_y = -1;

DLOG("mode: %dx%d+%d+%d\n", new->rect.width, new->rect.height,
new->rect.x, new->rect.y);

Expand Down
18 changes: 17 additions & 1 deletion src/x.c
Original file line number Diff line number Diff line change
Expand Up @@ -1286,9 +1286,25 @@ void x_push_changes(Con *con) {
Output *current = get_output_containing(pointerreply->root_x, pointerreply->root_y);
Output *target = get_output_containing(mid_x, mid_y);
if (current != target) {
current->remembered_x = pointerreply->root_x;
current->remembered_y = pointerreply->root_y;

/* Ignore MotionNotify events generated by warping */
xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT});
xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, mid_x, mid_y);
if(config.mouse_warping == POINTER_WARPING_REMEMBERED && target->remembered_x > -1 && target->remembered_y > -1) {
xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, target->remembered_x, target->remembered_y);
DLOG("warping pointer to remembered location: %d, %d\n", target->remembered_x, target->remembered_y);

/* Now that we've warped to the remembered location on the
* target output, forget that location so it's only
* re-remembered if we warp out again (this enforces
* correct behavior when changing focus with mouse).
*/
target->remembered_x = target->remembered_y = -1;
} else {
xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, mid_x, mid_y);
DLOG("warping pointer to default location: %d, %d\n", mid_x, mid_y);
}
xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK});
}

Expand Down
2 changes: 2 additions & 0 deletions src/xinerama.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ static void query_screens(xcb_connection_t *conn) {
s->rect.y = screen_info[screen].y_org;
s->rect.width = screen_info[screen].width;
s->rect.height = screen_info[screen].height;
s->remembered_x = -1;
s->remembered_y = -1;
/* We always treat the screen at 0x0 as the primary screen */
if (s->rect.x == 0 && s->rect.y == 0)
TAILQ_INSERT_HEAD(&outputs, s, outputs);
Expand Down