Author: Harald Oehlmann <[email protected]> State: Rejected Type: Project Vote: Done Created: 14-Jan-2022 Tcl-Version: 8.7 Tk-Ticket: 8a49f43b Tk-Branch: tip614-win-wtssession-change Vote-Summary: Rejected 1/2/2 Votes-For: JN Votes-Against: FV, KW Votes-Present: MC, SL
Add a TK notification when a Tk program in a Windows OS session is disconnected or connected to the user.
On Windows operating system, sessions (e.g. a whole desktop environment with all running programs) may be disconnected from the user and put into a hold state. There might be shared resources, which should only be active, if the program is connected to the user.
In my personal case, there is a barcode scanner connected by a serial interface. If a session is disconnected by the "Change User" button in the start menu, the serial interface should be closed. So, the new user in a new session may use the barcode scanner and it is not blocked by the disconnected session.
The following new protocols are added to the wm protocol command:
- WTS_CONSOLE_CONNECT and WTS_CONSOLE_DISCONNECT are sent on console connect/disconnect like a user change.
- WTS_REMOTE_CONNECT and WTS_REMOTE_DISCONNECT are sent on remote connect/disconnect.
- WTS_SESSION_LOGON and WTS_SESSION_LOGOFF are sent on session logon/logoff.
- WTS_SESSION_LOCK and WTS_SESSION_UNLOCK are sent when the session is locked by the user or on any upper action (as session lock is a side effect).
See the tk fossil branch tip614-win-wtssession-change.
Francois Vogel has commented the implementation and discussed the following points:
Double definition of macro "CurrentTime"
/* * Macro CurrentTime is defined in X.h. * CurrentTime is used as a variable name in the following include. * Thus, undefine it and define it back afterwards */ #undef CurrentTime #include<wtsapi32.h> #define CurrentTime 0L /* special Time */ #include "tkWinIco.h"
This looks a bit ugly. Isn't there a possibility to reorder the includes to avoid this? Doesn't this name conflict have some significance?
It is definitively ugly. It would be great to get a define with the name "CurrentTime" out of the public TCL headers. IMHO, there should never be a define without a "TCL_" prefix. Any recommendations welcome.
Symetry of calls to "WTSRegisterSessionNotification"/"WTSUnRegisterSessionNotification"
Another question. There is the following comment:
* Note: the Windows API requires to call * WTSUnRegisterSessionNotification for each prior call to * WTSRegisterSessionNotification. This would require to store * the registration fact somewhere and to call unregister on * windows destroy if registered. This is currently not implemented * and has probably no negative impacts.
Is this "no negative impacts" statement just your guess? Or do we introduce here some sort of Damocles sword that will hit us when expected the least? Note that the code in fact really calls WTSUnRegisterSessionNotification just below that comment, which makes me wonder whether this comment is correct?
Moreover, the documentation says:
When a window no longer requires these notifications, it must call WTSUnRegisterSessionNotification before being destroyed. For every call to this function, there must be a corresponding call to WTSUnRegisterSessionNotification.
Is this call before destroy implemented somewhere?
The backround to call "WTSUnRegisterSessionNotification" before registering it is, that we would get two notifications, if this is registered twice. So, it is unregistered just for the case it was registered before.
so: wm protocol . WTS_SESSION_LOGON myproc -> first registration for Window ".", unregistration fails but does not harm. wm protocol . WTS_SESSION_LOGOUT myproc -> 2nd registration for window ".", so unregistration is necessary.
"No negative impacts" means, that messages are never delivered, if the window is destroyed.
I agree, that it would be cleaner to: - save the fact if registered with the window data structure - call WTSUnRegisterSessionNotification on window destruction, if the registration took place.
I have to say, that such a solution is far from my programming skills. In consequence, I added the two warnings and implemented it with my limitted skills.
I may improve the implementation and follow two paths:
- Register any toplevel for session reporting and unregister on toplevel destroy
- Add a flag to the toplevel data structure, which is set on registration. If set, unregister on toplevel destroy.
I planned to write a "help request" on the core list to check those paths. As vote is currently in progress, I have to wait for the vote result.
To test the functionlity, user activity is required. There are no automated tests.
Here are some manual tests:
Lock screen detection
Enter in a wish compiled from branch "tip614-win-wtssession-change":
wm protocol . WTS_SESSION_LOCK "puts locked" wm protocol . WTS_SESSION_UNLOCK "puts unlocked"
Then lock your screen, for example by Windows+L key combination. When you unlock back, you will see the text "locked" and "unlocked".
Enter in a wish compiled from branch "tip614-win-wtssession-change":
wm protocol . WTS_CONSOLE_CONNECT "puts connect" wm protocol . WTS_CONSOLE_DISCONNECT "puts disconnect"
Then open the start menu and select "change user". Then log back in with the same user. You will see the text "disconnect" and "connect" in the console window. If the upper lock screen example is still active, you will also see "locked" and "unlocked".
The used protocol names are identical to the corresponding windows message define as listed in "WM_WTSSESSION_CHANGE".
implementation within wm protocol
There is a similar protocol on windows: wm protocol WM_SAFE_YOURSELF which reacts on the windows message WM_QUERYENDSESSION. This windows message is also session related and of similar nature. In consequence, this TIP is the extension of this behaviour
Why not in TCL, why with "wm protocol" ?
Strictly speaking, session control functionality belongs to TCL, not Tk. And it belongs to an application, not a particular toplevel window.
In contrast to those drawbacks, it is an extension of the existing wm protocol WM_SAFE_YOURSELF command, which exists already. It is logical, to place the new functionality close to this command.
Why not multi-platform ?
This is a Windows platform only TIP. Contributions and opinions for other platforms are welcome. Specially the message about a screen lock should exist on all platforms.
Implementation sketch on Linux
Christian Gollwitzer contributed on the core list information about Linux window managers:
On Linux, these things are solved by "dbus", which is an interprocess communication system for desktop OSes. Here is a description of the screensaver interface: GNOME Screensaver.
Despite this being a GNOME description, it works also on KDE and maybe others, because freedesktop.org atempts to standardize these APIs.
Fortunately, there is a dbus extension for Linux available by Schelte: TCL DBUS. Actually, it would make sense to include dbus in Tcl9 / Tk 9 as a standard extension.
dbus is an IPC protocol like DDE and Apple Events. With dbus you can both call a remote function and receive notifications on events that happen within the system.
dbus itself is agnostic of the purpose, but common Linux desktops (KDE, Gnome, partly XFCE...) use dbus to control the various desktop processes, and they currently try to harmonise on a common dbus protocols (freedesktop.org).
Here is some code in Python which uses dbus to do almost exactly what Harald suggests: Wait for dbus session lock unlock message.
If Schelte's package were included in core Tk, then sending an event on session lock/unlock would be a few lines of dbus code for Linux with no need for C level code, i.e. translate the Python from the link above.
Why not in Tk 8.6 ?
This enhancement may be seen as a bugfix to the wm protocol WM_SAFE_YOURSELF and thus may go to Tk 8.6. I would personally favor this, as Tk 8.6.13 may arise this year while Tk 8.7 is still in alpha phase and a release date is not in view.
Why was this TIP rejected?
There are two issues with the TIP:
The upper symetry of the notification calls was not fullfilled, what is not in conformance. An implementation sketch by Christian Werner introduced platform-specific code into generic code, what was seen as a no-go.
The implementation sketch is as follows:
- Add a new flag to TkWIndow flag field: #define TK_WIN_SESSION_NOTIFICATION_ENABLED 0x200000
- Use this flag to do the rgistration in win/tkWinWm.c
- If flag set, undo the rgistration in Tk_DestroyWindow. There is no way to do this in the Windows-only part of Tk, so we will have an ifdeffed part in the generic file.
Should be in TCL
This functionality should be moved to a notification framework within TCL and not Tk.
This document has been placed in the public domain.