summaryrefslogtreecommitdiffstats
path: root/twin/README
diff options
context:
space:
mode:
Diffstat (limited to 'twin/README')
-rw-r--r--twin/README206
1 files changed, 206 insertions, 0 deletions
diff --git a/twin/README b/twin/README
new file mode 100644
index 000000000..8d61c7163
--- /dev/null
+++ b/twin/README
@@ -0,0 +1,206 @@
+- The mailing list for KWin is twin@kde.org (https://mail.kde.org/mailman/listinfo/twin).
+
+- If you want to develop KWin, see file HACKING.
+
+- If you want to check KWin's compliance with specifications, see file COMPLIANCE.
+
+- File CONFIGURATION includes some details on configuring KWin.
+
+- Below is some info for application developers about application interaction
+ with the window manager, but it'd need some cleanup.
+
+
+
+
+
+
+
+
+ This README is meant as an explanation of various window manager related
+mechanisms that application developers need to be aware of. As some of these
+concepts may be difficult to understand for people not having the required
+background knowledge (since sometimes it's difficult even for people who
+do have the knowledge), the mechanisms are first briefly explained, and
+then an example of fixing the various problems is given.
+
+ For comments, questions, suggestions and whatever use the twin@kde.org
+mailing list.
+
+
+Table of contents:
+==================
+
+- Window relations
+ - how to make the window manager know which windows belong together
+- Focus stealing prevention
+ - how to solve cases where focus stealing prevention doesn't work
+ properly automatically
+
+
+
+Window relations:
+=================
+
+(For now, this explanation of window relations is mainly meant for
+focus stealing prevention. To be extended later.)
+
+ All windows created by an application should be organized in a tree
+with the root being the application's main window. Note that this is about
+toplevel windows, not widgets inside the windows. For example, if you
+have KWrite running, with a torn-off toolbar (i.e. a standalone toolbar),
+a file save dialog open, and the file save dialog showing a dialog
+for creating a directory, the window hiearchy should look like this:
+
+
+ KWrite mainwindow
+ / \
+ / \
+ file save dialog torn-off toolbar
+ \
+ \
+ create directory dialog
+
+ Each subwindow (i.e. all except for the KWrite mainwindow) points to its
+main window (which in turn may have another main window, as in the case
+of the file save dialog). When the window manager knows these relations,
+it can better arrange the windows (keeping subwindows above their
+main windows, preventing activation of a main window of a modal dialog,
+and similar). Failing to provide this information to the window manager
+may have various results, for example having dialogs positioned below
+the main window,
+
+The window property used by subwindows to point to their mainwindows is
+called WM_TRANSIENT_FOR. It can be seen by running
+'xprop | grep WM_TRANSIENT_FOR' and clicking on a window. If the property
+is not present, the window does not (claim to) have any mainwindow.
+If the property is present, it's value is the window id of its main window;
+window id of any window can be found out by running 'xwininfo'. A window
+having WM_TRANSIENT_FOR poiting to another window is said to be transient
+for that window.
+
+ In some cases, the WM_TRANSIENT_FOR property may not point to any other
+existing window, having value of 0, or pointing to the screen number
+('xwininfo -root'). These special values mean that the window is transient
+for all other windows in its window group. This should be used only
+in rare cases, everytime a specific main window is known, WM_TRANSIENT_FOR
+should be pointing to it instead of using one of these special values.
+(The explanation why is beyond the scope of this document - just accept it
+as a fact.)
+
+ With Qt, the WM_TRANSIENT_FOR property is set by Qt automatically, based
+on the toplevel widget's parent. If the toplevel widget is of a normal
+type (i.e. not a dialog, toolbar, etc.), Qt doesn't set WM_TRANSIENT_FOR
+on it. For special widgets, such as dialogs, WM_TRANSIENT_FOR is set
+to point to the widget's parent, if it has a specific parent, otherwise
+WM_TRANSIENT_FOR points to the root window.
+
+ As already said above, WM_TRANSIENT_FOR poiting to the root window should
+be usually avoided, so everytime the widget's main widget is known, the widget
+should get it passed as a parent in its constructor.
+(TODO KDialog etc. classes should not have a default argument for the parent
+argument, and comments like 'just pass 0 as the parent' should go.)
+
+
+
+Focus stealing prevention:
+==========================
+
+ Since KDE3.2 KWin has a feature called focus stealing prevention. As the name
+suggests, it prevents unexpected changes of focus. With older versions of KWin,
+if any application opened a new dialog, it became active, and
+if the application's main window was on another virtual desktop, also
+the virtual desktop was changed. This was annoying, and also sometimes led
+to dialogs mistakenly being closed because they received keyboard input that
+was meant for the previously active window.
+
+ The basic principle of focus stealing prevention is that the window with most
+recent user activity wins. Any window of an application will become active
+when being shown only if this application was the most recently used one.
+KWin itself, and some of the related tdecore classes should take care
+of the common cases, so usually there's no need for any special handling
+in applications. Qt/KDE applications, that is. Applications using other
+toolkits should in most cases work fine too. If they don't support
+the window property _NET_WM_USER_TIME, the window manager may fail to detect
+the user timestamp properly, resulting either in other windows becoming active
+while the user works with this application, or this application may sometimes
+steal focus (this second case should be very rare though).
+
+ There are also cases where KDE applications needs special handling. The two
+most common cases are when windows relations are not setup properly to make
+KWin realize that they belong to the same application, and when the user
+activity is not represented by manipulating with the application windows
+themselves.
+
+ Also note that focus stealing prevention implemented in the window manager
+can only help with focus stealing between different applications.
+If an application itself suddenly pops up a dialog, KWin cannot do anything about
+it, and its the application's job to handle this case.
+
+
+Window relations:
+-----------------
+
+ The common case here is when a dialog is shown for an application, but this
+dialog is not provided by the application itself, but by some other process.
+For example, dialogs with warnings about accepted cookies are provided
+by KCookieJar, instead of being shown by Konqueror. In the normal case,
+from KWin's point of view the cookie dialog would be an attempt of another
+application to show a dialog, and KWin wouldn't allow activation of this
+window.
+
+ The solution is to tell the window manager about the relation between
+the Konqueror main window and the cookie dialog, by making the dialog
+point to the mainwindow. Note that this is not special to focus stealing
+prevention, subwindows such as dialogs, toolbars and similar should always
+point to their mainwindow. See the section on window relations for full
+description.
+
+ The WM_TRANSIENT_FOR property that's set on dialogs to point to their
+mainwindow should in the cookie dialog case point to the Konqueror window
+for which it has been shown. This is solved in kcookiejar by including
+the window id in the DCOP call. When the cookie dialog is shown, its
+WM_TRANSIENT_FOR property is manually set using the XSetTransientForHint()
+call (see tdelibs/tdeioslave/http/kcookiejar/kcookiewin.cpp). The arguments
+to XSetTransientForHint() call are the X display (i.e. qt_xdisplay()),
+the window id on which the WM_TRANSIENT_FOR property is to be set
+(i.e. use QWidget::winId()), and the window id of the mainwindow.
+
+
+ Simple short HOWTO:
+
+ To put it simply: Let's say you have a daemon application that has
+DCOP call "showDialog( QString text )", and when this is called, it shows
+a dialog with the given text. This won't work properly with focus stealing
+prevention. The DCOP call should be changed to
+"showDialog( QString text, long id )". The caller should pass something like
+myMainWindow->winId() as the second argument. In the daemon, before
+the dialog is shown, a call to XSetTransientHint() should be added:
+
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), id_of_mainwindow );
+
+ That's it.
+
+Non-standard user activity:
+---------------------------
+
+ The most common case in KDE will be DCOP calls. For example, KDesktop's DCOP
+call "KDesktopIface popupExecuteCommand". Executing this DCOP call e.g.
+from Konsole as 'dcop kdesktop KDesktopIface popupExecuteCommand" will lead
+to showing the minicli, but the last user activity timestamp gained from events
+sent by X server will be older than user activity timestamp of Konsole, and
+would normally result in minicli not being active. Therefore, before showing
+the minicli, kdesktop needs to call TDEApplication::updateUserTimestamp().
+
+ However, this shouldn't be done with all DCOP calls. If a DCOP call is not
+a result of direct user action, calling TDEApplication::updateUserTimestamp()
+would lead to focus stealing. For example, let's assume for a moment
+that KMail would use this DCOP call in case it detects the modem is not
+connected, allowing to you to start KPPP or whatever tool you use. If KMail
+would be configured to check mail every 10 minutes, this would lead to minicli
+possibly suddenly showing up at every check. Basically, doing the above change
+to kdesktop's minicli means that the popupExecuteCommand() DCOP call is only
+for user scripting. (TODO write about focus transferring?)
+
+ Simply said, TDEApplication::updateUserTimestamp() should be called only
+as a result of user action. Unfortunately, I'm not aware of any universal
+way how to handle this, so every case will have to be considered separately.