Commit 446d8321 authored by Alexandre Julliard's avatar Alexandre Julliard

Store window icons in the window structure so that WM_SETICON can do

the right thing (based on a patch by Aric Stewart).
parent 9741589b
...@@ -845,6 +845,68 @@ static void test_mdi(void) ...@@ -845,6 +845,68 @@ static void test_mdi(void)
*/ */
} }
static void test_icons(void)
{
WNDCLASSEXA cls;
HWND hwnd;
HICON icon = LoadIconA(0, (LPSTR)IDI_APPLICATION);
HICON icon2 = LoadIconA(0, (LPSTR)IDI_QUESTION);
HICON small_icon = LoadImageA(0, (LPSTR)IDI_APPLICATION, IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
HICON res;
cls.cbSize = sizeof(cls);
cls.style = 0;
cls.lpfnWndProc = DefWindowProcA;
cls.cbClsExtra = 0;
cls.cbWndExtra = 0;
cls.hInstance = 0;
cls.hIcon = LoadIconA(0, (LPSTR)IDI_HAND);
cls.hIconSm = small_icon;
cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
cls.lpszMenuName = NULL;
cls.lpszClassName = "IconWindowClass";
RegisterClassExA(&cls);
hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
assert( hwnd );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
ok( res == 0, "wrong big icon %p/0\n", res );
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
ok( res == 0, "wrong previous big icon %p/0\n", res );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == 0, "wrong small icon %p/0\n", res );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
ok( res != 0, "wrong small icon %p\n", res );
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
ok( res == 0, "wrong previous small icon %p/0\n", res );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
/* make sure the big icon hasn't changed */
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
}
START_TEST(win) START_TEST(win)
{ {
pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" ); pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
...@@ -871,6 +933,7 @@ START_TEST(win) ...@@ -871,6 +933,7 @@ START_TEST(win)
test_shell_window(); test_shell_window();
test_mdi(); test_mdi();
test_icons();
UnhookWindowsHookEx(hhook); UnhookWindowsHookEx(hhook);
} }
...@@ -281,10 +281,9 @@ inline static void destroy_icon_window( Display *display, WND *win ) ...@@ -281,10 +281,9 @@ inline static void destroy_icon_window( Display *display, WND *win )
* *
* Set the icon wm hints * Set the icon wm hints
*/ */
static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints ) static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints, HICON hIcon )
{ {
X11DRV_WND_DATA *data = wndPtr->pDriverData; X11DRV_WND_DATA *data = wndPtr->pDriverData;
HICON hIcon = (HICON)GetClassLongA( wndPtr->hwndSelf, GCL_HICON );
if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap ); if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
if (data->hWMIconMask) DeleteObject( data->hWMIconMask); if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
...@@ -473,7 +472,7 @@ void X11DRV_set_wm_hints( Display *display, WND *win ) ...@@ -473,7 +472,7 @@ void X11DRV_set_wm_hints( Display *display, WND *win )
wm_hints->flags = InputHint | StateHint | WindowGroupHint; wm_hints->flags = InputHint | StateHint | WindowGroupHint;
wm_hints->input = !(win->dwStyle & WS_DISABLED); wm_hints->input = !(win->dwStyle & WS_DISABLED);
set_icon_hints( display, win, wm_hints ); set_icon_hints( display, win, wm_hints, (HICON)GetClassLongA( win->hwndSelf, GCL_HICON ));
wm_hints->initial_state = (win->dwStyle & WS_MINIMIZE) ? IconicState : NormalState; wm_hints->initial_state = (win->dwStyle & WS_MINIMIZE) ? IconicState : NormalState;
wm_hints->window_group = group_leader; wm_hints->window_group = group_leader;
...@@ -1312,16 +1311,14 @@ void X11DRV_SetFocus( HWND hwnd ) ...@@ -1312,16 +1311,14 @@ void X11DRV_SetFocus( HWND hwnd )
* This is not entirely correct, may need to create * This is not entirely correct, may need to create
* an icon window and set the pixmap as a background * an icon window and set the pixmap as a background
*/ */
HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small ) void X11DRV_SetWindowIcon( HWND hwnd, UINT type, HICON icon )
{ {
WND *wndPtr; WND *wndPtr;
Display *display = thread_display(); Display *display = thread_display();
HICON old = (HICON)SetClassLongW(hwnd, small ? GCL_HICONSM : GCL_HICON, (LONG)icon );
SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | if (type != ICON_BIG) return; /* nothing to do here */
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return old; if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
if (wndPtr->dwExStyle & WS_EX_MANAGED) if (wndPtr->dwExStyle & WS_EX_MANAGED)
{ {
...@@ -1333,7 +1330,7 @@ HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small ) ...@@ -1333,7 +1330,7 @@ HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
wine_tsx11_unlock(); wine_tsx11_unlock();
if (wm_hints) if (wm_hints)
{ {
set_icon_hints( display, wndPtr, wm_hints ); set_icon_hints( display, wndPtr, wm_hints, icon );
wine_tsx11_lock(); wine_tsx11_lock();
XSetWMHints( display, win, wm_hints ); XSetWMHints( display, win, wm_hints );
XFree( wm_hints ); XFree( wm_hints );
...@@ -1341,5 +1338,4 @@ HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small ) ...@@ -1341,5 +1338,4 @@ HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
} }
} }
WIN_ReleasePtr( wndPtr ); WIN_ReleasePtr( wndPtr );
return old;
} }
...@@ -119,7 +119,7 @@ typedef struct tagUSER_DRIVER { ...@@ -119,7 +119,7 @@ typedef struct tagUSER_DRIVER {
HWND (*pSetParent)(HWND,HWND); HWND (*pSetParent)(HWND,HWND);
BOOL (*pSetWindowPos)(WINDOWPOS *); BOOL (*pSetWindowPos)(WINDOWPOS *);
int (*pSetWindowRgn)(HWND,HRGN,BOOL); int (*pSetWindowRgn)(HWND,HRGN,BOOL);
HICON (*pSetWindowIcon)(HWND,HICON,BOOL); void (*pSetWindowIcon)(HWND,UINT,HICON);
void (*pSetWindowStyle)(HWND,DWORD); void (*pSetWindowStyle)(HWND,DWORD);
BOOL (*pSetWindowText)(HWND,LPCWSTR); BOOL (*pSetWindowText)(HWND,LPCWSTR);
BOOL (*pShowWindow)(HWND,INT); BOOL (*pShowWindow)(HWND,INT);
......
...@@ -61,6 +61,8 @@ typedef struct tagWND ...@@ -61,6 +61,8 @@ typedef struct tagWND
DWORD helpContext; /* Help context ID */ DWORD helpContext; /* Help context ID */
UINT flags; /* Misc. flags (see below) */ UINT flags; /* Misc. flags (see below) */
HMENU hSysMenu; /* window's copy of System Menu */ HMENU hSysMenu; /* window's copy of System Menu */
HICON hIcon; /* window's icon */
HICON hIconSmall; /* window's small icon */
int cbWndExtra; /* class cbWndExtra at window creation */ int cbWndExtra; /* class cbWndExtra at window creation */
int irefCount; /* window's reference count*/ int irefCount; /* window's reference count*/
DWORD userdata; /* User private data */ DWORD userdata; /* User private data */
......
...@@ -653,19 +653,60 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa ...@@ -653,19 +653,60 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
return 1; return 1;
case WM_SETICON: case WM_SETICON:
if (USER_Driver.pSetWindowIcon)
return (LRESULT)USER_Driver.pSetWindowIcon( hwnd, (HICON)lParam, (wParam != ICON_SMALL) );
else
{ {
HICON hOldIcon = (HICON)SetClassLongW( hwnd, (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM, HICON ret;
lParam); WND *wndPtr = WIN_GetPtr( hwnd );
switch(wParam)
{
case ICON_SMALL:
ret = wndPtr->hIconSmall;
wndPtr->hIconSmall = (HICON)lParam;
break;
case ICON_BIG:
ret = wndPtr->hIcon;
wndPtr->hIcon = (HICON)lParam;
break;
default:
ret = 0;
break;
}
WIN_ReleasePtr( wndPtr );
if (USER_Driver.pSetWindowIcon)
USER_Driver.pSetWindowIcon( hwnd, wParam, (HICON)lParam );
SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
return (LRESULT)hOldIcon;
return (LRESULT)ret;
} }
case WM_GETICON: case WM_GETICON:
return GetClassLongW( hwnd, (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM ); {
HICON ret;
WND *wndPtr = WIN_GetPtr( hwnd );
switch(wParam)
{
case ICON_SMALL:
ret = wndPtr->hIconSmall;
break;
case ICON_BIG:
ret = wndPtr->hIcon;
break;
case ICON_SMALL2:
ret = wndPtr->hIconSmall;
if (!ret) ret = (HICON)GetClassLongA( hwnd, GCL_HICONSM );
/* FIXME: should have a default here if class icon is null */
break;
default:
ret = 0;
break;
}
WIN_ReleasePtr( wndPtr );
return (LRESULT)ret;
}
case WM_HELP: case WM_HELP:
SendMessageW( GetParent(hwnd), msg, wParam, lParam ); SendMessageW( GetParent(hwnd), msg, wParam, lParam );
......
...@@ -241,7 +241,16 @@ NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle) ...@@ -241,7 +241,16 @@ NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
static HICON NC_IconForWindow( HWND hwnd ) static HICON NC_IconForWindow( HWND hwnd )
{ {
HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM ); HICON hIcon = 0;
WND *wndPtr = WIN_GetPtr( hwnd );
if (wndPtr && wndPtr != WND_OTHER_PROCESS)
{
hIcon = wndPtr->hIconSmall;
if (!hIcon) hIcon = wndPtr->hIcon;
WIN_ReleasePtr( wndPtr );
}
if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON ); if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
/* If there is no hIcon specified and this is a modal dialog, /* If there is no hIcon specified and this is a modal dialog,
......
...@@ -1071,6 +1071,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, ...@@ -1071,6 +1071,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
wndPtr->pVScroll = NULL; wndPtr->pVScroll = NULL;
wndPtr->pHScroll = NULL; wndPtr->pHScroll = NULL;
wndPtr->userdata = 0; wndPtr->userdata = 0;
wndPtr->hIcon = 0;
wndPtr->hIconSmall = 0;
wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0; wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
/* Correct the window style - stage 2 */ /* Correct the window style - stage 2 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment