Difference between revisions of "Development/Tutorials/Session Management"

Jump to: navigation, search
(code corrected)
 
(24 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{Template:I18n/Language Navigation Bar|Development/Tutorials/Session Management}}
+
 
 +
 
 +
{{TutorialBrowser|
 +
 
 +
series=Basics|
 +
 
 +
name=Session Management|
 +
 
 +
pre=[[Development/Tutorials/Creating_Libraries|Creating Libraries]]|
 +
 
 +
next=|
 +
 
 +
reading=[http://doc.trolltech.com/4.4/session.html Session Management in the Qt documentation]; [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow]; [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html KApplication]
 +
}}
  
 
==About KDE and X11 session management==
 
==About KDE and X11 session management==
  
KDE supports the legacy X11R4 and ICCCM session
+
Since KDE 1.0, KDE supports the legacy X11R4 and ICCCM session management protocols. It will restart with the specified command all legacy applications that define the <tt>WM_COMMAND</tt> property or support the <tt>WM_SAVE_YOURSELF</tt> protocol. It will also restore the window geometries on a best effort basis.
management protocols. Legacy applications that define the <tt>WM_COMMAND</tt>
+
property or support the <tt>WM_SAVE_YOURSELF</tt> 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
+
Since KDE 2.0, KDE also supports the standard X11R6 session management protocol XSMP and uses it. You can download the official documentation of the
session management protocol XSMP. The official documentation of the
+
standard from the X Consortium's FTP server  
standard can be download from the X Consortium's FTP server  
+
[http://stuff.mit.edu/afs/sipb/contrib/doc/X11/hardcopy/SM/xsmp.PS.gz ftp.x.org]. Unlike the legacy protocols, the new X11R6
[http://stuff.mit.edu/afs/sipb/contrib/doc/X11/hardcopy/SM/xsmp.PS.gz ftp.x.org]. Unlike these legacy protocols, the new X11R6
+
 
session management gives a chance to save application
 
session management gives a chance to save application
 
dependent settings when you log out.  A text
 
dependent settings when you log out.  A text
Line 19: Line 27:
 
protocol is the support for a clean and safe logout procedure even if the
 
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
 
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
+
applications the possibility to interact with the user if they are in
 
danger to lose some data, and to cancel the shutdown process if necessary.
 
danger to lose some data, and to cancel the shutdown process if necessary.
  
 
==Further Reading==
 
==Further Reading==
  
An introductive overview of session management functionality and
+
An introductory overview of session management functionality and
 
the Qt API for it is available from [http://doc.trolltech.com/4.4/session.html doc.trolltech.com].
 
the Qt API for it is available from [http://doc.trolltech.com/4.4/session.html doc.trolltech.com].
  
Line 31: Line 39:
 
hide all the ugly details from the programmer. Basically, a
 
hide all the ugly details from the programmer. Basically, a
 
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html KApplication] manages a
 
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html KApplication] manages a
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKConfig.html KConfig] configuration object
+
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKConfig.html KConfig] configuration object (available trough
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html#8f88369c240d6d90a04d29b2761989d9 sessionConfig()]
+
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html#8f88369c240d6d90a04d29b2761989d9 KApplication::sessionConfig()])
for you, that your application can utilize to store session specific data.
+
for you, that your application can use to store session specific data.
  
Please read the respective class documentation, especially the one of
+
Please read the class documentation, especially the one of
 
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], for a detailed interface description. With the advanced
 
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], for a detailed interface description. With the advanced
 
functionality in [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], it's really just a matter of a few lines to get even a multi-window application to retains its state between
 
functionality in [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], it's really just a matter of a few lines to get even a multi-window application to retains its state between
Line 42: Line 50:
 
==Implementing session management in your application==
 
==Implementing session management in your application==
  
Here's just a brief overview how things are done. Again, see the
+
Here's just a brief overview how you can add session management to your application. Again, see the class documentation for details.
respective class documentation for details.
+
  
Implementing session management in KDE is easy. You have just 2 things to do:
+
Implementing session management in KDE is easy. If your main window inherits from [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], you have just 2 things to do:
- Add session management support to your main() function.
+
* Reimplement some virtual functions of [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow].
- Reimplement some virtual functions of KMainWindow.
+
* Add session management support to your main() function.
 
That's all.
 
That's all.
  
===Add session management support to your main() function===
+
===Reimplement some virtual functions of KMainWindow===
  
====For one kind of toplevel widget====
+
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow] will automatically save its position, geometry and positions of toolbars and menu bar on logout - and restore it on the next startup.
 +
 
 +
For every other data that your application needs to restore a session, you have to write the code for saving and restoring yourself. However, [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow] makes this task easy. You can just re-implement the following functions:
 +
* [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 saveProperties()]: This function is called only when the session manager closes the application (and not when the user closes the application). To save the data that you need to restore the session, reimplement this function. (For a text editor that would be the list of loaded files) Note that you may not do any user interaction in this function! (For example, you may not display any dialog!)
 +
* [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#c8d0d64ed5b309ba1da410423120d0a6 readProperties()]: To read the data again on next login, reimplement this function.
 +
 
 +
Furthermore, the function [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 queryClose()] could be interesting for you. This function is called ''always'' before the window is closed, either by the user or indirectly by the session manager. ''(Note that this is not the case for a call of KApplication::quit() because this function will exit the event loop without causing a close event for the main windows. It will even not destroy them.)'' Typically, here you can warn the user that the application or some windows have unsaved data on close or logout (example: show a dialog with the buttons "Save changes" and "Discard changes"). However, for session management it isn't nice to need a user interaction before closing, so you better avoid this. Note that it is not determined if [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 saveProperties()] is called before or after [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 queryClose()]!
 +
 
 +
''To save your application-wide properties (data that is only needed once per application, and not for each main window instance) reimplement [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#cf811d77a3acdcf2b61f8826429615a7 saveGlobalProperties()] and it's counterpart [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#2d4da4f305f00e8a5c94f5b978334231 readGlobalProperties].  Normally, you don't need these functions.''
 +
 
 +
===Add session management support to your main() function===
  
If your client has only one kind of toplevel widgets (which should be pretty usual) then you should use the RESTORE-macro.
+
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 be called automatically, [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 add session restoring.
  
 
Imagine you have an
 
Imagine you have an
Line 61: Line 78:
 
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKXmlGuiWindow.html KXmlGuiWindow], which inherits from
 
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKXmlGuiWindow.html KXmlGuiWindow], which inherits from
 
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow]). In your main() function, you would then create/restore the
 
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow]). In your main() function, you would then create/restore the
application windows with something like:
+
application windows with something like this:
  
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
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:
+
   // example:
   MyWindow* window = new MyWindow();
+
   MyWindow * window = new MyWindow();
   // # will be replaced with numbers that are guaranteed to be unique in the application:
+
   // The function will replace '#' with numbers that are
   window->setObjectName("MainWindow#");
+
  // unique within the application:
 +
   window->setObjectName("MyWindow#");
 
   window->show();
 
   window->show();
 
}
 
}
 
return app.exec();
 
return app.exec();
</code>
+
</syntaxhighlight>
  
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.
  
With this you can easily restore all toplevel windows of your application.
+
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#".
  
====For several kinds of toplevel widgets====
+
With this you can easily restore all top-level windows of your application.
  
It is also possible to
+
It is also possible to restore different types of top-level windows (each
restore different types of toplevel windows within one application. In
+
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:
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 kRestoreMainWindows global functions:
+
  
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
KApplication app;
 
KApplication app;
if ( app->isSessionRestored() ) {
+
if ( app.isSessionRestored() ) {
 
   kRestoreMainWindows< childMW1, childMW2, childMW3 >();
 
   kRestoreMainWindows< childMW1, childMW2, childMW3 >();
 
} else {
 
} else {
 
   // create default application as usual
 
   // create default application as usual
   // for example:
+
   // example:
 
   childMW1* window1 = new childMW1();
 
   childMW1* window1 = new childMW1();
 
   childMW2* window2 = new childMW2();
 
   childMW2* window2 = new childMW2();
 
   childMW3* window3 = new childMW3();
 
   childMW3* window3 = new childMW3();
   // # will be replaced with numbers that are guaranteed to be unique in the application:
+
   // The function will replace '#' with numbers that are
 +
  // unique within the application:
 
   window1->setObjectName("type1mainWindow#");
 
   window1->setObjectName("type1mainWindow#");
 
   window2->setObjectName("type2mainWindow#");
 
   window2->setObjectName("type2mainWindow#");
Line 109: Line 125:
 
}
 
}
 
return app.exec();
 
return app.exec();
</code>
+
</syntaxhighlight>
 
+
Currently, these functions are provided for up to three template arguments.
+
 
+
===Reimplement some virtual functions of KMainWindow===
+
 
+
[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow] will save its position, geometry and positions of toolbars and menubar on logout. To save additional data, reimplement [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 saveProperties()] and (to read them again on next login) [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#c8d0d64ed5b309ba1da410423120d0a6 readProperties()]. (For a text editor, that would be the loaded files, for example.) To warn the user that the application or some windows have unsaved data on close or logout (and to give him the possibility to save them), reimplement [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 queryClose()]. These functions are called automatically by KMainWindow respectively by the session manager. Note that it is not determined if [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 saveProperties()] is called before or after [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 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 [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#cf811d77a3acdcf2b61f8826429615a7 saveGlobalProperties()] and it's counterpart [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#2d4da4f305f00e8a5c94f5b978334231 readGlobalProperties].  Normally, you don't need these functions.
+
Currently, kdelibs provides the [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/kmainwindow_8h.html#88ce427e39f425eefa5a94d746eb2bed kRestoreMainWindows<>()] template functions for up to three template arguments.
  
 
==Appendix: Architecture of the KDE session manager==
 
==Appendix: Architecture of the KDE session manager==
  
The session management server in KDE is called '''ksmserver''' and it is
+
The name of the session management server in KDE is '''ksmserver''' and it is
 
part of the '''kdebase''' package.  The server interacts with the KDE window
 
part of the '''kdebase''' package.  The server interacts with the KDE window
 
manager '''kwin''' to save and restore the window geometries and to perform
 
manager '''kwin''' to save and restore the window geometries and to perform

Latest revision as of 19:32, 15 July 2012


Session Management
Tutorial Series   Basics
Previous   Creating Libraries
What's Next  
Further Reading   Session Management in the Qt documentation; KMainWindow; KApplication

Contents

[edit] About KDE and X11 session management

Since KDE 1.0, KDE supports the legacy X11R4 and ICCCM session management protocols. It will restart with the specified command all legacy applications that define the WM_COMMAND property or support the WM_SAVE_YOURSELF protocol. It will also restore the window geometries on a best effort basis.

Since KDE 2.0, KDE also supports the standard X11R6 session management protocol XSMP and uses it. You can download the official documentation of the standard from the X Consortium's FTP server ftp.x.org. Unlike the 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 if they are in danger to lose some data, and to cancel the shutdown process if necessary.

[edit] Further Reading

An introductory 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 (available trough KApplication::sessionConfig()) for you, that your application can use to store session specific data.

Please read the 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.

[edit] Implementing session management in your application

Here's just a brief overview how you can add session management to your application. Again, see the 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.

[edit] Reimplement some virtual functions of KMainWindow

KMainWindow will automatically save its position, geometry and positions of toolbars and menu bar on logout - and restore it on the next startup.

For every other data that your application needs to restore a session, you have to write the code for saving and restoring yourself. However, KMainWindow makes this task easy. You can just re-implement the following functions:

  • saveProperties(): This function is called only when the session manager closes the application (and not when the user closes the application). To save the data that you need to restore the session, reimplement this function. (For a text editor that would be the list of loaded files) Note that you may not do any user interaction in this function! (For example, you may not display any dialog!)
  • readProperties(): To read the data again on next login, reimplement this function.

Furthermore, the function queryClose() could be interesting for you. This function is called always before the window is closed, either by the user or indirectly by the session manager. (Note that this is not the case for a call of KApplication::quit() because this function will exit the event loop without causing a close event for the main windows. It will even not destroy them.) Typically, here you can warn the user that the application or some windows have unsaved data on close or logout (example: show a dialog with the buttons "Save changes" and "Discard changes"). However, for session management it isn't nice to need a user interaction before closing, so you better avoid this. Note that it is not determined if saveProperties() is called before or after queryClose()!

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

[edit] Add session management support to your main() function

While KMainWindow::saveProperties() (and KMainWindow::queryClose()) will be called automatically, KMainWindow::readProperties() will not. You have to add some code to your main() function to add 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 this:

KApplication app;
if ( app.isSessionRestored() ) {
  kRestoreMainWindows< MyWindow >();
} else {
  // create default application as usual
  // example:
  MyWindow * window = new MyWindow();
  // The function will replace '#' with numbers that are
  // unique within 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 top-level windows of your application.

It is also possible to restore different types of top-level 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
  // example:
  childMW1* window1 = new childMW1();
  childMW2* window2 = new childMW2();
  childMW3* window3 = new childMW3();
  // The function will replace '#' with numbers that are
  // unique within the application:
  window1->setObjectName("type1mainWindow#");
  window2->setObjectName("type2mainWindow#");
  window3->setObjectName("type3mainWindow#");
  window1->show();
  window2->show();
  window3->show();
}
return app.exec();

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

[edit] Appendix: Architecture of the KDE session manager

The name of the session management server in KDE is 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


This page was last modified on 15 July 2012, at 19:32. This page has been accessed 17,561 times. Content is available under Creative Commons License SA 3.0 as well as the GNU Free Documentation License 1.2.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal