Merge pull request #1698 from Airblader/feature-1696
Added 'move position mouse'
This commit is contained in:
commit
da064cc08f
|
@ -1662,15 +1662,17 @@ bindsym $mod+f fullscreen toggle
|
||||||
bindsym $mod+t floating toggle
|
bindsym $mod+t floating toggle
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
=== Focusing/Moving containers
|
[[_focusing_moving_containers]]
|
||||||
|
|
||||||
To change the focus, use the focus command: +focus left+, +focus right+, +focus
|
=== Focusing containers
|
||||||
down+ and +focus up+.
|
|
||||||
|
|
||||||
There are a few special parameters you can use for the focus command:
|
To change focus, you can use the +focus+ command. The following options are
|
||||||
|
available:
|
||||||
|
|
||||||
|
left|right|up|down::
|
||||||
|
Sets focus to the nearest container in the given direction.
|
||||||
parent::
|
parent::
|
||||||
Sets focus to the +Parent Container+ of the current +Container+.
|
Sets focus to the parent container of the current container.
|
||||||
child::
|
child::
|
||||||
The opposite of +focus parent+, sets the focus to the last focused
|
The opposite of +focus parent+, sets the focus to the last focused
|
||||||
child container.
|
child container.
|
||||||
|
@ -1684,23 +1686,16 @@ output::
|
||||||
Followed by a direction or an output name, this will focus the
|
Followed by a direction or an output name, this will focus the
|
||||||
corresponding output.
|
corresponding output.
|
||||||
|
|
||||||
For moving, use +move left+, +move right+, +move down+ and +move up+.
|
|
||||||
|
|
||||||
*Syntax*:
|
*Syntax*:
|
||||||
-----------------------------------
|
----------------------------------------------
|
||||||
focus <left|right|down|up>
|
focus left|right|down|up
|
||||||
focus <parent|child|floating|tiling|mode_toggle>
|
focus parent|child|floating|tiling|mode_toggle
|
||||||
focus output <<left|right|down|up>|output>
|
focus output left|right|up|down|<output>
|
||||||
move <left|right|down|up> [<px> px]
|
----------------------------------------------
|
||||||
move [absolute] position [[<px> px] [<px> px]|center]
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
Note that the amount of pixels you can specify for the +move+ command is only
|
|
||||||
relevant for floating containers. The default amount is 10 pixels.
|
|
||||||
|
|
||||||
*Examples*:
|
*Examples*:
|
||||||
----------------------
|
-------------------------------------------------
|
||||||
# Focus container on the left, bottom, top, right:
|
# Focus container on the left, bottom, top, right
|
||||||
bindsym $mod+j focus left
|
bindsym $mod+j focus left
|
||||||
bindsym $mod+k focus down
|
bindsym $mod+k focus down
|
||||||
bindsym $mod+l focus up
|
bindsym $mod+l focus up
|
||||||
|
@ -1717,8 +1712,33 @@ bindsym $mod+x focus output right
|
||||||
|
|
||||||
# Focus the big output
|
# Focus the big output
|
||||||
bindsym $mod+x focus output HDMI-2
|
bindsym $mod+x focus output HDMI-2
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
# Move container to the left, bottom, top, right:
|
=== Moving containers
|
||||||
|
|
||||||
|
Use the +move+ command to move a container.
|
||||||
|
|
||||||
|
*Syntax*:
|
||||||
|
-----------------------------------------------------
|
||||||
|
# Moves the container into the given direction.
|
||||||
|
# The optional pixel argument specifies how far the
|
||||||
|
# container should be moved if it is floating and
|
||||||
|
# defaults to 10 pixels.
|
||||||
|
move <left|right|down|up> [<px> px]
|
||||||
|
|
||||||
|
# Moves the container either to a specific location
|
||||||
|
# or to the center of the screen. If 'absolute' is
|
||||||
|
# used, it is moved to the center of all outputs.
|
||||||
|
move [absolute] position [[<px> px] [<px> px]|center]
|
||||||
|
|
||||||
|
# Moves the container to the current position of the
|
||||||
|
# mouse cursor. Only affects floating containers.
|
||||||
|
move position mouse
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
*Examples*:
|
||||||
|
-------------------------------------------------------
|
||||||
|
# Move container to the left, bottom, top, right
|
||||||
bindsym $mod+j move left
|
bindsym $mod+j move left
|
||||||
bindsym $mod+k move down
|
bindsym $mod+k move down
|
||||||
bindsym $mod+l move up
|
bindsym $mod+l move up
|
||||||
|
@ -1728,10 +1748,12 @@ bindsym $mod+semicolon move right
|
||||||
# move more than the default
|
# move more than the default
|
||||||
bindsym $mod+j move left 20 px
|
bindsym $mod+j move left 20 px
|
||||||
|
|
||||||
# Move floating container to the center
|
# Move floating container to the center of all outputs
|
||||||
# of all outputs
|
|
||||||
bindsym $mod+c move absolute position center
|
bindsym $mod+c move absolute position center
|
||||||
----------------------
|
|
||||||
|
# Move container to the current position of the cursor
|
||||||
|
bindsym $mod+m move position mouse
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
=== Changing (named) workspaces/moving to workspaces
|
=== Changing (named) workspaces/moving to workspaces
|
||||||
|
|
||||||
|
|
|
@ -258,6 +258,12 @@ void cmd_move_window_to_position(I3_CMD, char *method, char *x, char *y);
|
||||||
*/
|
*/
|
||||||
void cmd_move_window_to_center(I3_CMD, char *method);
|
void cmd_move_window_to_center(I3_CMD, char *method);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of 'move [window|container] [to] position mouse'
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void cmd_move_window_to_mouse(I3_CMD);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of 'move scratchpad'.
|
* Implementation of 'move scratchpad'.
|
||||||
*
|
*
|
||||||
|
|
|
@ -70,6 +70,12 @@ bool floating_maybe_reassign_ws(Con *con);
|
||||||
*/
|
*/
|
||||||
void floating_center(Con *con, Rect rect);
|
void floating_center(Con *con, Rect rect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the given floating con to the current pointer position.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void floating_move_to_pointer(Con *con);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/**
|
/**
|
||||||
* Removes the floating client from its workspace and attaches it to the new
|
* Removes the floating client from its workspace and attaches it to the new
|
||||||
|
|
|
@ -271,6 +271,7 @@ state RENAME_WORKSPACE_NEW_NAME:
|
||||||
# move workspace to [output] <str>
|
# move workspace to [output] <str>
|
||||||
# move scratchpad
|
# move scratchpad
|
||||||
# move [window|container] [to] [absolute] position [ [<pixels> [px] <pixels> [px]] | center ]
|
# move [window|container] [to] [absolute] position [ [<pixels> [px] <pixels> [px]] | center ]
|
||||||
|
# move [window|container] [to] position mouse|cursor|pointer
|
||||||
state MOVE:
|
state MOVE:
|
||||||
'window'
|
'window'
|
||||||
->
|
->
|
||||||
|
@ -342,6 +343,8 @@ state MOVE_TO_ABSOLUTE_POSITION:
|
||||||
state MOVE_TO_POSITION:
|
state MOVE_TO_POSITION:
|
||||||
'center'
|
'center'
|
||||||
-> call cmd_move_window_to_center($method)
|
-> call cmd_move_window_to_center($method)
|
||||||
|
'mouse', 'cursor', 'pointer'
|
||||||
|
-> call cmd_move_window_to_mouse()
|
||||||
coord_x = word
|
coord_x = word
|
||||||
-> MOVE_TO_POSITION_X
|
-> MOVE_TO_POSITION_X
|
||||||
|
|
||||||
|
|
|
@ -1833,6 +1833,30 @@ void cmd_move_window_to_center(I3_CMD, char *method) {
|
||||||
ysuccess(true);
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementation of 'move [window|container] [to] position mouse'
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void cmd_move_window_to_mouse(I3_CMD) {
|
||||||
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
|
owindow *current;
|
||||||
|
TAILQ_FOREACH(current, &owindows, owindows) {
|
||||||
|
Con *floating_con = con_inside_floating(current->con);
|
||||||
|
if (floating_con == NULL) {
|
||||||
|
DLOG("con %p / %s is not floating, cannot move it to the mouse position.\n",
|
||||||
|
current->con, current->con->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DLOG("moving floating container %p / %s to cursor position\n", floating_con, floating_con->name);
|
||||||
|
floating_move_to_pointer(floating_con);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_output->needs_tree_render = true;
|
||||||
|
ysuccess(true);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implementation of 'move scratchpad'.
|
* Implementation of 'move scratchpad'.
|
||||||
*
|
*
|
||||||
|
|
|
@ -426,6 +426,42 @@ void floating_center(Con *con, Rect rect) {
|
||||||
con->rect.y = rect.y + (rect.height / 2) - (con->rect.height / 2);
|
con->rect.y = rect.y + (rect.height / 2) - (con->rect.height / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Moves the given floating con to the current pointer position.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void floating_move_to_pointer(Con *con) {
|
||||||
|
assert(con->type == CT_FLOATING_CON);
|
||||||
|
|
||||||
|
xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, root), NULL);
|
||||||
|
if (reply == NULL) {
|
||||||
|
ELOG("could not query pointer position, not moving this container\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output *output = get_output_containing(reply->root_x, reply->root_y);
|
||||||
|
if (output == NULL) {
|
||||||
|
ELOG("The pointer is not on any output, cannot move the container here.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine where to put the window. */
|
||||||
|
int32_t x = reply->root_x - con->rect.width / 2;
|
||||||
|
int32_t y = reply->root_y - con->rect.height / 2;
|
||||||
|
FREE(reply);
|
||||||
|
|
||||||
|
/* Correct target coordinates to be in-bounds. */
|
||||||
|
x = MAX(x, (int32_t)output->rect.x);
|
||||||
|
y = MAX(y, (int32_t)output->rect.y);
|
||||||
|
if (x + con->rect.width > output->rect.x + output->rect.width)
|
||||||
|
x = output->rect.x + output->rect.width - con->rect.width;
|
||||||
|
if (y + con->rect.height > output->rect.y + output->rect.height)
|
||||||
|
y = output->rect.y + output->rect.height - con->rect.height;
|
||||||
|
|
||||||
|
/* Update container's coordinates to position it correctly. */
|
||||||
|
floating_reposition(con, (Rect){x, y, con->rect.width, con->rect.height});
|
||||||
|
}
|
||||||
|
|
||||||
DRAGGING_CB(drag_window_callback) {
|
DRAGGING_CB(drag_window_callback) {
|
||||||
const struct xcb_button_press_event_t *event = extra;
|
const struct xcb_button_press_event_t *event = extra;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
#!perl
|
||||||
|
# vim:ts=4:sw=4:expandtab
|
||||||
|
#
|
||||||
|
# Please read the following documents before working on tests:
|
||||||
|
# • http://build.i3wm.org/docs/testsuite.html
|
||||||
|
# (or docs/testsuite)
|
||||||
|
#
|
||||||
|
# • http://build.i3wm.org/docs/lib-i3test.html
|
||||||
|
# (alternatively: perldoc ./testcases/lib/i3test.pm)
|
||||||
|
#
|
||||||
|
# • http://build.i3wm.org/docs/ipc.html
|
||||||
|
# (or docs/ipc)
|
||||||
|
#
|
||||||
|
# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
|
||||||
|
# (unless you are already familiar with Perl)
|
||||||
|
#
|
||||||
|
# Tests the 'move [window|container] [to] position mouse|cursor|pointer command.
|
||||||
|
# Ticket: #1696
|
||||||
|
use i3test i3_autostart => 0;
|
||||||
|
use POSIX qw(floor);
|
||||||
|
|
||||||
|
sub warp_pointer {
|
||||||
|
my ($pos_x, $pos_y) = @_;
|
||||||
|
$x->root->warp_pointer($pos_x, $pos_y);
|
||||||
|
sync_with_i3;
|
||||||
|
}
|
||||||
|
|
||||||
|
my ($pid, $config, $ws, $rect, @cons);
|
||||||
|
my $root_rect = $x->root->rect;
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Given a floating container and the cursor far from any edges, when
|
||||||
|
# moving the container to the mouse, then the container is moved such
|
||||||
|
# that the cursor is centered inside it.
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
$config = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font pango:monospace 8
|
||||||
|
EOT
|
||||||
|
$pid = launch_with_config($config);
|
||||||
|
|
||||||
|
$ws = fresh_workspace;
|
||||||
|
open_floating_window;
|
||||||
|
warp_pointer(100, 100);
|
||||||
|
|
||||||
|
cmd 'move position mouse';
|
||||||
|
|
||||||
|
@cons = @{get_ws($ws)->{floating_nodes}};
|
||||||
|
$rect = $cons[0]->{rect};
|
||||||
|
|
||||||
|
is(floor($rect->{x} + $rect->{width} / 2), 100, "con is centered around cursor horizontally");
|
||||||
|
is(floor($rect->{y} + $rect->{height} / 2), 100, "con is centered around cursor vertically");
|
||||||
|
|
||||||
|
exit_gracefully($pid);
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Given a floating container and the cursor is in the left upper edge
|
||||||
|
# of the output, when moving the container to the mouse, then the
|
||||||
|
# container is moved but adjusted to stay in-bounds.
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
$config = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font pango:monospace 8
|
||||||
|
EOT
|
||||||
|
$pid = launch_with_config($config);
|
||||||
|
|
||||||
|
$ws = fresh_workspace;
|
||||||
|
open_floating_window;
|
||||||
|
warp_pointer(5, 5);
|
||||||
|
|
||||||
|
cmd 'move position mouse';
|
||||||
|
|
||||||
|
@cons = @{get_ws($ws)->{floating_nodes}};
|
||||||
|
$rect = $cons[0]->{rect};
|
||||||
|
|
||||||
|
is($rect->{x}, 0, "con is on the left edge");
|
||||||
|
is($rect->{y}, 0, "con is on the upper edge");
|
||||||
|
|
||||||
|
exit_gracefully($pid);
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Given a floating container and the cursor is in the left right lower
|
||||||
|
# edge of the output, when moving the container to the mouse, then the
|
||||||
|
# container is moved but adjusted to stay in-bounds.
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
$config = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font pango:monospace 8
|
||||||
|
EOT
|
||||||
|
$pid = launch_with_config($config);
|
||||||
|
|
||||||
|
$ws = fresh_workspace;
|
||||||
|
open_floating_window;
|
||||||
|
warp_pointer($root_rect->width - 5, $root_rect->height - 5);
|
||||||
|
|
||||||
|
cmd 'move position mouse';
|
||||||
|
|
||||||
|
@cons = @{get_ws($ws)->{floating_nodes}};
|
||||||
|
$rect = $cons[0]->{rect};
|
||||||
|
|
||||||
|
is($rect->{x} + $rect->{width}, $root_rect->width, "con is on the right edge");
|
||||||
|
is($rect->{y} + $rect->{height}, $root_rect->height, "con is on the lower edge");
|
||||||
|
|
||||||
|
exit_gracefully($pid);
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Given a floating container and the cursor being close to the corner of
|
||||||
|
# an output, when the container is moved to the mouse, then the container
|
||||||
|
# is moved but adjusted to the output boundaries.
|
||||||
|
# This test verifies that boundaries of individual outputs are respected
|
||||||
|
# and not just boundaries of the entire X root screen.
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
$config = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font pango:monospace 8
|
||||||
|
fake-outputs 500x500+0+0,500x500+500+0,500x500+0+500,500x500+500+500
|
||||||
|
EOT
|
||||||
|
$pid = launch_with_config($config);
|
||||||
|
|
||||||
|
$ws = fresh_workspace;
|
||||||
|
open_floating_window;
|
||||||
|
warp_pointer(495, 495);
|
||||||
|
|
||||||
|
cmd 'move position mouse';
|
||||||
|
|
||||||
|
@cons = @{get_ws($ws)->{floating_nodes}};
|
||||||
|
$rect = $cons[0]->{rect};
|
||||||
|
|
||||||
|
is($rect->{x} + $rect->{width}, 500, "con is on the right edge");
|
||||||
|
is($rect->{y} + $rect->{height}, 500, "con is on the lower edge");
|
||||||
|
|
||||||
|
exit_gracefully($pid);
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
done_testing;
|
Loading…
Reference in New Issue