GNOME Bugzilla – Bug 606260
Support gestures for side by side windows. Request to implement side by side tiling by dragging to screen edge.
Last modified: 2010-09-17 14:03:30 UTC
Dragging a window to the left side edge should make resizeable windows take up the left half of the current monitor. Dragging a window to the right edge should make resizeable windows take up the right half of the current monitor. (Maybe) Dragging to the top should make windows maximumize. If another monitor lies beyond the edge of the current monitor then we should treat that differently since it is also likely that the window is intended for the other display. We may want to have some fuzz around the edge for when the window should snap in. See the screencast of Cinch for an example of how this may work: http://www.irradiatedsoftware.com/cinch/
Bug 607694 proposes this feature for metacity as well - no complaining here if we get this mostly free in mutter ...
*** Bug 608124 has been marked as a duplicate of this bug. ***
kde 4.4 will get this great feature. If you drag window to left or right border of screen, it will be resized so that it takes exactly half of screen, and is maximized vertically. This allows user to setup to apps side by side and allow max viewing size for both. Adding to summary so easier to find via search.
A very nice idea, perhaps it could be expanded by 1) Move window to one corner could resize the window to 1/4 of the screen 2) Instead of maximizing the window application when moving to the top (something that could be done by double-clicking on window title bar of using window buttons) it should get resize to 1/2 of the screen but "horizontally" hence moving a windows to the bottom should also resize this window to 1/2 of the screen. I have proposed something similar but in overlay mode, but may be the current idea give the user a better experience. https://bugzilla.gnome.org/show_bug.cgi?id=608860
(In reply to comment #4) > A very nice idea, perhaps it could be expanded by > > 1) Move window to one corner could resize the window to 1/4 of the screen > ... the more different things you can do, the more confusing it is, and the harder it is to get it to do the one you want. Side-by-side windows is basically about the fact that (a) most users* like to maximize all windows, and (b) as monitors get larger this becomes increasingly wasteful, since many apps can't make efficient use of that much width. (Reading becomes more difficult as lines get longer, so anything with text is not going to want to be 1920 pixels wide. And lots of web sites have layouts that won't even use any width beyond 800 or 1024 pixels anyway.) Extra *height*, on the other hand, is much easier to use. So the idea is to treat wide monitors sort of like they were a pair of narrower monitors. (*Note that when I say "most users", I mean "most users", not "most of the people reading this bug report".)
Right. My guess is that the Snap design was informed by the research described here (see "Data on Real-World Usage"): http://blogs.msdn.com/e7/archive/2008/10/01/user-interface-managing-windows-windows.aspx It is pretty clear that the real sweet spot for trading complexity vs. power is the two window mode. Though, we'll need to be a little more sophisticated maybe when performing this when not in landscape orientation...
(In reply to comment #5) May be the corner idea is not very good one, ok give-up about that and reduce the "confusion" but the top-bottom idea I think is very useful. I only use a laptop, so may be there is the bias. I think a side-by-side windows approach is not useful for Firefox when using gmail or wordpress, a terminal, a word processor, evince with lateral panel etc is very useful for apps like pymol and mendeley (I know not a lot of people don`t use this last two applications but out-there must exist other apps that I don´t use but have similar layouts). This are all applications I frequently use and I would like to see simultaneously to compare content (in fact sometimes I have to manually arrange the windows). May be I don´t behave like most users do, but I don´t see the trouble of enabling this features, if normal users use the side-by-side approach let this approach to be the default and "hide" the ability to also activate the top-bottom feature inside gconf-editor or something similar and let the user decide if they prefer one, the other or both approach. I almost don´t understand anything about programming but I think/imagine that if you are able to implement the side-by-side feature the top-bottom feature is just a "couple" more lines of code.
Created attachment 165374 [details] [review] Implement side-by-side tiling When dragging a window over a screen edge and dropping it there, maximize it vertically and scale it horizontally to cover the corresponding half of the current monitor. Whenever a "hot area" which triggers this behavior is entered, an indication of window's target size is displayed after a short delay to avoid distraction when moving a window between monitors. Some comments about the patch: - the tiling indicators are done outside the compositor/plugin so the patch can be used for bug 607694 (that's also why there exists a non-composite fallback); if we want more control over them in the shell (e.g. to do the animations) this can be done in a follow-up patch - the patch introduces a gconf key without adding it to the schema - the idea is to add it to metacity - there's a major flaw when handling windows that cannot be tiled: (a) for windows that are not resizable, no indicator is displayed and tiling is not possible (b) for windows whose minimum size exceeds the tiled area, an indicator is displayed but the window is not tiled when dropped It shouldn't be too hard to find a more meaningful indication for (a). I'm not too sure how to handle (b) correctly though (input welcome). - I am not a dual-monitor user, so that behavior probably requires at least some tweaking - that said, I tested it briefly with a second monitor, so the basic functionality is there - last but not least: sorry for dumping a big patch - the only meaningful split I can think of is "add tiling to window handling", "add tile previews" and "make tiling a preference" - these are already pretty separated by files, so I decided to leave it in one piece
Created attachment 165375 [details] [review] Enable side-by-side tiling Override the metacity schema for side-by-side tiling to change the default behavior when running mutter in GNOME Shell.
Created attachment 165420 [details] [review] Implement side-by-side tiling Updated patch: - fix color of the tile preview, which was not picked up properly by the theme - give tiling a higher priority than snapping back maximized windows which have been shaken loose (as suggested by mccann on IRC)
Review of attachment 165420 [details] [review]: hey, this is really nice! Couple of behavioral things: - I saw a problem where the second window wouldn't tile once I'd tile one window - I'd get the blue highlight, but it wouldn't "take" on release. Can't reproduce now, but something to keep an eye out for. - The behavior of: - Drag window to tiled - Maximize - Unmaximize Is unexpected (it leaves the window in an intermediate drag position). What I think I'd expect is that it would go back to tiled. - When dragging off of the tiled state, the window first jumps to one position, then after further motions, to another position with respect to the cursor. Code looks pretty good. I have a suspicion that something going to break in the complexity that is the maximize-unmaximize machinery, but I can't find anything in particular. (other than the things observed above.) I think we just have to try it and fix it when people find problems, and hope it is not 3 years from now :-) - What would happen if a plugin called meta_window_unmaximize() on a tiled window? It seems that the result would be that ->tile_mode would be left set? Then if a move grab started and ended without ever calling update_move() (can that happen?) the window would retile? ::: src/core/core.c @@ +327,3 @@ + + meta_error_trap_push (display); + XConfigureWindow (xdisplay, Hmm, the Mutter code is supposed to be using MetaStackTracker to record everything it does to the stacking order... the stack tracker is supposed to have the "as current as we know it" order of windows, to prevent cases where we do something to a window, draw it wrong for a frame, then get notification back from the X server. You'd use meta_stack_tracker_record_lower_below() here, but you'd also need to use meta_stack_tracker_record_add(), and I guess meta_stack_tracker_record_remove(). If it ends up being too much of a pain, then we can just have a comment here that we didn't do it (the worst that can possibly happen is we paint wrong for a frame), but it's easiest if all the code in Mutter just does it - prevents wrongness getting copied around, etc. You can see how frame.c handles the interaction with the ui/ code. @@ +331,3 @@ + CWSibling | CWStackMode, + &changes); + meta_error_trap_pop (display, TRUE); last_request_was_roundtrip should be FALSE here, XConfigureWindow isn't a round trip ::: src/core/window-private.h @@ +131,3 @@ + /* The current or requested tile mode. If maximized_vertically is true, + * this is the current mode. If not, it is the mode which will be + * requested after the window grab is released */ Ugly. But don't have a great suggestion for a way that would be less ugly. :-) ::: src/core/window.c @@ +7580,1 @@ #define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 6 Needs some sort of "Originally for detaching maximized windows, but we use this for the zones at the sides of the monitor where trigger tiling because it's about the right size" comment - since the name is confusing if reading straight down in the new code. ::: src/ui/tile-preview.c @@ +94,3 @@ + FALSE, + OUTLINE_WIDTH - 1, OUTLINE_WIDTH - 1, + preview->tile_rect.width - (2 * OUTLINE_WIDTH - 1), I think I'd write that as: preview->tile_rect.width - 2 * (OUTLINE_WIDTH - 1) - 1 I don't think '2 * OUTLINE_WIDTH - 1' as itself is a meaningful quantity. @@ +110,3 @@ + + iv = gtk_icon_view_new (); + gtk_container_add (GTK_CONTAINER (widget), iv); Yikes! Can you use: http://library.gnome.org/devel/gtk/stable/gtk-Resource-Files.html#gtk-rc-get-style-by-paths To avoid doing this? @@ +129,3 @@ +{ + MetaTilePreview *preview; + GdkColormap *cm; Don't like the cm name here since it's not necessarily the colormap we use, it's the rgba_colormap whether we use it or not. @@ +148,3 @@ + preview->tile_rect.width = preview->tile_rect.height = 0; + + preview->has_alpha = cm && gdk_screen_is_composited (screen); Calling this function inside Mutter, to me is like using libwnck in gnome-shell - we're going the long way around. (I don't care about the Metacity + xcompmgr case.) Could add a "core" function to query whether compositing, but I think I'd just pass it in to meta_tile_preview_new().
Review of attachment 165375 [details] [review]: No problems with the two lines of code :-) ::: data/gnome-shell.schemas @@ +38,3 @@ + <short>enable side-by-side tiling when dropping windows on screen edges</short> + <long> + This key overrides /apps/metacity/general/side_by_side_tiling when I think the long description is supposed to be a superset of the short description. Especially since we aren't actually installing a schema description for the metacity key (until the patch gets merged into Metacity anyways), it's probably good to have decent docs here.
(In reply to comment #11) > Couple of behavioral things: > > - I saw a problem where the second window wouldn't tile once I'd tile one > window - I'd get the blue highlight, but it wouldn't "take" on release. Can't > reproduce now, but something to keep an eye out for. Could this be the issue mentioned above under (b)? That is, the missing indication that a window's minimum size prevents tiling. > - When dragging off of the tiled state, the window first jumps to one > position, then after further motions, to another position with respect to the > cursor. I'm not sure whether I misunderstand the problem's description or just can't reproduce it - the intended behavior should be consistent with the shaking-loose behavior of maximized windows, e.g. jump to the cursor position after exceeding some threshold. Anyway, I hope to have an updated patch ready later - it's been a while :)
Created attachment 169447 [details] [review] Implement side-by-side tiling Except for the questions in the last comment, most issues should have been addressed now. (In reply to comment #11) > - What would happen if a plugin called meta_window_unmaximize() on a tiled > window? It seems that the result would be that ->tile_mode would be left set? > Then if a move grab started and ended without ever calling update_move() (can > that happen?) the window would retile? When addressing your comment about the tile->maximized->unmaximized behavior, meta_window_unmaximize() now restores the tiled state. So calling unmaximize on a tiled window will now do nothing at all (after all, there's nothing to unmaximize unless in maximized state, right?) Acceptable behavior? > You'd use meta_stack_tracker_record_lower_below() here, but you'd also need to > use meta_stack_tracker_record_add(), and I guess > meta_stack_tracker_record_remove(). I don't think meta_stack_tracker_record_remove() is necessary - the tile preview is kept around until the MetaScreen is destroyed, which will unref the stack tracker as well. Unless there are plans to share a stack tracker between screens, we should get away with not removing the window.
Created attachment 169448 [details] [review] Enable side-by-side tiling (In reply to comment #12) > I think the long description is supposed to be a superset of the short > description. Especially since we aren't actually installing a schema > description for the metacity key (until the patch gets merged into Metacity > anyways), it's probably good to have decent docs here. Fair enough, especially as I'm already mainting a port of the patch for metacity bug 607694 which contains a proper description ...
Review of attachment 169448 [details] [review]: ::: data/gnome-shell.schemas @@ +40,3 @@ + If enabled, dropping windows on screen edges maximizes them + vertically and resizes them horizontally to cover half of the + available area. Drag-dropping to the top maximizes the window. Wooops - left over from an older revision...
Created attachment 169449 [details] [review] Enable side-by-side tiling Remove reference to removed drag-to-top-to-maximize behavior.
(In reply to comment #13) > (In reply to comment #11) > > Couple of behavioral things: > > > > - I saw a problem where the second window wouldn't tile once I'd tile one > > window - I'd get the blue highlight, but it wouldn't "take" on release. Can't > > reproduce now, but something to keep an eye out for. > > Could this be the issue mentioned above under (b)? That is, the missing > indication that a window's minimum size prevents tiling. Yes, it was. Evolution has a very large minimum size.... > > - When dragging off of the tiled state, the window first jumps to one > > position, then after further motions, to another position with respect to the > > cursor. > > I'm not sure whether I misunderstand the problem's description or just can't > reproduce it - the intended behavior should be consistent with the > shaking-loose behavior of maximized windows, e.g. jump to the cursor position > after exceeding some threshold. I can still reproduce. You have to drag off very slowly and watch carefully what happens (and it's possible that it might be a race so that it doesn't occur if your computer is particularly slow or particularly fast.) If I drag a window to the right half of the screen, then drag the titlebar slowly to the left, what I'll see is that the window will bounce further to the left for one frame and then draw in the right position.
(In reply to comment #14) > (In reply to comment #11) > > - What would happen if a plugin called meta_window_unmaximize() on a tiled > > window? It seems that the result would be that ->tile_mode would be left set? > > Then if a move grab started and ended without ever calling update_move() (can > > that happen?) the window would retile? > > When addressing your comment about the tile->maximized->unmaximized behavior, > meta_window_unmaximize() now restores the tiled state. So calling unmaximize on > a tiled window will now do nothing at all (after all, there's nothing to > unmaximize unless in maximized state, right?) > > Acceptable behavior? Seems like it. My concern wasn't really about behavior, but rather that it seemed like meta_window_unmaximize() would put you in an inconsistent state where tile_mode was set but you weren't vertically maximized. > > You'd use meta_stack_tracker_record_lower_below() here, but you'd also need to > > use meta_stack_tracker_record_add(), and I guess > > meta_stack_tracker_record_remove(). > > I don't think meta_stack_tracker_record_remove() is necessary - the tile > preview is kept around until the MetaScreen is destroyed, which will unref the > stack tracker as well. Unless there are plans to share a stack tracker between > screens, we should get away with not removing the window. yeah, if you are calling meta_tile_preview_free() after meta_stack_tracker_free() you don't need to record the remove.
Review of attachment 169449 [details] [review]: Looks good
(In reply to comment #18) > (In reply to comment #13) > > Could this be the issue mentioned above under (b)? That is, the missing > > indication that a window's minimum size prevents tiling. > > Yes, it was. Evolution has a very large minimum size.... OK, known issue then. Still a blocker in my opinion, I'm just scared to mess too much with the internals of constraints here. > I can still reproduce. You have to drag off very slowly [...] Very very slowly. Thanks for the clarification, I'm now able to reproduce and will look into it.
Review of attachment 169447 [details] [review]: Just a couple of minor things. The remaining hard part seems to be to debug the jumping. What I might suggest to try is something like: connect-after to the stages paint signal add an idle handler at high priority in the handler sleep(1) (I think if you just sleep in the signal handler the stage won't appear painted yet.) Other than that, just reading carefully the code that determines the position of the window after it is dragged away from being tiled might reveal the problem - compare it to how you update the position on move. ::: src/core/screen.c @@ +1771,3 @@ + meta_stack_tracker_record_add (screen->stack_tracker, + xwindow, + XNextRequest (screen->display->xdisplay)); this is the wrong serial - you need the serial of the creation request. See how meta_ui_create_frame_window() returns out the create serial. Now, we have a harder case here, because for your window, creation is bound up in realization, and inside gtk_window_realize(), but it looks to me if you call XNextRequest() before gtk_widget_realize() it will be "close enough". There might be some extra calls, but I think usually the XCreateWindow() will actually be the first X request after gtk_widget_realize() and as far as I recall it should be safer to have the serial "too early" rather than "too late". (If there is a sequence with a consecutive XCreateColormap/XCreateWindow the stack tracker isn't going to care if its told that the XCreateColormap was the request that created the window.) ::: src/ui/tile-preview.c @@ +108,3 @@ + style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget), + "GtkIconView", + "GtkIconView", I'd us GtkWindow.GtkIconView for both of these - GtkIconView isn't a valid widget hierarchy, and it's possible a theme might not handle it @@ +124,3 @@ +MetaTilePreview * +meta_tile_preview_new (int screen_number, + gboolean composited) parameters not lined up
(In reply to comment #21) > (In reply to comment #18) > > (In reply to comment #13) > > > Could this be the issue mentioned above under (b)? That is, the missing > > > indication that a window's minimum size prevents tiling. > > > > Yes, it was. Evolution has a very large minimum size.... > > OK, known issue then. Still a blocker in my opinion, I'm just scared to mess > too much with the internals of constraints here. Can you just tile it respecting the minimum width? It will be broken since it won't fit with the other half-tile, but it will be broken in an obvious way that makes sense to the user. And users will complain and apps will be fixed not to set a huge minimum width.
Created attachment 170268 [details] [review] Implement side-by-side tiling Fixed the previous patch, I didn't address the inconsistency when tiling fails yet. (In reply to comment #23) > Can you just tile it respecting the minimum width? It will be broken since it > won't fit with the other half-tile, but it will be broken in an obvious way > that makes sense to the user. And users will complain and apps will be fixed > not to set a huge minimum width. Not sure I understand you correctly - you mean tile the window anyway so that it covers more than half the screen? I guess that will work, yes.
Created attachment 170271 [details] [review] Enable side-by-side tiling Rebased on master.
(In reply to comment #24) > Created an attachment (id=170268) [details] [review] > Implement side-by-side tiling > > Fixed the previous patch, I didn't address the inconsistency when tiling fails > yet. > > (In reply to comment #23) > > Can you just tile it respecting the minimum width? It will be broken since it > > won't fit with the other half-tile, but it will be broken in an obvious way > > that makes sense to the user. And users will complain and apps will be fixed > > not to set a huge minimum width. > > Not sure I understand you correctly - you mean tile the window anyway so that > it covers more than half the screen? I guess that will work, yes. Yeah, I mean +--------------------------------+ | | | | | | | | The window | | | | | | | +--------------------------------+
Created attachment 170418 [details] [review] Include check for size hints when deciding whether a window can tile The implementation is simple, but slightly incorrect: there will be cases where the tile preview is shown and the window won't tile. First of two alternatives for the problem of windows which can't tile due to their minimum size hint.
Created attachment 170419 [details] [review] Allow tiling to exceed the usual tile size Extend the tile area if a window's minimum size hint exceeds half the monitor width. Second alternative, implementing Owen's suggestion - it's more correct than the first patch (e.g. it just works), but I'd still prefer the first one (sorry evolution ...)
Jon - can you try this out? (or I can show you on my laptop) Personally I like the second approach better - the first seems like "some apps mysteriously don't tile"
(In reply to comment #29) > the first seems like "some apps mysteriously don't tile" Is that referring to the corner case mentioned in the comment or the general problem of no feedback (e.g. reddish preview tiles instead of blue ones - though jimmac probably won't approve that particular suggestion)
Tried out both approaches and I think the problem is rare enough (or hopefully is) that either is really ok. The second approach (a best effort) is a little weirder in that the preview blue "tile" thingy doesn't reflect the actual size that the window will be. We already have the case where some windows, the non-resizeable ones, won't work so having massive ones not work isn't necessarily that different. We may also want to disable this feature when the screen size/aspect ratio reaches a certain value. This is pretty silly in the portrait mode case for example. And a negative feedback there would be pretty annoying. So, for the cases where we don't tile I think we should just not do the tile preview and call it good. If there is a strong feeling that the best-effort approach is better I'm not strongly opposed to it. But it would probably be better if the preview blue rect was accurate. It might be worth checking what Windows 7 does in this case. FWIW, Windows 7 also uses a ripple effect when the size of the screen is touched and the effect will be triggered. Similar to what we do for the hotcorner.
Review of attachment 170419 [details] [review]: Since Florian and Jon have the same preference, I'm not going to object to that.
Review of attachment 170418 [details] [review]: ::: src/core/window.c @@ +3207,3 @@ + /* We ignore the frame here, which gives false positives when the minimum + * size is satisfied without the frame but not including it. + * In that case the tile preview will be shown, but the window won't tile. I don't think this is OK... having a minimum size within a few pixels of half the screen is going to occur some times. I think it should be OK to call meta_frame_calc_geometry() here to get the actual left/right size of the decorations. (Things change and get more complicated in some ways and simpler and others if we change tiled windows to have maximized decorations. More complicated: decorations are different than current. Simpler: maximized windows don't have left/right borders. But I'd like to see the overall change landed before we experiment with decoration.)
Created attachment 170483 [details] [review] Include check for size hints when deciding whether a window can tile n reply to comment #33) > I don't think this is OK... having a minimum size within a few pixels of half > the screen is going to occur some times. I think it should be OK to call > meta_frame_calc_geometry() here to get the actual left/right size of the > decorations. OK. I was trying to avoid calling this on every update_move(), but it does not seem too bad on a netbook ... > (Things change and get more complicated in some ways and simpler and others if > we change tiled windows to have maximized decorations. More complicated: > decorations are different than current. Simpler: maximized windows don't have > left/right borders. But I'd like to see the overall change landed before we > experiment with decoration.) I actually tried that at some point, but didn't like it much. The edge in the center of the screen looks a bit weird with one tiled window; with two windows it looks pretty confusing, as the windows appear like one window with half the title bar active and the other half inactive. I guess the correct decoration would use maximized decorations on the monitor edge and normal decoration in the center. But yeah, I'd like to keep that for later improvements.
Review of attachment 170483 [details] [review]: Looks good
Review of attachment 170268 [details] [review]: Looks good
Attachment 170268 [details] pushed as 97e2b46 - Implement side-by-side tiling (with the second patch squashed)
Comment on attachment 170271 [details] [review] Enable side-by-side tiling Attachment 170271 [details] pushed as a2553f4 - Enable side-by-side tiling