Tk Source Code

Changes On Branch tip614-win-wtssession-change
Login
EuroTcl/OpenACS 11 - 12 JULY 2024, VIENNA

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch tip614-win-wtssession-change Excluding Merge-Ins

This is equivalent to a diff from ab0f950a to 6456cf4c

2022-03-07
21:35
Merge TIP #552 implementation, following positive vote by the TCT. Many thanks to Peter Spjuth! check-in: 58cb640d user: fvogel tags: trunk, main
2022-03-03
10:34
Merge 8.7. Also introduce *Ptr variable, to store the Tcl_Obj* of tag options check-in: 52c278b7 user: jan.nijtmans tags: revised_text, tip-466
2022-03-02
16:37
Merge 8.7 check-in: 4ee64e9f user: jan.nijtmans tags: tip-606
16:36
Merge 8.7 check-in: 4d6d5460 user: jan.nijtmans tags: tip-616
16:35
Merge 8.7 check-in: 26be88e2 user: jan.nijtmans tags: pspjuth-treeview
16:35
Merge 8.7 check-in: 28d67f76 user: jan.nijtmans tags: mac_styles_87
16:34
Merge 8.7 check-in: 00c426a5 user: jan.nijtmans tags: revised_text-bug
16:33
Merge 8.7 check-in: b67f55c2 user: jan.nijtmans tags: glyph_indexing_2
16:32
Merge 8.7 Closed-Leaf check-in: 6456cf4c user: jan.nijtmans tags: tip614-win-wtssession-change
16:28
Fix [e049e2a7b8]: macOS : error on compilation with tkMacOSXMouseEvent.c, due to merge conflict check-in: ab0f950a user: jan.nijtmans tags: trunk, main
13:44
Merge 8.7 check-in: 4edd4569 user: jan.nijtmans tags: tip614-win-wtssession-change
12:51
Merge 8.6 check-in: ed4aacb0 user: jan.nijtmans tags: trunk, main

Changes to doc/wm.n.

656
657
658
659
660
661
662
663



664
665




666
667
668
669
670
671
672
installs a handler for this protocol, which responds by destroying the
window. The \fBwm protocol\fR command can be used to replace this default
handler by one which responds differently.
.RE
.RS
.PP
The list of available window manager protocols depends on the window manager,
but all window managers supported by Tk provide \fBWM_DELETE_WINDOW\fR. On the



Windows platform, a \fBWM_SAVE_YOURSELF\fR message is sent on user logout
or system restart.




.RE
.RS
.PP
If both \fIname\fR and \fIcommand\fR are specified, then \fIcommand\fR becomes
the handler for the protocol specified by \fIname\fR. The atom for \fIname\fR
will be added to \fIwindow\fR's \fBWM_PROTOCOLS\fR property to tell the window
manager that the application has a handler for the protocol specified by







|
>
>
>
|
|
>
>
>
>







656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
installs a handler for this protocol, which responds by destroying the
window. The \fBwm protocol\fR command can be used to replace this default
handler by one which responds differently.
.RE
.RS
.PP
The list of available window manager protocols depends on the window manager,
but all window managers supported by Tk provide \fBWM_DELETE_WINDOW\fR.
.RE
.RS
.PP
On the Windows platform, the following additional messages are implemented.
\fBWM_SAVE_YOURSELF\fR is sent on user logout or system restart.
\fBWTS_CONSOLE_CONNECT\fR and \fBWTS_CONSOLE_DISCONNECT\fR are sent on console connect/disconnect like a user change.
\fBWTS_REMOTE_CONNECT\fR and \fBWTS_REMOTE_DISCONNECT\fR are sent on remote connect/disconnect.
\fBWTS_SESSION_LOGON\fR and \fBWTS_SESSION_LOGOFF\fR are sent on session logon/logoff.
\fBWTS_SESSION_LOCK\fR and \fBWTS_SESSION_UNLOCK\fR are sent when the session is locked by the user or on any upper action (as session lock is a side effect).
.RE
.RS
.PP
If both \fIname\fR and \fIcommand\fR are specified, then \fIcommand\fR becomes
the handler for the protocol specified by \fIname\fR. The atom for \fIname\fR
will be added to \fIwindow\fR's \fBWM_PROTOCOLS\fR property to tell the window
manager that the application has a handler for the protocol specified by

Changes to win/configure.

4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler flags" >&5
printf %s "checking compiler flags... " >&6; }
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32 -lwinspool"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \$@"







|







4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler flags" >&5
printf %s "checking compiler flags... " >&6; }
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32 -lwinspool -lwtsapi32"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \$@"
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo"
	    LINKBIN="link"
	fi

	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib winspool.lib"

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r







|







4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo"
	    LINKBIN="link"
	fi

	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib winspool.lib wtsapi32.lib"

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r

Changes to win/makefile.vc.

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
!if $(TK_NO_DEPRECATED)
		 /DTK_NO_DEPRECATED=1
!endif

PRJ_DEFINES	= /DBUILD_ttk $(CONFIG_DEFS) /Dinline=__inline /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE

# Additional Link libraries needed beyond those in rules.vc
PRJ_LIBS   = netapi32.lib gdi32.lib user32.lib userenv.lib winspool.lib shell32.lib ole32.lib uuid.lib

#---------------------------------------------------------------------
# TkTest flags
#---------------------------------------------------------------------

!if "$(TESTPAT)" != ""
TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)







|







356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
!if $(TK_NO_DEPRECATED)
		 /DTK_NO_DEPRECATED=1
!endif

PRJ_DEFINES	= /DBUILD_ttk $(CONFIG_DEFS) /Dinline=__inline /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE

# Additional Link libraries needed beyond those in rules.vc
PRJ_LIBS   = netapi32.lib gdi32.lib user32.lib userenv.lib winspool.lib shell32.lib ole32.lib uuid.lib wtsapi32.lib

#---------------------------------------------------------------------
# TkTest flags
#---------------------------------------------------------------------

!if "$(TESTPAT)" != ""
TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)

Changes to win/tcl.m4.

650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

    AC_MSG_CHECKING([compiler flags])
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32 -lwinspool"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \[$]@"







|







650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

    AC_MSG_CHECKING([compiler flags])
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32 -lwinspool -lwtsapi32"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \[$]@"
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo"
	    LINKBIN="link"
	fi

	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib winspool.lib"

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r







|







839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo"
	    LINKBIN="link"
	fi

	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib winspool.lib wtsapi32.lib"

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r

Changes to win/tkWinWm.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21










22
23
24
25
26
27
28
 *
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkWinInt.h"
#include <windows.h>
#include <wtypes.h>
#include <shobjidl.h>
#include <shlguid.h>
#include <shellapi.h>










#include "tkWinIco.h"
/*
 * These next two defines are only valid on Win2K/XP+.
 */

#ifndef WS_EX_LAYERED
#define WS_EX_LAYERED	0x00080000







<






>
>
>
>
>
>
>
>
>
>







8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 *
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkWinInt.h"
#include <windows.h>
#include <wtypes.h>
#include <shobjidl.h>
#include <shlguid.h>
#include <shellapi.h>

/*
 * 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"
/*
 * These next two defines are only valid on Win2K/XP+.
 */

#ifndef WS_EX_LAYERED
#define WS_EX_LAYERED	0x00080000
4927
4928
4929
4930
4931
4932
4933
































































4934
4935
4936
4937
4938
4939
4940
4941
	    }
	    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
	    break;
	}
    }
    cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);
    if (cmdLength > 0) {
































































	protPtr = (ProtocolHandler *)ckalloc(HANDLER_SIZE(cmdLength));
	protPtr->protocol = protocol;
	protPtr->nextPtr = wmPtr->protPtr;
	wmPtr->protPtr = protPtr;
	protPtr->interp = interp;
	memcpy(protPtr->command, cmd, cmdLength + 1);
    }
    return TCL_OK;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
	    }
	    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
	    break;
	}
    }
    cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);
    if (cmdLength > 0) {
        const char *item;
        TkSizeT itemLength;

	/*
	 * Activate notification by WM_WTSSESSION_CHANGE, for relevant
	 * messages. Note: this does not harm, if activated erroneously,
	 * so be relax on the protocol name and only check for prefix
	 * "WTS_".
	 */

        item = Tcl_GetStringFromObj(objv[3], &itemLength);
	if ((itemLength > 4) && (0 == memcmp(item,"WTS_", 4))) {

	    /*
	     * Unregister callback on Windows level.
	     * This is required, to avoid multiple notifications due to
	     * multiple registrations. We first clear an eventual registration
	     * here and recreate it back below. If there was no prior
	     * registration, the call fails, which is ok and is ignored.
	     *
	     * 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.
	     */

	    if (NULL != winPtr->wmInfoPtr
		    && NULL != winPtr->wmInfoPtr->wrapper) {
		WTSUnRegisterSessionNotification(
			winPtr->wmInfoPtr->wrapper);
	    }

	    /*
	     * Be sure that the window exists. If not, try to make it exist.
	     * This is required, if no "update" was run after windows
	     * creation.
	     */

	    if (NULL == winPtr->wmInfoPtr
		    || NULL == winPtr->wmInfoPtr->wrapper) {
		Tk_MakeWindowExist((Tk_Window)winPtr);
	    }

	    /*
	     * Activate notification by message WM_WTSSESSION_CHANGE.
	     */

	    if (NULL == winPtr->wmInfoPtr
		    || NULL == winPtr->wmInfoPtr->wrapper
		    || ! WTSRegisterSessionNotification(
			winPtr->wmInfoPtr->wrapper,
			NOTIFY_FOR_THIS_SESSION)
	    ) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"registration failed for window \"%s\"",
			Tk_PathName(winPtr)));
		Tcl_SetErrorCode(interp, "TK", "WM", "PROTOCOL", "FAIL",
			objv[3], NULL);
		return TCL_ERROR;
	    }
	}

        protPtr = (ProtocolHandler *)ckalloc(HANDLER_SIZE(cmdLength));
	protPtr->protocol = protocol;
	protPtr->nextPtr = wmPtr->protPtr;
	wmPtr->protPtr = protPtr;
	protPtr->interp = interp;
	memcpy(protPtr->command, cmd, cmdLength + 1);
    }
    return TCL_OK;
7949
7950
7951
7952
7953
7954
7955












































































7956
7957
7958
7959
7960
7961
7962
	event.xclient.message_type =
	    Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");
	event.xclient.data.l[0] =
	    Tk_InternAtom((Tk_Window) winPtr, "WM_SAVE_YOURSELF");
	TkWmProtocolEventProc(winPtr, &event);
	break;
    }













































































    default:
	break;
    }

    winPtr = GetTopLevel(hwnd);
    switch(message) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
	event.xclient.message_type =
	    Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");
	event.xclient.data.l[0] =
	    Tk_InternAtom((Tk_Window) winPtr, "WM_SAVE_YOURSELF");
	TkWmProtocolEventProc(winPtr, &event);
	break;
    }

    case WM_WTSSESSION_CHANGE: {
	DWORD SessionID;
	XEvent event;

	/*
	 * Check, if it is my session.
	 * Normally, we get only notifications about our session.
	 * But, if WTSRegisterSessionNotification is called somewhere else
	 * with all sessions, filtering may be helpful.
	 */

	if ( 0 == ProcessIdToSessionId(GetCurrentProcessId(),&SessionID)
		|| SessionID != lParam) {
	    break;
	}

	/*
	 * Filter the notification items we take.
	 * Note, that the following notifications are not reported:
	 * WTS_SESSION_REMOTE_CONTROL, WTS_SESSION_CREATE,
	 * WTS_SESSION_TERMINATE.
	 */

	switch (wParam) {
	case WTS_CONSOLE_CONNECT:
	case WTS_CONSOLE_DISCONNECT:
	case WTS_REMOTE_CONNECT:
	case WTS_REMOTE_DISCONNECT:
	case WTS_SESSION_LOGON:
	case WTS_SESSION_LOGOFF:
	case WTS_SESSION_LOCK:
	case WTS_SESSION_UNLOCK:

	    winPtr = GetTopLevel(hwnd);
	    event.xclient.message_type =
		Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");

	    switch (wParam) {
	    case WTS_CONSOLE_CONNECT:
		event.xclient.data.l[0] =
		    Tk_InternAtom((Tk_Window) winPtr, "WTS_CONSOLE_CONNECT");
		break;
	    case WTS_CONSOLE_DISCONNECT:
		event.xclient.data.l[0] =
		    Tk_InternAtom((Tk_Window) winPtr, "WTS_CONSOLE_DISCONNECT");
		break;
	    case WTS_REMOTE_CONNECT:
		event.xclient.data.l[0] =
		    Tk_InternAtom((Tk_Window) winPtr, "WTS_REMOTE_CONNECT");
		break;
	    case WTS_REMOTE_DISCONNECT:
		event.xclient.data.l[0] =
		    Tk_InternAtom((Tk_Window) winPtr, "WTS_REMOTE_DISCONNECT");
		break;
	    case WTS_SESSION_LOGON:
		event.xclient.data.l[0] =
		    Tk_InternAtom((Tk_Window) winPtr, "WTS_SESSION_LOGON");
		break;
	    case WTS_SESSION_LOGOFF:
		event.xclient.data.l[0] =
		    Tk_InternAtom((Tk_Window) winPtr, "WTS_SESSION_LOGOFF");
		break;
	    case WTS_SESSION_LOCK:
		event.xclient.data.l[0] =
		    Tk_InternAtom((Tk_Window) winPtr, "WTS_SESSION_LOCK");
		break;
	    case WTS_SESSION_UNLOCK:
		event.xclient.data.l[0] =
		    Tk_InternAtom((Tk_Window) winPtr, "WTS_SESSION_UNLOCK");
	        break;
	    }
	    TkWmProtocolEventProc(winPtr, &event);
	    break;
	}
    }

    default:
	break;
    }

    winPtr = GetTopLevel(hwnd);
    switch(message) {