1
2
3
4
5
6
7
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
// 6 april 2015
#include "uipriv_windows.hpp"
static HHOOK filter;
static LRESULT CALLBACK filterProc(int code, WPARAM wParam, LPARAM lParam)
{
MSG *msg = (MSG *) lParam;
if (code < 0)
goto callNext;
if (areaFilter(msg)) // don't continue to our IsDialogMessage() hack if the area handled it
goto discard;
// TODO IsDialogMessage() hack here
// otherwise keep going
goto callNext;
discard:
// we handled it; discard the message so the dialog manager doesn't see it
return 1;
callNext:
return CallNextHookEx(filter, code, wParam, lParam);
}
int registerMessageFilter(void)
{
filter = SetWindowsHookExW(WH_MSGFILTER,
filterProc,
hInstance,
GetCurrentThreadId());
return filter != NULL;
}
void unregisterMessageFilter(void)
{
if (UnhookWindowsHookEx(filter) == 0)
logLastError(L"error unregistering libui message filter");
}
// LONGTERM http://blogs.msdn.com/b/oldnewthing/archive/2005/04/08/406509.aspx when adding accelerators, TranslateAccelerators() before IsDialogMessage()
static void processMessage(MSG *msg)
{
HWND correctParent;
if (msg->hwnd != NULL)
correctParent = parentToplevel(msg->hwnd);
else // just to be safe
correctParent = GetActiveWindow();
if (correctParent != NULL)
// this calls our mesage filter above for us
if (IsDialogMessage(correctParent, msg) != 0)
return;
TranslateMessage(msg);
DispatchMessageW(msg);
}
static int waitMessage(MSG *msg)
{
int res;
res = GetMessageW(msg, NULL, 0, 0);
if (res < 0) {
logLastError(L"error calling GetMessage()");
return 0; // bail out on error
}
return res != 0; // returns false on WM_QUIT
}
void uiMain(void)
{
while (uiMainStep(1))
;
}
void uiMainSteps(void)
{
// don't need to do anything here
}
static int peekMessage(MSG *msg)
{
BOOL res;
res = PeekMessageW(msg, NULL, 0, 0, PM_REMOVE);
if (res == 0)
return 2; // no message available
if (msg->message != WM_QUIT)
return 1; // a message
return 0; // WM_QUIT
}
int uiMainStep(int wait)
{
MSG msg;
if (wait) {
if (!waitMessage(&msg))
return 0;
processMessage(&msg);
return 1;
}
// don't wait for a message
switch (peekMessage(&msg)) {
case 0: // quit
// TODO PostQuitMessage() again?
return 0;
case 1: // process a message
processMessage(&msg);
// fall out to the case for no message
}
return 1; // no message
}
void uiQuit(void)
{
PostQuitMessage(0);
}
void uiQueueMain(void (*f)(void *data), void *data)
{
if (PostMessageW(utilWindow, msgQueued, (WPARAM) f, (LPARAM) data) == 0)
// LONGTERM this is likely not safe to call across threads (allocates memory)
logLastError(L"error queueing function to run on main thread");
}
|