Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright (C) Jon TURNEY 2011 | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice (including the next | |
12 | * paragraph) shall be included in all copies or substantial portions of the | |
13 | * Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | #include "win.h" | |
26 | ||
27 | /* | |
28 | * This is the messaging window, a hidden top-level window. We never do anything | |
29 | * with it, but other programs may send messages to it. | |
30 | */ | |
31 | ||
32 | /* | |
33 | * winMsgWindowProc - Window procedure for msg window | |
34 | */ | |
35 | ||
36 | static | |
37 | LRESULT CALLBACK | |
38 | winMsgWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) | |
39 | { | |
40 | #if CYGDEBUG | |
41 | winDebugWin32Message("winMsgWindowProc", hwnd, message, wParam, lParam); | |
42 | #endif | |
43 | ||
44 | switch (message) { | |
45 | case WM_ENDSESSION: | |
46 | if (!wParam) | |
47 | return 0; /* shutdown is being cancelled */ | |
48 | ||
49 | /* | |
50 | Send a WM_GIVEUP message to the X server thread so it wakes up if | |
51 | blocked in select(), performs GiveUp(), and then notices that GiveUp() | |
52 | has set the DE_TERMINATE flag so exits the msg dispatch loop. | |
53 | */ | |
54 | { | |
55 | ScreenPtr pScreen = screenInfo.screens[0]; | |
56 | ||
57 | winScreenPriv(pScreen); | |
58 | PostMessage(pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0); | |
59 | } | |
60 | ||
61 | /* | |
62 | This process will be terminated by the system almost immediately | |
63 | after the last thread with a message queue returns from processing | |
64 | WM_ENDSESSION, so we cannot rely on any code executing after this | |
65 | message is processed and need to wait here until ddxGiveUp() is called | |
66 | and releases the termination mutex to guarantee that the lock file and | |
67 | unix domain sockets have been removed | |
68 | ||
69 | ofc, Microsoft doesn't document this under WM_ENDSESSION, you are supposed | |
70 | to read the source of CRSS to find out how it works :-) | |
71 | ||
72 | http://blogs.msdn.com/b/michen/archive/2008/04/04/application-termination-when-user-logs-off.aspx | |
73 | */ | |
74 | { | |
75 | int iReturn = pthread_mutex_lock(&g_pmTerminating); | |
76 | ||
77 | if (iReturn != 0) { | |
78 | ErrorF("winMsgWindowProc - pthread_mutex_lock () failed: %d\n", | |
79 | iReturn); | |
80 | } | |
81 | winDebug | |
82 | ("winMsgWindowProc - WM_ENDSESSION termination lock acquired\n"); | |
83 | } | |
84 | ||
85 | return 0; | |
86 | } | |
87 | ||
88 | return DefWindowProc(hwnd, message, wParam, lParam); | |
89 | } | |
90 | ||
91 | static HWND | |
92 | winCreateMsgWindow(void) | |
93 | { | |
94 | HWND hwndMsg; | |
95 | wATOM winClass; | |
96 | ||
97 | // register window class | |
98 | { | |
99 | WNDCLASSEX wcx; | |
100 | ||
101 | wcx.cbSize = sizeof(WNDCLASSEX); | |
102 | wcx.style = CS_HREDRAW | CS_VREDRAW; | |
103 | wcx.lpfnWndProc = winMsgWindowProc; | |
104 | wcx.cbClsExtra = 0; | |
105 | wcx.cbWndExtra = 0; | |
106 | wcx.hInstance = g_hInstance; | |
107 | wcx.hIcon = NULL; | |
108 | wcx.hCursor = 0; | |
109 | wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); | |
110 | wcx.lpszMenuName = NULL; | |
111 | wcx.lpszClassName = WINDOW_CLASS_X_MSG; | |
112 | wcx.hIconSm = NULL; | |
113 | winClass = RegisterClassEx(&wcx); | |
114 | } | |
115 | ||
116 | // Create the msg window. | |
117 | hwndMsg = CreateWindowEx(0, // no extended styles | |
118 | WINDOW_CLASS_X_MSG, // class name | |
119 | "XWin Msg Window", // window name | |
120 | WS_OVERLAPPEDWINDOW, // overlapped window | |
121 | CW_USEDEFAULT, // default horizontal position | |
122 | CW_USEDEFAULT, // default vertical position | |
123 | CW_USEDEFAULT, // default width | |
124 | CW_USEDEFAULT, // default height | |
125 | (HWND) NULL, // no parent or owner window | |
126 | (HMENU) NULL, // class menu used | |
127 | GetModuleHandle(NULL), // instance handle | |
128 | NULL); // no window creation data | |
129 | ||
130 | if (!hwndMsg) { | |
131 | ErrorF("winCreateMsgWindow - Create msg window failed\n"); | |
132 | return NULL; | |
133 | } | |
134 | ||
135 | winDebug("winCreateMsgWindow - Created msg window hwnd 0x%x\n", hwndMsg); | |
136 | ||
137 | return hwndMsg; | |
138 | } | |
139 | ||
140 | static void * | |
141 | winMsgWindowThreadProc(void *arg) | |
142 | { | |
143 | HWND hwndMsg; | |
144 | ||
145 | winDebug("winMsgWindowThreadProc - Hello\n"); | |
146 | ||
147 | hwndMsg = winCreateMsgWindow(); | |
148 | if (hwndMsg) { | |
149 | MSG msg; | |
150 | ||
151 | /* Pump the msg window message queue */ | |
152 | while (GetMessage(&msg, hwndMsg, 0, 0) > 0) { | |
153 | #if CYGDEBUG | |
154 | winDebugWin32Message("winMsgWindowThread", msg.hwnd, msg.message, | |
155 | msg.wParam, msg.lParam); | |
156 | #endif | |
157 | DispatchMessage(&msg); | |
158 | } | |
159 | } | |
160 | ||
161 | winDebug("winMsgWindowThreadProc - Exit\n"); | |
162 | ||
163 | return NULL; | |
164 | } | |
165 | ||
166 | Bool | |
167 | winCreateMsgWindowThread(void) | |
168 | { | |
169 | pthread_t ptMsgWindowThreadProc; | |
170 | ||
171 | /* Spawn a thread for the msg window */ | |
172 | if (pthread_create(&ptMsgWindowThreadProc, | |
173 | NULL, winMsgWindowThreadProc, NULL)) { | |
174 | /* Bail if thread creation failed */ | |
175 | ErrorF("winCreateMsgWindow - pthread_create failed.\n"); | |
176 | return FALSE; | |
177 | } | |
178 | ||
179 | return TRUE; | |
180 | } |