Monday, 2 June 2008

KWin window groups

The more I think about it the stranger it seems that modern window managers can only "manage" one window at a time. Usually when dealing with apps that beget multiple windows it makes much more sense to manage them not as individual windows but as a group. Sometimes it is even desirable for several applications or different instances of the same application to behave as one within your window manager. The Compiz plugin "group and tab" tries to solve this problem but, not being built-in to the window-manager, it doesn't quite deliver the functionality.

So why is this? I have set about thinking how useful window-group functionality might be integrated into KWin. N.B. I'm not going to say anything here about tabbed windows.

Before I go any further, I'd like to make it clear that I am no kind of expert, my hope with this post is to get some feedback, to change what I've got wrong, fill in the blanks and hopefully come up with a workable proposal.

So to it, and lets start with the basics: What are my design principles? Window grouping should
  1. not interfere with current functionality
  2. have a simple, intuitive and transparent interface/behaviour
  3. be fully integrated into window manager (i.e. not a compositor plugin)
  4. be work-saving
OK, and what essential functionality should it provide?
  1. The ability to select and group multiple windows
  2. To keep track of these groups
  3. The ability to "act on" groups of windows, for example moving, closing or minimising the whole group.

1. group semantics

I want to keep this as simple as possible, at least unless and until use suggests the need for something more sophisticated. A window may belong to one group or no groups at all. There should be only level of grouping (i.e. you cannot have groups of groups).

These simple semantics facilitate the interface that I will describe below.

2. interface

There are four core components to managing grouped windows
  1. selecting and grouping windows
  2. performing actions (close, move, shade, etc.) on groups
  3. performing actions on single windows
  4. persistent settings and configuration

2.1 selecting groups: Point 1 can be solved by the usual point and click process: hold [GSMK] (group-selection modifier key or key combination) and click on windows to select and press, say, [GSMK] + "g" to group the selected windows. We can also add options to the window operations menu (the one that comes up when you right-click in the titlebar), more on that later.

Transient groups: While a set of windows is selected it should be possible to act on them as if they were grouped without actually grouping them.

2.2 acting on windows and groups: In order to perform actions on single windows and groups of windows I suggest using the existing interfaces (buttons on the toolbar, window operations menu, key shortcuts) but if the window is a member of a group, by default apply the actions to the group rather than the single window. We then use another modifier key(combo), which we'll call [IGMK] (ignore-groups modifier key) which allows the user to move, resize etc. the window individually as though it were not a member of a group.

In section 3 we'll look at what it means to apply the actions [close, move, no border, to desktop n, minimise/restore, keep above, keep below, send to all desktops, resize, maximise, shade] to a group but first to the window operations menu.

We could extend the current window operations menu to include all of the window-group functions but it makes more sense to have two different menus. In the same way that minimising a grouped window will minimise the whole group, right-clicking in the titlebar of a grouped window will open the window-group operations menu (and holding [IGMK] allows the user to access the single-window menu).

The window-group operations menu might look something like this:

::::::: This window
::::::: Advanced >>
::::::: ::::::: Keep above
::::::: ::::::: Keep below
::::::: ::::::: Fullscreen
::::::: ::::::: No boarder
::::::: ::::::: Group shortcuts
::::::: ::::::: Special group settings
::::::: ::::::: Special application settings
::::::: To desktop >>
::::::: ::::::: All desktops
::::::: ::::::: Dektop 1
::::::: ::::::: Dektop 2
::::::: ::::::: ...
::::::: Move
::::::: Minimise
::::::: Maximise
::::::: Shade
::::::: Group with... >>
::::::: ::::::: lists all groups and single windows that can be added
::::::: Remove window from group (removes this window from the group)
::::::: Ungroup (disbands whole group)
::::::: Configure group behaviour...
::::::: Close

This is basically the same as the standard menu except (1) All of the actions refer to the group, not the single window. (2) New menu item, "this window", which brings up the standard window operations menu. (3) No "fullscreen" menu item. (4) No "special application settings" menu item. (5) A section containing options for merging/ungrouping windows etc. Note that the menu item "group with" should also be included in the single-window KWin menu.

2.3 persistent settings and configuration: Here I am entering the realm of guesswork so I will be brief. I don't know about the workings of X-windows and KWin so I can't really speculate too much about this. One useful feature would be the ability to make all windows created by a given process automatically be grouped, to make this the default behaviour and to set up exceptions. We'd also want to facilitate the interaction of other apps and applets, for example the taskbar and the box-switcher effect, with window groups.

3. acting on the group: what does it mean?

This is largely a matter of deciding the balance between the group as an entity that has its own state and a simple service for routing commands to its child windows.

For example for a binary state like 'keep above' a command routing approach would simply allow the user to either change the state of all windows in the group to 'keep above' or change the state of all windows in the group to 'don't keep above'. A group-with-state approach would allow the user to set the state of the group to, for example "keep all windows in the group on top", "dont keep any of the windows in the group on top" or "apply each window's own keep-on-top settings" without modifying the keep-on-top settings of each window.

While the second approach is more powerful, it is also more cumbersome and harder for the user to grasp. In particular there is a tendency for there to be a certain amount of 'hidden state' e.g. the user cannot tell immediately whether a group of windows are on top because of the group settings or because of the individual window settings. For this reason I suggest the first, 'command router' approach, this also has the benefit of being much simpler to implement.

I have divided the window manager actions into groups according to how they should be dealt with when applied to a group:

apply to each window:
The following actions should simply be applied to each window in the group
  • close
  • move
  • no border
  • to desktop n
  • minimise
binary state:
These actions should also be applied to each window, it makes more sense for the first click to synchronise the state of all windows
(e.g. if some windows are minimised and some are not, to restore all windows with the first click) rather than to toggle the state of all windows.
  • toggle minimise/restore
  • keep above
  • keep below
  • send to all desktops
  • shade*
whole group - geometry:
These actions are a little more complicated. It makes sense to keep the relative geometry of the whole group fixed when resizing it and to "shade" a group into a single titlebar.
  • resize
  • maximise
  • shade*
not available:
The following actions cannot be applied to the whole group and should be applied to the single window
  • fullscreen
  • "special window settings"/"application settings" - replaced by "group settings"
* from the user's point of view it would make most sense if 'shade group' collapsed all windows into one bar, however this might be tricky to implement.

new functions:
New operations for managing the grouping of windows, these are self-explanatory.
  • group with...
  • remove window from group
  • ungroup (disband group)
4. graphical feedback

The problems here don't appear to be huge but, again, not knowing much about the practicalities I can't say how easy they will be to solve. The following is the situation as I see it.

Despite trying to design a window grouping functionality that is as simple and transparent as possible, it is desirable to have some feedback to the user to communicate some information, namely:
  1. Which windows are currently selected
  2. Is the current window part of a group and which other windows are part of that group
1 and 2 can be seen as part of the same problem. We need only to be able to highlight one set of windows. While a set of windows are selected, highlight that set, else if the active window belongs to a group highlight that group. Holding [IGMK] should turn off the group highlighting since we are telling KWin to ignore grouping.

We would like to be able to use existing window decorators without adding functionality to deal with groups. It would also be rather hackinsh and ugly to try to layer graphical feedback on top of the window manager. So what is the best way to proceed?

5. summary of implementation:

  1. Data structures for storing information about groups, ability to query whether a window belongs to a group, which group etc.
  2. Functions to "act on group" for maximise, minimise, close, open, move etc.
  3. Select and group multiple windows.
  4. Alternate right-click window management menu for group actions.
  5. Graphical highlighting of groups and selected windows.
  6. A KControl module for editing global settings for window groups such as "auto-group windows belonging to a single app" and choosing the shortcut keys.

EDIT: It seems a feature-request exists for this on KDE bug tracker. The feature request doesn't go into details but a reply does note that the feature already exists in Blackbox. Does anyone have experience of this?

1 comment:

Stuart said...

I really like the concept. I would be happy with the compiz way which I find quite intuitive. The working into menus would be useful but I would almost always use either the modifier selection or as I do in compiz set every window to start with the icon so I can drag one onto the other.