-
Notifications
You must be signed in to change notification settings - Fork 770
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
Tiling drag, take 3 #3085
Tiling drag, take 3 #3085
Conversation
4de85a4
to
f711a0f
Compare
I think @acrisci just meant that when you drop-move a window, we need to emit the regular
Let's hold off on that for now. I think the focused color is a reasonable choice. When the need arises we can still make it configurable.
Perhaps @MForster can add some insight here. :-) I haven't looked into it yet.
Yes, let's please squash; but we can wait with that until we merge. To retain attributions, the commit message should just mention the other authors having worked on this previously.
That's a very good point. Yes, I think we should have this option.
Perhaps leave a comment at the existing two PRs so the people subscribed there get a notification that this has been picked up upon again? You can also drop an email to the mailing list and / or call for testers on reddit. |
We can probably do this when this is ready to merge (or after it is merged in a separate branch for limited time? dunno). I predict that writing excessive tests for this will take some time. For now, it would be great if you and/or @stapelberg can run this. |
27c6d27
to
4992156
Compare
I've been trying to write the tests. Maybe @stapelberg can help with my problem: #!perl
use i3test i3_config => <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
focus_follows_mouse no
floating_modifier Mod1
# 2 side by side outputs
fake-outputs 1000x500+0+0,1000x500+1000+0
EOT
use i3test::XTEST;
sub start_drag {
my ($pos_x, $pos_y) = @_;
$x->root->warp_pointer($pos_x, $pos_y);
xtest_sync_with_i3;
xtest_key_press(64); # Alt_L
xtest_button_press(1, $pos_x, $pos_y);
xtest_sync_with_i3;
}
sub end_drag {
my ($pos_x, $pos_y) = @_;
$x->root->warp_pointer($pos_x, $pos_y);
xtest_sync_with_i3;
xtest_button_release(1, $pos_x, $pos_y);
xtest_key_release(64); # Alt_L
xtest_sync_with_i3;
}
my $ws2 = fresh_workspace(output => 1);
my $ws1 = fresh_workspace(output => 0);
open_window;
my $A = get_focused($ws1);
start_drag(50, 50);
end_drag(1050, 50);
is(get_focused($ws2), $A, 'A moved to the right workspace');
done_testing; I have tried every sync permutation for the |
Hmm, I think it gets stuck because i3 is inside |
Possible feature: special keybind that when used with tiling windows it turns them to floating. From https://www.reddit.com/r/i3wm/comments/7xrmxu/move_nonfloating_window_using_the_mouse/ |
@stapelberg, since you are fairly active lately, do you have any input regarding the problem I described above? Thanks. |
Sorry for the late reply. I think your assessment is correct: we don’t correctly handle the sync event from within the drag_pointer event loop. It should be an easy addition to do so, though :). Let me know if you can’t get that to work, and thanks for being diligent regarding the tests — I think this will be our first test case performing any kind of dragging. |
They generally seem to be handled but they get stuck sometimes. The test sometimes hangs for 10-20 seconds and then continues. This is the gdb log.
It seems like it's possible to have leftover X events but ev_run doesn't get interrupted? I'll continue tomorrow. |
Just checking — your git working directory does contain commit 0d8b671, yes? If not, that would be my suspicion. |
Yes, I had rebased with the latest next. |
I wonder if we are going against libev's documentation here:
|
Fair point. If you can find a cleaner way to implement this, pull requests are very welcome :) |
Tbh, I don't really understand the rationale behind the quoted text, I don't think that the current implementation causes any problems as far as I can tell. I'll see if I can come up with a cleaner solution though. For this PR though my problem is that I still don't completely understand why the i3sync event gets lost. I have tried some hacks that improved the situation a bit (eg an additional ev_idle or ev_check makes the 1-minute hang more rare) but I am still searching for a complete solution. Since you are significantly more experienced with libev any ideas for the possible solution/cause might help. |
Can you give me the steps required to reproduce the issue please? |
I've pushed a test that should exhibit this behaviour. |
I looked into this a little bit, and I’m fairly convinced that the issue is that we’re draining the events in Line 695 in ddc80ab
Line 763 in ddc80ab
Indeed, adding a quick and dirty “drain:” label in front of the while loop and jumping to it before the final Note that this doesn’t eliminate all causes of flakiness for 295-tiling-drag.t for me. One other issue is that you’re calling I hope this helps you make some progress on this. Let me know if you need further help. |
Thanks! I had done something similar with your
I ran it hundreds of times with a loop and it never hanged. |
As discussed in PR i3#3085, X11 events can appear while dragloop->callback() is running.
Seems to be the intention, indicated by this comment (con.c:1308-1310): /* For split containers, we use the currently focused container within it. * This allows setting marks on, e.g., tabbed containers which will move * con to a new tab behind the focused tab. */ Related to i3#3085.
Fixes i3#2643 Inner drop region behaves like move to mark. The outer region is close to the edge (currently 30px from the edge). This will place the container as a sibling in the given direction within the parent container. If the move direction goes against the orientation of the parent container, tree_move() is called. Contributors: Co-authored-by: Orestis Floros <orestisflo@gmail.com> See i3#3085 - Inner drop region behaves like move to mark - Handle workspaces - Fix crash when target closes - Initiate tiling drag from titlebar - Hide indicator until container is dragged outside of original position - Calculate outer_threshold using percentages instead of fixed pixel values - Emit 'move' event properly - Don't focus previously unfocused containers - Use tree_split() on different orientation - Fix redundant split containers - DT_PARENT - Readability & optimizations - Limit parent threshold by render_deco_height() - Tests - Fullscreen container handling - Initiate drag from title bar - Fix issue of EnterNotify events still triggering after drag_callback is called - Include decorations for drop target calculation Co-authored-by: Michael Forster <email@michael-forster.de> See i3#2178 - Original implementation of tiling drag + indicator window > A container can be dragged by the title bar to one of the four sides > of another container. That container will then be split either > horizontally or vertically. Co-authored-by: Tony Crisci <tony@dubstepdish.com> See i3#2653 - Original implementation of outer/inner drop region indicator: > There are two drop regions per direction. > > The inner region is closer to the center of the window. Dropping on > this region will split the target container and put the container > within the split at the given direction beside the target container. > > The outer region is close to the edge (currently 30px from the edge). > This will place the container as a sibling in the given direction within > the parent container. > > Dropping into the outer region moves the con beside the target. If the > move direction goes against the orientation of the parent container, the > con moves out of the row. - Fix crash: Ignore containers without a managed window (eg i3bar)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall. Just a few small finishing touches.
direction_t direction; | ||
drop_type_t drop_type; | ||
xcb_window_t indicator = 0; | ||
const struct callback_params params = {&indicator, &target, &direction, &drop_type}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation. I think we can remove the const
qualifier, which will result in better code overall — if the params need to be mutable in this case, we might as well reflect that in the signature.
src/tiling_drag.c
Outdated
|
||
ipc_send_window_event("move", con); | ||
break; | ||
case DT_PARENT:; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL :)
Thus far, I have usually created a new scope to be able to declare variables after a label:
case DT_PARENT: {
const bool …
}
Can you see if that works here? I would prefer a new scope over the subtle ;
. If a new scope doesn’t work, at least add a comment explaining the ;
Fixes i3#2643 Inner drop region behaves like move to mark. The outer region is close to the edge (currently 30px from the edge). This will place the container as a sibling in the given direction within the parent container. If the move direction goes against the orientation of the parent container, tree_move() is called. Contributors: Co-authored-by: Orestis Floros <orestisflo@gmail.com> See i3#3085 - Inner drop region behaves like move to mark - Handle workspaces - Fix crash when target closes - Initiate tiling drag from titlebar - Hide indicator until container is dragged outside of original position - Calculate outer_threshold using percentages instead of fixed pixel values - Emit 'move' event properly - Don't focus previously unfocused containers - Use tree_split() on different orientation - Fix redundant split containers - DT_PARENT - Readability & optimizations - Limit parent threshold by render_deco_height() - Tests - Fullscreen container handling - Initiate drag from title bar - Fix issue of EnterNotify events still triggering after drag_callback is called - Include decorations for drop target calculation Co-authored-by: Michael Forster <email@michael-forster.de> See i3#2178 - Original implementation of tiling drag + indicator window > A container can be dragged by the title bar to one of the four sides > of another container. That container will then be split either > horizontally or vertically. Co-authored-by: Tony Crisci <tony@dubstepdish.com> See i3#2653 - Original implementation of outer/inner drop region indicator: > There are two drop regions per direction. > > The inner region is closer to the center of the window. Dropping on > this region will split the target container and put the container > within the split at the given direction beside the target container. > > The outer region is close to the edge (currently 30px from the edge). > This will place the container as a sibling in the given direction within > the parent container. > > Dropping into the outer region moves the con beside the target. If the > move direction goes against the orientation of the parent container, the > con moves out of the row. - Fix crash: Ignore containers without a managed window (eg i3bar)
Regarding the I have made the change but I would still favor the old code 1. because of the point above 2. because it minimizes risk of a last-minute regression for this PR. |
That’s fair. We can leave the Can you update and rebase to pick up the CI fixes please? |
Fixes i3#2643 Inner drop region behaves like move to mark. The outer region is close to the edge (currently 30px from the edge). This will place the container as a sibling in the given direction within the parent container. If the move direction goes against the orientation of the parent container, tree_move() is called. Contributors: Co-authored-by: Orestis Floros <orestisflo@gmail.com> See i3#3085 - Inner drop region behaves like move to mark - Handle workspaces - Fix crash when target closes - Initiate tiling drag from titlebar - Hide indicator until container is dragged outside of original position - Calculate outer_threshold using percentages instead of fixed pixel values - Emit 'move' event properly - Don't focus previously unfocused containers - Use tree_split() on different orientation - Fix redundant split containers - DT_PARENT - Readability & optimizations - Limit parent threshold by render_deco_height() - Tests - Fullscreen container handling - Initiate drag from title bar - Fix issue of EnterNotify events still triggering after drag_callback is called - Include decorations for drop target calculation Co-authored-by: Michael Forster <email@michael-forster.de> See i3#2178 - Original implementation of tiling drag + indicator window > A container can be dragged by the title bar to one of the four sides > of another container. That container will then be split either > horizontally or vertically. Co-authored-by: Tony Crisci <tony@dubstepdish.com> See i3#2653 - Original implementation of outer/inner drop region indicator: > There are two drop regions per direction. > > The inner region is closer to the center of the window. Dropping on > this region will split the target container and put the container > within the split at the given direction beside the target container. > > The outer region is close to the edge (currently 30px from the edge). > This will place the container as a sibling in the given direction within > the parent container. > > Dropping into the outer region moves the con beside the target. If the > move direction goes against the orientation of the parent container, the > con moves out of the row. - Fix crash: Ignore containers without a managed window (eg i3bar)
Done :) |
Merged! 🎉 Thanks for your work on this! |
Thanks for the patch! I have just tested it (on top of 4.20.1) and I have found a case where it does not work:
If I drag the top vbeterm on top of the bottom vbeterm, the positions of the two are swapped as expected. But if I drag the bottom vbeterm on top of the top one, the two windows are not swapped. The indicator is correct (I get an orange area on the center of the target term), but when releasing the mouse button, it does nothing. Edit: I have tested on top of i3-gaps, so maybe this does not happen with vanilla i3. I'll test on top of vanilla i3 a bit later. |
@vincentbernat Thanks for trying this already The semantics of drag & drop are not to swap containers, but similar to Copy & paste from the docs in this PR:
|
Understood, thanks for the clarification! |
Thanks a lot for seeing this through to completion! I always felt bad about teasing the feature with an unfinished patch and then letting it drop. Seeing how much work this was I wouldn't have been able to to see it through. So, thanks again for picking this up and finishing it! |
how do i disable it? i looked in documentation and it tells you pretty much everything but that |
Can you explain why you want to disable the feature, as opposed to just not using it? Is it getting in your way somehow? |
You can't. Please track updates on a possible setting for this here: #5155 |
yeah, well i usually click the tabs to change them, and now that this is added if you move your mouse within like 3px while clicking it drags them off. i also move my windows with keyboard basically tldr, i don't plan on using it, and it gets in the way in a pretty big way in my specific use case. i can understand why it was added and why other people might want it and see it as a useful feature as well though, and well, it was also at least intended to have a way to disable this feature if you scroll to the top, airblader agreed its a good idea. (quoted here)
That's a very good point. Yes, I think we should have this option.」 i guess that about sums it up. |
Left click is maybe not the best choice. Would be nice to be able to change which mouse button triggers the drag. |
It's probably time to lock this thread to encourage proper structured discussion via new issues. This is a released feature now so future changes need to be treated as bugs/enhancements. Thank you to everyone that contributed to this discussion over the years, feedback has been very valuable! |
Fixes #2643.
This is a continuation of #2653.
I have changed the behaviour for the inner region from #2653. The inner region now behaves likemove container to mark
and supports no direction. This reduces the changes to corecon.c
functions and is simpler. It was also enough for the support of stacked & tabbed containers without any extra work.The code needs some polishing here and there but I hope that the core functionality works as intended with zero crashes. I have opened this PR to get some first feedback and hopefully get some people to run the code on their machines.
Current status
TODOs
(removed completed items from #2653):
Initiate tiling drag from titlebarThis would break resizingRefactor insert_con_into() into con.cWhy?Configure color of drop indicator❓ (even though using the focused color seems like a reasonable default, do we want to add the extra configuration?)con
if it had focus. To change this,route_click
should also be modified since focus changes there.Rearrange tabbed / stacked by dropping on the title?=> out of scopedragging & swapping ?-- can be done in future PRgit blame
.Tests
dragging onto stacked / tabbed containers=> out of scope