Development/Tutorials/Session Management: Difference between revisions

From KDE TechBase
No edit summary
(removed description of (KDE3) RESTORE - instead using kRestoreMainWindows also for one type of main window)
Line 63: Line 63:


While [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 KMainWindow::saveProperties()] and [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 KMainWindow::queryClose()] will work out of the box, [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#c8d0d64ed5b309ba1da410423120d0a6 KMainWindow::readProperties()] will not. You have to add some code to your main() function to implement session restoring.
While [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 KMainWindow::saveProperties()] and [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 KMainWindow::queryClose()] will work out of the box, [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#c8d0d64ed5b309ba1da410423120d0a6 KMainWindow::readProperties()] will not. You have to add some code to your main() function to implement session restoring.
====For one kind of toplevel widget====
If your client has only one kind of toplevel widgets (which should be pretty usual) then you should use the RESTORE-macro.


Imagine you have an
Imagine you have an
Line 78: Line 74:
KApplication app;
KApplication app;
if ( app.isSessionRestored() ) {
if ( app.isSessionRestored() ) {
   RESTORE( MyWindow )
   kRestoreMainWindows< MyWindow >();
} else {
} else {
   // create default application as usual
   // create default application as usual
   // for example:
   // for example:
   MyWindow* window = new MyWindow();
   MyWindow * window = new MyWindow();
   // # will be replaced with numbers that are guaranteed
   // # will be replaced with numbers that are guaranteed
   // to be unique in the application:
   // to be unique in the application:
   window->setObjectName("MainWindow#");
   window->setObjectName("MyWindow#");
   window->show();
   window->show();
}
}
Line 91: Line 87:
</code>
</code>


RESTORE will create as many instances of MyWindow as have existed in the last session. Note that QWidget::show() is called.
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/kmainwindow_8h.html#88ce427e39f425eefa5a94d746eb2bed kRestoreMainWindows<>()] will create (on the heap) as many instances of your main windows as have existed in the last session and call [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#46e01bd1aa6d488f1be2a5010030efb2 KMainWindow::restore()] with the correct arguments. Note that also QWidget::show() is called implicitly.
 
About setObjectName("MyWindow#"): For session management and window management to work properly, all main windows in the application should have a different name. If you don't do it, KMainWindow will create a unique name, but it's recommended to explicitly pass a window name that will also describe the type of the window. If there can be several windows of the same type, append '#' (hash) to the name, and KMainWindow will replace it with numbers to make the names unique. For example, for a mail client which has one main window showing the mails and folders, and which can also have one or more windows for composing mails, the name for the folders window should be e.g. "mainwindow" and for the composer windows "composer#".


With this you can easily restore all toplevel windows of your application.
With this you can easily restore all toplevel windows of your application.


====For several kinds of toplevel widgets====
It is also possible to restore different types of toplevel windows (each
 
derived from [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], of course) within one application. Imagine you have three classes of main windows: childMW1, childMW2 and childMW3:
It is also possible to
restore different types of toplevel windows within one application. In
that case, the RESTORE macro is too primitive. If you have more than one
kind of toplevel widget (each derived from [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], of course), you
can use the templated [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/kmainwindow_8h.html#88ce427e39f425eefa5a94d746eb2bed kRestoreMainWindows()] global functions:


<code cppqt>
<code cppqt>
Line 125: Line 118:
</code>
</code>


Currently, these functions are provided for up to three template arguments.
Currently, the [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/kmainwindow_8h.html#88ce427e39f425eefa5a94d746eb2bed kRestoreMainWindows<>()] template functions are provided for up to three template arguments.
 
===Internals===
 
These macros and template functions make use of [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#46e01bd1aa6d488f1be2a5010030efb2 KMainWindow::restore()] to restore the session.


==Appendix: Architecture of the KDE session manager==
==Appendix: Architecture of the KDE session manager==

Revision as of 22:49, 1 January 2009


Development/Tutorials/Session Management


About KDE and X11 session management

KDE supports the legacy X11R4 and ICCCM session management protocols. Legacy applications that define the WM_COMMAND property or support the WM_SAVE_YOURSELF protocol will be restarted with the specified command. The window geometries will be restored on a best effort basis.

Since version 2.0, KDE also supports and uses the standard X11R6 session management protocol XSMP. The official documentation of the standard can be download from the X Consortium's FTP server ftp.x.org. Unlike these legacy protocols, the new X11R6 session management gives a chance to save application dependent settings when you log out. A text editor, for instance, would save the names of the loaded files and would reload them when you log in again. Another major advantage of the new protocol is the support for a clean and safe logout procedure even if the users decides not to restore the session next time. The protocol gives applications the possibility to interact with the user in case they are in danger to lose some data, and to cancel the shutdown process if necessary.

Further Reading

An introductive overview of session management functionality and the Qt API for it is available from doc.trolltech.com.

In KDE, the classes KApplication and KMainWindow hide all the ugly details from the programmer. Basically, a KApplication manages a KConfig configuration object sessionConfig() for you, that your application can utilize to store session specific data.

Please read the respective class documentation, especially the one of KMainWindow, for a detailed interface description. With the advanced functionality in KMainWindow, it's really just a matter of a few lines to get even a multi-window application to retains its state between different user sessions.

Implementing session management in your application

Here's just a brief overview how things are done. Again, see the respective class documentation for details.

Implementing session management in KDE is easy. If your main window inherits from KMainWindow, you have just 2 things to do:

  • Reimplement some virtual functions of KMainWindow.
  • Add session management support to your main() function.

That's all.

Reimplement some virtual functions of KMainWindow

KMainWindow will save its position, geometry and positions of toolbars and menubar on logout.

  • To warn the user that the application or some windows have unsaved data on close or logout (for example: show a dialog with the buttons "Save changes" and "Discard changes"), reimplement queryClose().
  • To save additional data, reimplement saveProperties(). (For a text editor, that would be the loaded files, for example.) Note that no user interaction is allowed in this function! For example, you may not display any dialog!
  • To read the additional data again on next login, reimplement readProperties().

These functions are called automatically by KMainWindow respectively by the session manager. Note that it is not determined if saveProperties() is called before or after queryClose()! Please read documentation of the respective functions before reimplementing them.

To save your application-wide properties (data that is only needed once per application, and not for each main window) reimplement saveGlobalProperties() and it's counterpart readGlobalProperties. Normally, you don't need these functions.

Add session management support to your main() function

While KMainWindow::saveProperties() and KMainWindow::queryClose() will work out of the box, KMainWindow::readProperties() will not. You have to add some code to your main() function to implement session restoring.

Imagine you have an application with a main window MyWindow inherited from KMainWindow (or from KXmlGuiWindow, which inherits from KMainWindow). In your main() function, you would then create/restore the application windows with something like:

KApplication app; if ( app.isSessionRestored() ) {

 kRestoreMainWindows< MyWindow >();

} else {

 // create default application as usual
 // for example:
 MyWindow * window = new MyWindow();
 // # will be replaced with numbers that are guaranteed
 // to be unique in the application:
 window->setObjectName("MyWindow#");
 window->show();

} return app.exec();

kRestoreMainWindows<>() will create (on the heap) as many instances of your main windows as have existed in the last session and call KMainWindow::restore() with the correct arguments. Note that also QWidget::show() is called implicitly.

About setObjectName("MyWindow#"): For session management and window management to work properly, all main windows in the application should have a different name. If you don't do it, KMainWindow will create a unique name, but it's recommended to explicitly pass a window name that will also describe the type of the window. If there can be several windows of the same type, append '#' (hash) to the name, and KMainWindow will replace it with numbers to make the names unique. For example, for a mail client which has one main window showing the mails and folders, and which can also have one or more windows for composing mails, the name for the folders window should be e.g. "mainwindow" and for the composer windows "composer#".

With this you can easily restore all toplevel windows of your application.

It is also possible to restore different types of toplevel windows (each derived from KMainWindow, of course) within one application. Imagine you have three classes of main windows: childMW1, childMW2 and childMW3:

KApplication app; if ( app.isSessionRestored() ) {

 kRestoreMainWindows< childMW1, childMW2, childMW3 >();

} else {

 // create default application as usual
 // for example:
 childMW1* window1 = new childMW1();
 childMW2* window2 = new childMW2();
 childMW3* window3 = new childMW3();
 // # will be replaced with numbers that are guaranteed
 // to be unique in the application:
 window1->setObjectName("type1mainWindow#");
 window2->setObjectName("type2mainWindow#");
 window3->setObjectName("type3mainWindow#");
 window1->show();
 window2->show();
 window3->show();

} return app.exec();

Currently, the kRestoreMainWindows<>() template functions are provided for up to three template arguments.

Appendix: Architecture of the KDE session manager

The session management server in KDE is called ksmserver and it is part of the kdebase package. The server interacts with the KDE window manager kwin to save and restore the window geometries and to perform legacy session management. To make session management work, ksmserver has to be started as last process of the X login procedure. This happens automatically at the end of the startkde script.


Initial Author: Matthias Ettrich