winmsgwindow.c revision 35c4bbdf
1848b8605Smrg/*
2848b8605Smrg * Copyright (C) Jon TURNEY 2011
3848b8605Smrg *
4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5848b8605Smrg * copy of this software and associated documentation files (the "Software"),
6848b8605Smrg * to deal in the Software without restriction, including without limitation
7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
9848b8605Smrg * Software is furnished to do so, subject to the following conditions:
10848b8605Smrg *
11848b8605Smrg * The above copyright notice and this permission notice (including the next
12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the
13848b8605Smrg * Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21848b8605Smrg * DEALINGS IN THE SOFTWARE.
22848b8605Smrg *
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg#ifdef HAVE_XWIN_CONFIG_H
26848b8605Smrg#include <xwin-config.h>
27848b8605Smrg#endif
28848b8605Smrg
29848b8605Smrg#include "win.h"
30848b8605Smrg
31b8e80941Smrg/*
32848b8605Smrg * This is the messaging window, a hidden top-level window. We never do anything
33848b8605Smrg * with it, but other programs may send messages to it.
34b8e80941Smrg */
35848b8605Smrg
36848b8605Smrg/*
37848b8605Smrg * winMsgWindowProc - Window procedure for msg window
38848b8605Smrg */
39848b8605Smrg
40848b8605Smrgstatic
41848b8605SmrgLRESULT CALLBACK
42848b8605SmrgwinMsgWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
43b8e80941Smrg{
44848b8605Smrg#if CYGDEBUG
45b8e80941Smrg    winDebugWin32Message("winMsgWindowProc", hwnd, message, wParam, lParam);
46b8e80941Smrg#endif
47b8e80941Smrg
48b8e80941Smrg    switch (message) {
49b8e80941Smrg    case WM_ENDSESSION:
50b8e80941Smrg        if (!wParam)
51848b8605Smrg            return 0;           /* shutdown is being cancelled */
52b8e80941Smrg
53848b8605Smrg        /*
54848b8605Smrg           Send a WM_GIVEUP message to the X server thread so it wakes up if
55848b8605Smrg           blocked in select(), performs GiveUp(), and then notices that GiveUp()
56848b8605Smrg           has set the DE_TERMINATE flag so exits the msg dispatch loop.
57848b8605Smrg         */
58848b8605Smrg        {
59848b8605Smrg            ScreenPtr pScreen = screenInfo.screens[0];
60848b8605Smrg
61848b8605Smrg            winScreenPriv(pScreen);
62848b8605Smrg            PostMessage(pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
63b8e80941Smrg        }
64848b8605Smrg
65b8e80941Smrg        /*
66b8e80941Smrg           This process will be terminated by the system almost immediately
67b8e80941Smrg           after the last thread with a message queue returns from processing
68b8e80941Smrg           WM_ENDSESSION, so we cannot rely on any code executing after this
69b8e80941Smrg           message is processed and need to wait here until ddxGiveUp() is called
70848b8605Smrg           and releases the termination mutex to guarantee that the lock file and
71848b8605Smrg           unix domain sockets have been removed
72b8e80941Smrg
73848b8605Smrg           ofc, Microsoft doesn't document this under WM_ENDSESSION, you are supposed
74b8e80941Smrg           to read the source of CRSS to find out how it works :-)
75b8e80941Smrg
76848b8605Smrg           http://blogs.msdn.com/b/michen/archive/2008/04/04/application-termination-when-user-logs-off.aspx
77b8e80941Smrg         */
78b8e80941Smrg        {
79848b8605Smrg            int iReturn = pthread_mutex_lock(&g_pmTerminating);
80b8e80941Smrg
81b8e80941Smrg            if (iReturn != 0) {
82b8e80941Smrg                ErrorF("winMsgWindowProc - pthread_mutex_lock () failed: %d\n",
83b8e80941Smrg                       iReturn);
84b8e80941Smrg            }
85b8e80941Smrg            winDebug
86b8e80941Smrg                ("winMsgWindowProc - WM_ENDSESSION termination lock acquired\n");
87848b8605Smrg        }
88b8e80941Smrg
89b8e80941Smrg        return 0;
90b8e80941Smrg    }
91b8e80941Smrg
92848b8605Smrg    return DefWindowProc(hwnd, message, wParam, lParam);
93b8e80941Smrg}
94848b8605Smrg
95848b8605Smrgstatic HWND
96b8e80941SmrgwinCreateMsgWindow(void)
97848b8605Smrg{
98848b8605Smrg    HWND hwndMsg;
99848b8605Smrg
100848b8605Smrg    // register window class
101848b8605Smrg    {
102848b8605Smrg        WNDCLASSEX wcx;
103848b8605Smrg
104848b8605Smrg        wcx.cbSize = sizeof(WNDCLASSEX);
105b8e80941Smrg        wcx.style = CS_HREDRAW | CS_VREDRAW;
106848b8605Smrg        wcx.lpfnWndProc = winMsgWindowProc;
107b8e80941Smrg        wcx.cbClsExtra = 0;
108b8e80941Smrg        wcx.cbWndExtra = 0;
109b8e80941Smrg        wcx.hInstance = g_hInstance;
110b8e80941Smrg        wcx.hIcon = NULL;
111b8e80941Smrg        wcx.hCursor = 0;
112b8e80941Smrg        wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
113b8e80941Smrg        wcx.lpszMenuName = NULL;
114b8e80941Smrg        wcx.lpszClassName = WINDOW_CLASS_X_MSG;
115b8e80941Smrg        wcx.hIconSm = NULL;
116b8e80941Smrg        RegisterClassEx(&wcx);
117b8e80941Smrg    }
118b8e80941Smrg
119b8e80941Smrg    // Create the msg window.
120b8e80941Smrg    hwndMsg = CreateWindowEx(0, // no extended styles
121b8e80941Smrg                             WINDOW_CLASS_X_MSG,        // class name
122b8e80941Smrg                             "XWin Msg Window", // window name
123b8e80941Smrg                             WS_OVERLAPPEDWINDOW,       // overlapped window
124b8e80941Smrg                             CW_USEDEFAULT,     // default horizontal position
125b8e80941Smrg                             CW_USEDEFAULT,     // default vertical position
126b8e80941Smrg                             CW_USEDEFAULT,     // default width
127b8e80941Smrg                             CW_USEDEFAULT,     // default height
128b8e80941Smrg                             (HWND) NULL,       // no parent or owner window
129b8e80941Smrg                             (HMENU) NULL,      // class menu used
130b8e80941Smrg                             GetModuleHandle(NULL),     // instance handle
131848b8605Smrg                             NULL);     // no window creation data
132b8e80941Smrg
133b8e80941Smrg    if (!hwndMsg) {
134b8e80941Smrg        ErrorF("winCreateMsgWindow - Create msg window failed\n");
135b8e80941Smrg        return NULL;
136b8e80941Smrg    }
137b8e80941Smrg
138b8e80941Smrg    winDebug("winCreateMsgWindow - Created msg window hwnd 0x%p\n", hwndMsg);
139b8e80941Smrg
140b8e80941Smrg    return hwndMsg;
141b8e80941Smrg}
142b8e80941Smrg
143b8e80941Smrgstatic void *
144b8e80941SmrgwinMsgWindowThreadProc(void *arg)
145b8e80941Smrg{
146b8e80941Smrg    HWND hwndMsg;
147b8e80941Smrg
148b8e80941Smrg    winDebug("winMsgWindowThreadProc - Hello\n");
149b8e80941Smrg
150b8e80941Smrg    hwndMsg = winCreateMsgWindow();
151b8e80941Smrg    if (hwndMsg) {
152848b8605Smrg        MSG msg;
153848b8605Smrg
154b8e80941Smrg        /* Pump the msg window message queue */
155b8e80941Smrg        while (GetMessage(&msg, hwndMsg, 0, 0) > 0) {
156b8e80941Smrg#if CYGDEBUG
157b8e80941Smrg            winDebugWin32Message("winMsgWindowThread", msg.hwnd, msg.message,
158b8e80941Smrg                                 msg.wParam, msg.lParam);
159b8e80941Smrg#endif
160b8e80941Smrg            DispatchMessage(&msg);
161b8e80941Smrg        }
162848b8605Smrg    }
163848b8605Smrg
164848b8605Smrg    winDebug("winMsgWindowThreadProc - Exit\n");
165848b8605Smrg
166848b8605Smrg    return NULL;
167848b8605Smrg}
168848b8605Smrg
169848b8605SmrgBool
170848b8605SmrgwinCreateMsgWindowThread(void)
171848b8605Smrg{
172848b8605Smrg    pthread_t ptMsgWindowThreadProc;
173848b8605Smrg
174848b8605Smrg    /* Spawn a thread for the msg window  */
175848b8605Smrg    if (pthread_create(&ptMsgWindowThreadProc,
176848b8605Smrg                       NULL, winMsgWindowThreadProc, NULL)) {
177b8e80941Smrg        /* Bail if thread creation failed */
178848b8605Smrg        ErrorF("winCreateMsgWindow - pthread_create failed.\n");
179848b8605Smrg        return FALSE;
180848b8605Smrg    }
181848b8605Smrg
182848b8605Smrg    return TRUE;
183848b8605Smrg}
184848b8605Smrg