Migration protocol ------------------ 0. Terminology We have an "old display" and a "new display". "window" is the window that is being moved from the old display to the new display, "mover" is the app that initiates the move. It must have a connection on the old display in order to send messages to the window, but it may in fact be an application which whose "home" is the new display (pull scenario) 1. Declaring participation in the protocol If the client who owns the window wants to allow moving it to a different display, it puts the _NET_CHANGE_DISPLAY atom in the WM_PROTOCOLS property on window. The idea here is that windows which don't support _NET_CHANGE_PROTOCOLS would not be listed when displaying a list of move candidates. Note that clients must still be prepared to get _NET_CHANGE_DISPLAY messages even if they don't list the protocol. 2. Initiating the move Mover puts a property on the window, containing the name of the display to move to, optionally followed by key-value pairs separated by line breaks. The display name must be a hostname:display.screen display name as understood by XOpenDisplay(). It is important to realize that the hostname must be suitable for connecting to the new display from whereever the client owning the window runs. E.g if the mover is actually running on the new display, the string returned by gdk_display_get_name() is most likely *not* suitable, since it may contain "localhost" or the empty string as hostname. This key is required. The atom naming the property can be freely choosen by the mover (a good choice would be _NET_CHANGE_DISPLAY) The mover sends a WM_PROTOCOLS client message as specified in the ICCCM to the window with the following: format: 32 type: WM_PROTOCOLS data[0]: _NEW_CHANGE_DISPLAY data[1]: data[2]: data[3]: where status-window is the X id of a window on which the mover listens for the client message indicating that the move is done. If this is set to None, the client message is sent back to the root window of the old display. 3. Moving When the client owning the window receives the aforementioned message, it connects to the new display, recreates the window and all transients belonging to it over there and closes the window on the old display. It then sends a client message on the old display to the status window specified in the message with the following contents: format: 32 type: _NET_CHANGE_DISPLAY data[0]: data[1]: data[2]: where window is the id of the window on the old display, the status code is interpreted as follows 0 success 1 unable to connect to display 2 requested screen does not exist 3 invalid authentication (not currently used) 4 indeterminate failure 5 move refused by the client who owns the window and new-window is either the id of the moved window on the new display, or None if the move was not successful or if the window id is not available for some other reason. GTK+ API to support the migration protocol ------------------------------------------ void gtk_window_set_allow_screen_change (GtkWindow *window, gboolean allow); can be called on a window before realizing it to determine whether the window participates in the _NET_CHANGE_DISPLAY protocol. By default windows do not participate in the protocol. (I added an environment variable to allow to override this for development purposes, but that won't stay) The will be a new signal on GtkWindow void (* change_screen) (const gchar *display, GdkChangeScreenStatus *status); enum GdkChangeScreenStatus { GDK_CHANGE_SCREEN_PENDING = -1, GDK_CHANGE_SCREEN_SUCCESS = 0, GDK_CHANGE_SCREEN_NO_DISPLAY = 1, GDK_CHANGE_SCREEN_NO_SCREEN = 2, GDK_CHANGE_SCREEN_NO_AUTH = 3, GDK_CHANGE_SCREEN_FAILURE = 4, GDK_CHANGE_SCREEN_REFUSED = 5 } Apps can connect to this signal and do whatever additional work they have to do before moving to the new screen. The can also complete the work of moving the window the new screen and do whatever setup is necessary over there. In that case, they have to update the status to reflect the result of the move. The default handler for the signal will move the window if the status indicates that the move is still pending, and a status client message will be sent back to the mover. The corresponding GDK API is void gdk_window_set_allow_screen_change (GdkWindow *window, gboolean allow); gboolean gdk_window_get_allow_screen_change (GdkWindow *window);