TIP 614: Windows: OS: WTSSESSION change notification

Login
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

Abstract

Add a TK notification when a Tk program in a Windows OS session is disconnected or connected to the user.

Rationale

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.

Proposal

The following new protocols are added to the wm protocol command:

Reference Implementation

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?

Harald answer:

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?

Harald answered:

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:

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:

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.

Test

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".

Change user

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".

Discussion

protocol names

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:

Implementation

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:

Should be in TCL

This functionality should be moved to a notification framework within TCL and not Tk.

Copyright

This document has been placed in the public domain.