update wine to wine-1.1.7
[sugaredwine.git] / patches / 0007-explorer-add-a-window-switcher-tasklist-to-the-ta.patch
blob647592173304ff394258458fb3a9cef3f8e3acef
1 From 487c019e7cb54f2d582960b9d1ddd33d9d13a38e Mon Sep 17 00:00:00 2001
2 From: Vincent Povirk <vincent@codeweavers.com>
3 Date: Mon, 25 Aug 2008 08:39:06 -0500
4 Subject: [PATCH] explorer: add a window switcher (tasklist) to the taskbar
6 ---
7 programs/explorer/Makefile.in | 3 +-
8 programs/explorer/desktop.c | 3 +
9 programs/explorer/explorer_private.h | 7 +-
10 programs/explorer/systray.c | 14 +-
11 programs/explorer/taskbar.c | 17 ++-
12 programs/explorer/tasklist.c | 337 ++++++++++++++++++++++++++++++++++
13 6 files changed, 371 insertions(+), 10 deletions(-)
14 create mode 100644 programs/explorer/tasklist.c
16 diff --git a/programs/explorer/Makefile.in b/programs/explorer/Makefile.in
17 index f2fc10a..99500b9 100644
18 --- a/programs/explorer/Makefile.in
19 +++ b/programs/explorer/Makefile.in
20 @@ -14,7 +14,8 @@ C_SRCS = \
21 explorer.c \
22 startmenu.c \
23 systray.c \
24 - taskbar.c
25 + taskbar.c \
26 + tasklist.c
28 @MAKE_PROG_RULES@
30 diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
31 index ce31a03..43d6f8b 100644
32 --- a/programs/explorer/desktop.c
33 +++ b/programs/explorer/desktop.c
34 @@ -369,6 +369,9 @@ void manage_desktop( WCHAR *arg )
35 while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
36 WINE_TRACE( "desktop message loop exiting for hwnd %p\n", hwnd );
39 + if (using_root)
40 + finalize_taskbar();
42 ExitProcess( 0 );
44 diff --git a/programs/explorer/explorer_private.h b/programs/explorer/explorer_private.h
45 index 22bc009..c6f3b09 100644
46 --- a/programs/explorer/explorer_private.h
47 +++ b/programs/explorer/explorer_private.h
48 @@ -23,9 +23,14 @@
50 extern void manage_desktop( WCHAR *arg );
51 extern HWND initialize_systray(HWND parent);
52 -extern void initialize_taskbar(void);
53 extern void initialize_appbar(void);
55 +extern void initialize_taskbar(void);
56 +extern void finalize_taskbar(void);
58 extern void do_startmenu(HWND hwnd, HWND button);
59 extern LRESULT handle_menu(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
60 +extern HWND initialize_tasklist(HWND parent);
61 +extern void finalize_tasklist(void);
63 #endif /* __WINE_EXPLORER_PRIVATE_H */
64 diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c
65 index e422a86..12582bc 100644
66 --- a/programs/explorer/systray.c
67 +++ b/programs/explorer/systray.c
68 @@ -61,7 +61,7 @@ static BOOL hide_systray;
69 static HWND parent_window;
70 static int icon_cx, icon_cy;
72 -#define MIN_DISPLAYED (parent_window?0:8)
73 +#define MIN_DISPLAYED 8
74 #define ICON_BORDER 2
76 /* Retrieves icon record by owner window and ID */
77 @@ -84,9 +84,13 @@ static SIZE get_window_size(void)
79 rect.left = 0;
80 rect.top = 0;
81 - rect.right = icon_cx * max( nb_displayed, MIN_DISPLAYED );
82 + if (parent_window)
83 + rect.right = icon_cy * nb_displayed;
84 + else
85 + rect.right = icon_cx * max( nb_displayed, MIN_DISPLAYED );
86 rect.bottom = icon_cy;
87 - AdjustWindowRect( &rect, WS_CAPTION, FALSE );
88 + if (!parent_window)
89 + AdjustWindowRect( &rect, WS_CAPTION, FALSE );
90 size.cx = rect.right - rect.left;
91 size.cy = rect.bottom - rect.top;
92 return size;
93 @@ -204,7 +208,7 @@ static BOOL show_icon(struct icon *icon)
94 update_tooltip_position( icon );
95 invalidate_icons( nb_displayed-1, nb_displayed-1 );
97 - if (nb_displayed > MIN_DISPLAYED)
98 + if (parent_window || nb_displayed > MIN_DISPLAYED)
100 SIZE size = get_window_size();
101 SetWindowPos( tray_window, 0, 0, 0, size.cx, size.cy, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
102 @@ -238,7 +242,7 @@ static BOOL hide_icon(struct icon *icon)
103 invalidate_icons( icon->display, nb_displayed );
104 icon->display = -1;
106 - if (nb_displayed >= MIN_DISPLAYED)
107 + if (parent_window || nb_displayed >= MIN_DISPLAYED)
109 SIZE size = get_window_size();
110 SetWindowPos( tray_window, 0, 0, 0, size.cx, size.cy, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
111 diff --git a/programs/explorer/taskbar.c b/programs/explorer/taskbar.c
112 index aa443d6..0a7becf 100644
113 --- a/programs/explorer/taskbar.c
114 +++ b/programs/explorer/taskbar.c
115 @@ -30,6 +30,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(explorer);
117 static HWND taskbar_window;
118 static HWND systray_window;
119 +static HWND tasklist_window;
120 static HWND startbutton;
122 static void taskbar_setpos(void)
123 @@ -62,6 +63,8 @@ static void taskbar_setpos(void)
124 GetWindowRect(systray_window, &rc);
126 SetWindowPos(systray_window, HWND_TOP, abd.rc.right - abd.rc.left - (rc.right - rc.left), 1, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
128 + MoveWindow(tasklist_window, 76, 1, abd.rc.right - abd.rc.left - (rc.right - rc.left) - 80, 24, TRUE);
131 static LRESULT WINAPI taskbar_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
132 @@ -196,19 +199,27 @@ void initialize_taskbar(void)
134 systray_window = initialize_systray(taskbar_window);
136 - taskbar_setpos();
138 initcomctl.dwSize = sizeof(initcomctl);
139 initcomctl.dwICC = ICC_STANDARD_CLASSES;
140 InitCommonControlsEx(&initcomctl);
143 /* FIXME: make the caption translateable */
144 startbutton = CreateWindowA( "Button", "Start", WS_CHILD|BS_PUSHBUTTON, 0, 1, 72, 24,
145 taskbar_window, 0, 0, 0);
147 + tasklist_window = initialize_tasklist(taskbar_window);
149 + taskbar_setpos();
151 ShowWindow(systray_window, SW_SHOW);
152 ShowWindow(startbutton, SW_SHOW);
153 ShowWindow(taskbar_window, SW_SHOW);
156 +void finalize_taskbar(void)
158 + finalize_tasklist();
160 + DestroyWindow(taskbar_window);
163 diff --git a/programs/explorer/tasklist.c b/programs/explorer/tasklist.c
164 new file mode 100644
165 index 0000000..11b54ab
166 --- /dev/null
167 +++ b/programs/explorer/tasklist.c
168 @@ -0,0 +1,337 @@
170 + * Copyright (C) 2008 Vincent Povirk for CodeWeavers
172 + * This library is free software; you can redistribute it and/or
173 + * modify it under the terms of the GNU Lesser General Public
174 + * License as published by the Free Software Foundation; either
175 + * version 2.1 of the License, or (at your option) any later version.
177 + * This library is distributed in the hope that it will be useful,
178 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
179 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
180 + * Lesser General Public License for more details.
182 + * You should have received a copy of the GNU Lesser General Public
183 + * License along with this library; if not, write to the Free Software
184 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
185 + */
187 +#define UNICODE
188 +#include <windows.h>
189 +#include <commctrl.h>
190 +#include <wine/debug.h>
192 +WINE_DEFAULT_DEBUG_CHANNEL(explorer);
194 +static HWND tasklist;
196 +static WCHAR classname[] = {'t','a','s','k','l','i','s','t',0};
198 +struct toplevel_window
200 + HWND hwnd;
201 + BOOL still_alive;
202 + HWND button;
203 + LPWSTR caption;
206 +static struct toplevel_window *toplevels=NULL;
207 +static int toplevels_len = 0; /* number of top-level windows in toplevels[] */
208 +static int toplevels_size = 0; /* amount of allocated memory in toplevels[] */
210 +HWND foreground;
212 +#define MAX_BUTTON_WIDTH 150
213 +static int button_width = 0;
215 +/* get the index of a window in the toplevels list; this can change */
216 +static int get_toplevel(HWND hwnd)
218 + int i;
220 + for (i=0; i<toplevels_size; i++)
222 + if (toplevels[i].hwnd == hwnd)
223 + return i;
226 + return -1;
229 +static void refresh_buttons(void)
231 + int i;
232 + RECT rc;
234 + if (toplevels_len == 0)
235 + return;
237 + GetWindowRect(tasklist, &rc);
239 + button_width = min(MAX_BUTTON_WIDTH, (rc.right - rc.left) / toplevels_len);
241 + for (i=0; i<toplevels_len; i++)
243 + SetWindowLongPtrW(toplevels[i].button, GWLP_ID, i);
245 + MoveWindow(toplevels[i].button, button_width*i, 0, button_width, (rc.bottom - rc.top), TRUE);
249 +static void update_window_caption(int index)
251 + int length;
252 + LPWSTR caption;
254 + length = GetWindowTextLengthW(toplevels[index].hwnd);
256 + caption = HeapAlloc(GetProcessHeap(), 0, (length+1)*sizeof(WCHAR));
257 + if (length == 0 || !GetWindowTextW(toplevels[index].hwnd, caption, length+1))
258 + caption[0] = 0;
260 + SetWindowTextW(toplevels[index].button, caption);
263 +/* add a window to the list and return its index */
264 +static int add_hwnd(HWND hwnd)
266 + int result;
267 + static const WCHAR buttonW[] = {'B','u','t','t','o','n',0};
269 + if (toplevels_len == toplevels_size)
271 + toplevels = HeapReAlloc(GetProcessHeap(), 0, toplevels, sizeof(struct toplevel_window)*toplevels_size+10);
272 + if (!toplevels)
273 + WINE_ERR("Out of memory\n");
274 + toplevels_size = HeapSize(GetProcessHeap(), 0, toplevels) / sizeof(struct toplevel_window);
277 + WINE_TRACE("adding %p to task list\n", hwnd);
279 + result = toplevels_len;
280 + toplevels_len++;
281 + toplevels[result].hwnd = hwnd;
283 + toplevels[result].button = CreateWindowW(buttonW, buttonW, WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON|BS_LEFT, 0, 0, 0, 0, tasklist, (HMENU)result, NULL, NULL);
285 + update_window_caption(result);
287 + refresh_buttons();
289 + return result;
292 +/* Called before a window is removed from the list.
293 + *
294 + * If several windows are being removed at once, the structure at *toplevel may
295 + * not be at the given index in toplevels. The index given is where it would be
296 + * just before it is removed if we were removing each item individually.
297 + */
298 +static void removing_window(int index, struct toplevel_window* toplevel)
300 + WINE_TRACE("removing %p from task list\n", toplevel->hwnd);
302 + DestroyWindow(toplevel->button);
304 + HeapFree(GetProcessHeap(), 0, toplevel->caption);
307 +#if 0
308 +static void del_window(int window)
310 + removing_window(window);
312 + toplevels_len--;
314 + if (toplevels_len != window)
315 + MoveMemory(&toplevels[window], &toplevels[window+1], sizeof(struct toplevel_window) * (toplevels_len - window));
317 +#endif
319 +static void cull_windows()
321 + int i, j;
322 + BOOL needs_refresh=FALSE;
324 + j=0;
325 + for (i=0; i<toplevels_len; i++)
327 + if (toplevels[i].still_alive)
329 + if (i != j)
330 + CopyMemory(&toplevels[j], &toplevels[i], sizeof(struct toplevel_window));
332 + j++;
334 + else
336 + removing_window(j, &toplevels[i]);
337 + needs_refresh = TRUE;
341 + toplevels_len = j;
343 + if (needs_refresh)
344 + refresh_buttons();
347 +static void foreground_changed(HWND new_foreground)
349 + int i;
351 + i = get_toplevel(foreground);
352 + if (i != -1)
353 + SendMessageW(toplevels[i].button, BM_SETSTATE, (WPARAM)BST_UNCHECKED, 0);
355 + i = get_toplevel(new_foreground);
356 + if (i != -1)
357 + SendMessageW(toplevels[i].button, BM_SETSTATE, (WPARAM)BST_PUSHED, 0);
359 + foreground = new_foreground;
362 +static BOOL CALLBACK handle_enumwindow(HWND hwnd, LPARAM lparam)
364 + int window;
365 + WINDOWINFO wi;
367 + if (GetWindow(hwnd, GW_OWNER))
368 + return TRUE;
370 + wi.cbSize = sizeof(wi);
371 + if (!GetWindowInfo(hwnd, &wi))
372 + return TRUE;
374 + if (wi.dwExStyle & WS_EX_TOOLWINDOW || !(wi.dwStyle & WS_VISIBLE))
375 + return TRUE;
377 + if ((window = get_toplevel(hwnd)) == -1)
379 + window = add_hwnd(hwnd);
381 + else
383 + update_window_caption(window);
386 + toplevels[window].still_alive = TRUE;
388 + return TRUE;
391 +/* update the window list using a blunt object */
392 +static void do_polling(void)
394 + int i;
395 + HWND new_foreground, parent;
397 + /* mark all top-level windows as dead */
398 + for (i=0; i<toplevels_len; i++)
399 + toplevels[i].still_alive = FALSE;
401 + /* mark the alive ones as still alive, and add any new ones */
402 + EnumWindows(handle_enumwindow, 0);
404 + /* remove dead windows */
405 + cull_windows();
407 + new_foreground = GetForegroundWindow();
408 + while ((parent = GetParent(new_foreground)))
409 + new_foreground = parent;
410 + if (foreground != new_foreground)
411 + foreground_changed(new_foreground);
414 +static void handle_click(int index)
416 + HWND hwnd=toplevels[index].hwnd;
417 + LONG_PTR style = GetWindowLongPtrW(hwnd, GWL_STYLE);
419 + if (hwnd == foreground && !(style & WS_MINIMIZE))
421 + ShowWindow(hwnd, SW_SHOWMINNOACTIVE); /* MSDN suggests that SW_FORCEMINIMIZE is
422 + more appropriate, but it seems to make them vanish on Windows.. */
423 + foreground_changed(0);
425 + else
427 + SetForegroundWindow(hwnd);
428 + if (style & WS_MAXIMIZE)
429 + ShowWindow(hwnd, SW_SHOWMAXIMIZED);
430 + else
431 + ShowWindow(hwnd, SW_SHOWNORMAL);
432 + foreground_changed(hwnd);
436 +static LRESULT WINAPI tasklist_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
438 + switch (msg)
440 + case WM_TIMER:
441 + do_polling();
442 + return 0;
443 + case WM_SIZE:
444 + refresh_buttons();
445 + return 0;
446 + case WM_COMMAND:
447 + switch (HIWORD(wparam))
449 + case BN_CLICKED:
450 + handle_click(LOWORD(wparam));
451 + break;
453 + break;
456 + return DefWindowProcW(hwnd, msg, wparam, lparam);
459 +HWND initialize_tasklist(HWND parent)
461 + WNDCLASSEXW class;
463 + ZeroMemory(&class, sizeof(class));
464 + class.cbSize = sizeof(class);
465 + class.style = CS_DBLCLKS;
466 + class.lpfnWndProc = tasklist_wndproc;
467 + class.hInstance = NULL;
468 + class.hIcon = LoadIconW(0, (LPCWSTR)IDI_WINLOGO);
469 + class.hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
470 + class.hbrBackground = (HBRUSH) COLOR_WINDOW;
471 + class.lpszClassName = (WCHAR *) &classname;
473 + if (!RegisterClassExW(&class))
475 + WINE_ERR("Couldn't register tasklist class\n");
476 + return NULL;
479 + tasklist = CreateWindowExW(0, classname, classname, WS_CHILD|WS_VISIBLE, 73, 1, 100, 24, parent, NULL, NULL, NULL);
480 + if (!tasklist)
482 + WINE_ERR("Couldn't create tasklist window\n");
483 + return NULL;
486 + toplevels = HeapAlloc(GetProcessHeap(), 0, sizeof(struct toplevel_window)*10);
487 + if (!toplevels)
489 + WINE_ERR("Out of memory\n");
490 + return NULL;
492 + toplevels_size = HeapSize(GetProcessHeap(), 0, toplevels) / sizeof(struct toplevel_window);
494 + SetTimer(tasklist, 0, 1500, NULL);
496 + return tasklist;
499 +void finalize_tasklist(void)
501 + DestroyWindow(tasklist);
503 + HeapFree(GetProcessHeap(), 0, toplevels);
507 1.5.6.5