System Dialogs

In some cases, we want to show the user dialogs that are not really scoped to any particular application.

Some of this material is old and refers to the GNOME 2 > 3 transition. The page needs reviewing and updating.

Examples

  • Shutdown dialog (status menu->shutdown)

  • Log out dialog (status menu->log out)

  • PolicyKit dialog (e.g. run virt-manager)

  • ConsoleHelper (e.g. run system-config-foo)

Discussion

These dialogs require immediate attention from the user and should take "center stage". For example, a user shouldn't be able to sideline a system password dialog, because entering the password is a very important task that the user should be acutely conscious of. We don't want to desensitize the user from the risks of giving their password to anything that asks for it. In this vein, system password dialogs should look distinct, so that when a non-system dialog asks for the password the user questions whether or not to proceed.

The shutdown dialog is another example of something the user needs to deal with right away. If they don't then the system is going to shutdown without them.

In a sense these types of dialogs are analagous to modal dialogs in applications (like say confirmation dialogs), but instead of being tied to particular document windows or applications, they're tied to the entire session.

Most common system dialogs

Because they're tied to the entire session, it makes sense for the common ones to look like they are part of the the shell. To the user, the shell is the system­—the negative space that is not the applications. System dialogs fall into this same approximate cognitive domain.

From a technical point of view, this means the dialogs will probably need to be implemented directly within the shell process. This is because

  1. There's no current plans to provide a mechanism for making apps using gtk widgets to "look like" the shell. This precludes doing the dialog presentation outside of the shell
  2. Designers should have the freedom to design each system dialog independently without being tied down by rules implicitly imposed by some generic "actions based" shell provided interprocess api. i.e., there would be an artificial loss of flexibility in how a dialog could be designed and laid out, if the shell was told to "show a system modal dialog with 'this text' and 'these buttons'" rather than "Show the logout dialog". An alternative idea would be to go with the generic actions based api, but then mitigate the loss of flexibility by putting some sort of system-defined "context hint" in the api. It probably makes sense to go with the specific APIs instead of the generic API+context hint, because we can then "form-fit" the APIs to match the scenarios in which they're used. Of course, even after going with the form-fit APIs, there's nothing stopping us from adding a more generic API later, if necessary.

Like most other UI in the shell, system dialogs should be implemented in javascript. While not only more convenient than C, this also gives them the ability to be easily themed with css. Still, we should try to provide a common "SystemDialog" object that the specific dialogs subclass as needed. This should help cut down on cut-and-paste code and provide some visual consistency between dialogs where visual consistency is appropriate.

One question is, should these dialogs be exposed via a D-Bus api over the session bus? Or via some mechanism involving ClientMessages over the X protocol? Both options seem valid. There's already some precedent for showing dialogs via ClientMessages. The _GNOME_PANEL_ACTION protocol is used in gnome 2 between metacity and the panel to have the panel show its run dialog. On the other hand, D-Bus is certainly a more modern fit. And some might argue that D-Bus was designed for doing exactly this sort of thing. The only real advantage with going with an X based approach is to facilitate interoperability with legacy applications (where using D-Bus would be potentially difficult). That advantage doesn't really apply for these types of dialogs, though, since each of these dialogs is designed to be called from by specific, modern clients.

DBus in the shell

There are a number of libraries that provide access to the message bus loaded in gnome-shell:

  • It currently uses dbus-glib to register itself on the session bus. There's also a copy-and-paste of gdm code in the shell for the user switcher menu that uses dbus-glib.
  • The javascript bindings provide a an interface to dbus called gjs-dbus.
  • gio in glib ships with its own dbus implementation.

Given the dialogs will be implemented in javascript, we'll be using the gjs-dbus interface to the bus.

The current primary shell dbus interface is in shellDBus.js:

const GnomeShellIface = {
    name: 'org.gnome.Shell',
    methods: [{ name: 'Eval',
                inSignature: 's',
                outSignature: 'bs'
              }
             ],
    signals: [],
    properties: [{ name: 'OverviewActive',
                   signature: 'b',
                   access: 'readwrite' }]
};

Right now there is only 1 method (Eval) and 1 property (OverviewActive) exposed on the /org/gnome/Shell object. It's probably best to leave this main object alone and have subobjects for the individual dialogs. The javascript api for putting an object on the bus is DBus.session.exportObject(objectPath, this); in the constructor and DBus.conformExport(ObjectGoesHere.prototype, IfaceGoesHere); at the bottom of the file.

Shell Extensions

Another point to think about it that each dialog is in many ways specific to the application that needs it. What I mean is, we probably don't want applications to call, e.g., org.gnome.Shell.LogoutDialog.Open directly, but instead to call org.gnome.SessionManager.Logout. The only thing that should ever tell the shell directly to put up the logout dialog is gnome-session. We really want a private API between the shell and the specific application that "owns" a particular system modal dialog. That API needs to be flexible so it can be changed as the needs of the application change, as well. Ideally, that means we would ship the code for making the dialogs with the individual apps that want the dialogs. The shell already provides a convenient extension system for doing just this sort of thing. It allows applications to install a javascript file and custom stylesheet, and those bits are automatically loaded and run when the shell starts up. I think it makes sense to leverage that feature to allow dialogs to be tightly coupled with their applications.

The next question is how much "implementation" (versus "presentation") should be in the javascript files. E.g., should the shutdown dialog javascript just reply what choice the user chose and let the caller process the shutdown, or should it actually initiate the shutdown in response to the user's choice? The extensions do have full access to most platform APIs and services via GObject introspection and via the messages buses, so in many cases it shouldn't be problem to do the implementation from within the javascript code. On the other hand, it does mean the code will be running within the context of the shell. Bugs in the code could destabilize the shell, synchronous calls could block the shell, etc. I think the answer to the implementation-presentation-split question may vary on a case by case basis.

gnome-shell already provides a mechanism for creating stub extensions on the fly. The gnome-shell --create-extension command will ask a few questions and then dump a javascript file, stylesheet, and extension metadata file into the user's ~/.local/share/gnome-shell/extensions/ directory. These stub files are a starting point for creating the dialogs.

Fallback for less common system dialogs

There may be scenarios where a system modal dialog is really required, but a design isn't yet implemented in the shell, or wouldn't be appropriate for the shell. In these cases, while not providing the "look" of a system dialog, we may still want to provide the "feel". Some examples of "feel" include:

  1. Presenting the dialog above all others
  2. Disabling interaction to other windows
  3. Centering the dialog on screen
  4. Enforcing one system modal dialog at a time.

One question then is, how do we let applications tell the shell to "treat this window as system modal" ?

Right now, applications tell the window manager about application modal dialogs by the WM_TRANSIENT_FOR property. An, e.g., confirmation dialog, sets the value of this property to the xid of its parent, and then window manager treats that confirmation dialog special with respect to that parent (if the parent is minimized, then the dialog is, too, the dialog is centered on the parent when mapped, etc). So one obvious idea would be to set WM_TRANSIENT_FOR to the root window as a way of informing the window manager that a dialog should be system modal. Unfortunately, the Extended Window Manager Hints specification says:

  • If the WM_TRANSIENT_FOR property is set to None or Root window, the window should be treated as a transient for all other windows in the same group.

So using the XID of the root window in WM_TRANSIENT_FOR already has a well defined and conflicting meaning.

Another idea would be to use the XID of the shell stage or composite overlay window. These are possibilities, but there's already precedent for implementing system modal dialogs using MWM hints (by the motif window manager).

mutter already implements some MWM hints for controlling window decorations, so it's fairly natural to extend that support for system modal dialogs. mutter has this in xprops.h:

  /* Copied from Lesstif by way of GTK. Rudimentary docs can be
   * found in some Motif reference guides online.
   */
  typedef struct {
      unsigned long flags;
      unsigned long functions;
      unsigned long decorations;
      long input_mode;
      unsigned long status;
  } MotifWmHints, MwmHints;

This structure is automatically filled in and associated with new windows. the "input_mode" field contains the value used to specify if the window is system modal or not. It's possible values are:

#define MWM_INPUT_MODELESS 0
#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
#define MWM_INPUT_SYSTEM_MODAL 2
#define MWM_INPUT_FULL_APPLICATION_MODAL 3

These values are currently ignored by mutter, but that could easily be changed. On the client side, there's presently no toolkit support for setting the input_mode property. GDK does set the _MWM_HINTS property, for decoration handling, though. This means, if we do go the "use mwm hints" route, then we'll need to be careful to update the hints after GDK is done with its decoration handling. This will require some careful consideration in client code. Eventually, it may make sense to add direct support in GTK+ to hide some of the murky details and prevent the property from getting changed twice in a row. Or, given the limited utility of system model dialogs, it may make sense to keep this code out of the toolkit.

See Also

Design/OS/SystemDialogs (last edited 2015-10-20 16:39:57 by AllanDay)