* Sync the recent cmake branch changes.
[reactos.git] / dll / win32 / user32 / controls / appswitch.c
1
2 /*
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: dll/win32/user32/controls/appswitch.c
6 * PURPOSE: app switching functionality
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9
10 #include <user32.h>
11
12 #include <wine/debug.h>
13 WINE_DEFAULT_DEBUG_CHANNEL(user32);
14
15 typedef struct APPSWITCH_ITEM
16 {
17 HWND hwndDlg;
18 DWORD zPos;
19 HICON hIcon;
20 BOOL bFocus;
21 struct APPSWITCH_ITEM * Next;
22 WCHAR szText[1];
23 } APPSWITCH_ITEM, *PAPPSWITCH_ITEM;
24
25 static PAPPSWITCH_ITEM pRoot = NULL;
26 static DWORD NumOfWindows = 0;
27 static HWND hAppWindowDlg = NULL;
28 static HHOOK hhk = NULL;
29
30 UINT WINAPI PrivateExtractIconExW(LPCWSTR,int,HICON*,HICON*,UINT);
31
32
33 BOOL
34 CALLBACK
35 EnumWindowEnumProc(
36 HWND hwnd,
37 LPARAM lParam
38 )
39 {
40 PAPPSWITCH_ITEM pItem;
41 UINT Length;
42 HICON hIcon;
43 PAPPSWITCH_ITEM pCurItem;
44 DWORD dwPid;
45 HANDLE hProcess;
46 WCHAR szFileName[MAX_PATH] = {0};
47
48 /* check if the enumerated window is visible */
49 if (!IsWindowVisible(hwnd))
50 return TRUE;
51 /* get window icon */
52 hIcon = (HICON)SendMessage(hwnd, WM_GETICON, ICON_BIG, 0);
53 if (!hIcon)
54 {
55 GetWindowThreadProcessId(hwnd, &dwPid);
56 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, dwPid);
57 if (hProcess)
58 {
59 // if (GetModuleFileNameExW(hProcess, NULL, szFileName, MAX_PATH))
60 {
61 szFileName[MAX_PATH-1] = L'\0';
62 PrivateExtractIconExW(szFileName, 0, &hIcon, NULL, 1);
63 }
64 }
65 }
66 else
67 {
68 /* icons from WM_GETICON need to be copied */
69 hIcon = CopyIcon(hIcon);
70 }
71 /* get the text length */
72 Length = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
73 /* allocate item structure for it */
74 // pItem = (PAPPSWITCH_ITEM)HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(APPSWITCH_ITEM) + Length * sizeof(WCHAR));
75 if (!pItem)
76 return TRUE;
77 if (Length)
78 {
79 /* retrieve the window text when available */
80 SendMessageW(hwnd, WM_GETTEXT, Length+1, (LPARAM)pItem->szText);
81 }
82 /* copy the window icon */
83 pItem->hIcon = hIcon;
84 /* store window handle */
85 pItem->hwndDlg = hwnd;
86 /* is the window the active window */
87 if (GetActiveWindow() == hwnd)
88 pItem->bFocus = TRUE;
89
90 if (!pRoot)
91 {
92 /* first item */
93 pRoot = pItem;
94 return TRUE;
95 }
96
97 /* enumerate the last item */
98 pCurItem = pRoot;
99 while(pCurItem->Next)
100 pCurItem = pCurItem->Next;
101
102 /* insert it into the list */
103 pCurItem->Next = pItem;
104 NumOfWindows++;
105 return TRUE;
106 }
107
108 VOID
109 EnumerateAppWindows(HDESK hDesk, HWND hwndDlg)
110 {
111 /* initialize defaults */
112 pRoot = NULL;
113 NumOfWindows = 0;
114 hAppWindowDlg = hwndDlg;
115 /* enumerate all windows */
116 EnumDesktopWindows(hDesk, EnumWindowEnumProc, (LPARAM)NULL);
117 if (NumOfWindows > 7)
118 {
119 /* FIXME resize window */
120 }
121 }
122
123 VOID
124 MarkNextEntryAsActive()
125 {
126 PAPPSWITCH_ITEM pItem;
127
128 pItem = pRoot;
129 if (!pRoot)
130 return;
131
132 while(pItem)
133 {
134 if (pItem->bFocus)
135 {
136 pItem->bFocus = FALSE;
137 if (pItem->Next)
138 pItem->Next->bFocus = TRUE;
139 else
140 pRoot->bFocus = TRUE;
141 }
142 pItem = pItem->Next;
143 }
144
145 InvalidateRgn(hAppWindowDlg, NULL, TRUE);
146 }
147
148
149 LRESULT
150 CALLBACK
151 KeyboardHookProc(
152 int nCode,
153 WPARAM wParam,
154 LPARAM lParam
155 )
156 {
157 PKBDLLHOOKSTRUCT hk = (PKBDLLHOOKSTRUCT) lParam;
158
159 if (wParam == WM_SYSKEYUP)
160 {
161 /* is tab key pressed */
162 if (hk->vkCode == VK_TAB)
163 {
164 if (hAppWindowDlg == NULL)
165 {
166 /* FIXME
167 * launch window
168 */
169 FIXME("launch alt-tab window\n");
170 }
171 else
172 {
173 MarkNextEntryAsActive();
174 }
175 }
176 }
177 return CallNextHookEx(hhk, nCode, wParam, lParam);
178 }
179
180 VOID
181 PaintAppWindows(HWND hwndDlg, HDC hDc)
182 {
183 DWORD dwIndex, X, Y;
184 PAPPSWITCH_ITEM pCurItem;
185 RECT Rect;
186 DWORD XSize, YSize, XMax;
187 HBRUSH hBrush;
188
189 X = 10;
190 Y = 10;
191 XSize = GetSystemMetrics(SM_CXICON);
192 YSize = GetSystemMetrics(SM_CYICON);
193 XMax = (XSize+(XSize/2)) * 7 + X;
194 pCurItem = pRoot;
195
196 for (dwIndex = 0; dwIndex < NumOfWindows; dwIndex++)
197 {
198 if (X >= XMax)
199 {
200 X = 10;
201 Y += YSize + (YSize/2);
202 }
203 if (pCurItem->bFocus)
204 {
205 hBrush = CreateSolidBrush(RGB(30, 30, 255));
206 SetRect(&Rect, X-5, Y-5, X + XSize + 5, Y + YSize + 5);
207 FillRect(hDc, &Rect, hBrush);
208 DeleteObject((HGDIOBJ)hBrush);
209 // SendDlgItemMessageW(hwndDlg, IDC_STATIC_CUR_APP, WM_SETTEXT, 0, (LPARAM)pCurItem->szText);
210 }
211
212 DrawIcon(hDc, X, Y, pCurItem->hIcon);
213 pCurItem = pCurItem->Next;
214 X += XSize +(XSize/2);
215 }
216 }
217 VOID
218 DestroyAppWindows()
219 {
220 PAPPSWITCH_ITEM pCurItem, pNextItem;
221
222 pCurItem = pRoot;
223 while(pCurItem)
224 {
225 pNextItem = pCurItem->Next;
226 DestroyIcon(pCurItem->hIcon);
227 // HeapFree(Win32CsrApiHeap, 0, pCurItem);
228 pCurItem = pNextItem;
229 }
230 pRoot = NULL;
231 hAppWindowDlg = NULL;
232 NumOfWindows = 0;
233 }
234
235 INT_PTR
236 CALLBACK
237 SwitchWindowDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
238 {
239 PAINTSTRUCT Paint;
240 HDESK hInput;
241
242 switch (message)
243 {
244 case WM_INITDIALOG:
245 hInput = OpenInputDesktop(0,0, GENERIC_ALL);
246 if (hInput)
247 {
248 EnumerateAppWindows(hInput, hwndDlg);
249 CloseDesktop(hInput);
250 }
251 return TRUE;
252 case WM_PAINT:
253 BeginPaint(hwndDlg, &Paint);
254 PaintAppWindows(hwndDlg, Paint.hdc);
255 EndPaint(hwndDlg, &Paint);
256 break;
257 case WM_DESTROY:
258 DestroyAppWindows();
259 break;
260 }
261 return FALSE;
262 }
263
264 VOID
265 WINAPI
266 InitializeAppSwitchHook()
267 {
268 hhk = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, NULL, 0);
269 TRACE("InitializeAppSwitchHook hhk %p\n", hhk);
270 }