explorer: Create a standalone tray window wrapper if the driver doesn't provide native implementation. Take 2.

Dmitry Timoshkov dmitry at codeweavers.com
Fri Oct 22 08:14:26 CDT 2010


This patch makes sure that "Shell_TrayWnd" window doesn't have a caption
since some apps depend on it being empty. The bug #20129 lists one of such
applications. It does FindWindow("Shell_TrayWnd", "") and expects that it
returns a valid tray window handle.
---
 dlls/user32/tests/win.c     |    1 -
 programs/explorer/systray.c |   67 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index 80aad49..5a378de 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -6266,7 +6266,6 @@ static void test_FindWindowEx(void)
 
     /* test behaviour with a window title that is an empty character */
     found = FindWindowExA( 0, 0, "Shell_TrayWnd", title );
-todo_wine
     ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
     found = FindWindowExA( 0, 0, "Shell_TrayWnd", NULL );
     ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c
index 615768f..a05250f 100644
--- a/programs/explorer/systray.c
+++ b/programs/explorer/systray.c
@@ -109,7 +109,6 @@ static SIZE get_window_size(void)
     rect.top = 0;
     rect.right = icon_cx * max( nb_displayed, MIN_DISPLAYED );
     rect.bottom = icon_cy;
-    AdjustWindowRect( &rect, WS_CAPTION, FALSE );
     size.cx = rect.right - rect.left;
     size.cy = rect.bottom - rect.top;
     return size;
@@ -204,6 +203,61 @@ static void invalidate_icons( unsigned int start, unsigned int end )
     InvalidateRect( tray_window, &rect, TRUE );
 }
 
+static LRESULT WINAPI tray_wrapper_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+    switch (msg)
+    {
+    case WM_MOVE:
+        SetWindowPos( tray_window, 0, LOWORD(lparam), HIWORD(lparam), 0,0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+        break;
+
+    case WM_CLOSE:
+        /* don't destroy the tray window, just hide it */
+        ShowWindow( hwnd, SW_HIDE );
+        return 0;
+
+    default:
+        break;
+    }
+    return DefWindowProcW( hwnd, msg, wparam, lparam );
+}
+
+static void embed_tray_window( void )
+{
+    static const WCHAR classW[] = {'w','i','n','e',' ','t','r','a','y',' ','w','r','a','p','p','e','r',0};
+    static const WCHAR captionW[] = {'W','i','n','e',' ','S','y','s','t','e','m',' ','T','r','a','y',0};
+    static const LONG style = WS_POPUP | WS_CAPTION | WS_BORDER;
+    static HWND tray_window_wrapper;
+    WNDCLASSEXW class;
+    SIZE sz;
+    RECT rc;
+
+    if (tray_window_wrapper) return;
+
+    memset( &class, 0, sizeof(class) );
+    class.cbSize        = sizeof(class);
+    class.style         = CS_DBLCLKS;
+    class.lpfnWndProc   = tray_wrapper_wndproc;
+    class.hIcon         = LoadIconW( 0, (LPCWSTR)IDI_WINLOGO );
+    class.hCursor       = LoadCursorW( 0, (LPCWSTR)IDC_ARROW );
+    class.hbrBackground = (HBRUSH)COLOR_WINDOW;
+    class.lpszClassName = classW;
+
+    if (!RegisterClassExW( &class )) return;
+
+    sz = get_window_size();
+    SetRect( &rc, 0, 0, sz.cx, sz.cy );
+    AdjustWindowRect( &rc, style, FALSE );
+    tray_window_wrapper = CreateWindowExW( 0, classW, captionW, style,
+                                           CW_USEDEFAULT, CW_USEDEFAULT,
+                                           rc.right - rc.left, rc.bottom - rc.top,
+                                           0, 0, 0, 0 );
+    if (!tray_window_wrapper) return;
+
+    SetWindowLongPtrW( tray_window, GWLP_HWNDPARENT, (LONG_PTR)tray_window_wrapper );
+    ShowWindow( tray_window_wrapper, SW_SHOWNA );
+}
+
 /* make an icon visible */
 static BOOL show_icon(struct icon *icon)
 {
@@ -234,7 +288,11 @@ static BOOL show_icon(struct icon *icon)
     }
     else if (nb_displayed == 1)
     {
-        if (!hide_systray) ShowWindow( tray_window, SW_SHOWNA );
+        if (!hide_systray)
+        {
+            embed_tray_window();
+            ShowWindow( tray_window, SW_SHOWNA );
+        }
     }
 
     create_tooltip(icon);
@@ -562,7 +620,6 @@ void initialize_systray(void)
     SIZE size;
     WNDCLASSEXW class;
     static const WCHAR classname[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0};
-    static const WCHAR winname[] = {'W','i','n','e',' ','S','y','s','t','e','m',' ','T','r','a','y',0};
 
     if ((x11drv = GetModuleHandleA( "winex11.drv" )))
         wine_notify_icon = (void *)GetProcAddress( x11drv, "wine_notify_icon" );
@@ -580,7 +637,7 @@ void initialize_systray(void)
     class.hIcon         = LoadIconW(0, (LPCWSTR)IDI_WINLOGO);
     class.hCursor       = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
     class.hbrBackground = (HBRUSH) COLOR_WINDOW;
-    class.lpszClassName = (WCHAR *) &classname;
+    class.lpszClassName = classname;
 
     if (!RegisterClassExW(&class))
     {
@@ -589,7 +646,7 @@ void initialize_systray(void)
     }
 
     size = get_window_size();
-    tray_window = CreateWindowW( classname, winname, WS_OVERLAPPED | WS_CAPTION,
+    tray_window = CreateWindowW( classname, NULL, WS_POPUP,
                                  CW_USEDEFAULT, CW_USEDEFAULT, size.cx, size.cy, 0, 0, 0, 0 );
     if (!tray_window)
     {
-- 
1.7.0.6




More information about the wine-patches mailing list