Changelog: * Implement SetShellWindow(), SetShellWindowEx() and GetShellWindow() to make taskbar of explorer work in desktop mode -- Martin Fuchs martin-fuchs@gmx.net
Index: dlls/user/focus.c =================================================================== RCS file: /home/wine/wine/dlls/user/focus.c,v retrieving revision 1.5 diff -u -r1.5 focus.c --- dlls/user/focus.c 5 Sep 2003 23:08:29 -0000 1.5 +++ dlls/user/focus.c 28 Sep 2003 09:08:47 -0000 @@ -84,6 +84,12 @@ return TRUE; } + if (hwnd == GetShellWindow()) + { + TRACE("set_active_window(%#x): ignored for shell window\n", hwnd); + return TRUE; + } + /* call CBT hook chain */ cbt.fMouse = mouse; cbt.hWndActive = previous; @@ -344,3 +350,65 @@ SERVER_END_REQ; return ret; } + + +/*********************************************************************** +* SetShellWindowEx (USER32.@) +* hwndShell = Progman[Program Manager] +* |-> SHELLDLL_DefView +* hwndListView = | |-> SysListView32 +* | | |-> tooltips_class32 +* | | +* | |-> SysHeader32 +* | +* |-> ProxyTarget +*/ +BOOL WINAPI SetShellWindowEx(HWND hwndShell, HWND hwndListView) +{ + BOOL ret; + + SERVER_START_REQ(set_shell_windows) + { + req->shell_window = hwndShell; + req->shell_listview = hwndListView; + + ret = !wine_server_call_err(req); + } + SERVER_END_REQ; + + if (ret) + { + if (hwndListView && hwndListView!=hwndShell) + SetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + + SetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + } + + return ret; +} + +/******************************************************************* +* SetShellWindow (USER32.@) +*/ +BOOL WINAPI SetShellWindow(HWND hwndShell) +{ + return SetShellWindowEx(hwndShell, hwndShell); +} + +/******************************************************************* +* GetShellWindow (USER32.@) +*/ +HWND WINAPI GetShellWindow() +{ + HWND hwndShell = 0; + + SERVER_START_REQ(get_shell_windows) + { + if (!wine_server_call_err(req)) + hwndShell = reply->shell_window; + } + SERVER_END_REQ; + + return hwndShell; +} + Index: include/wine/server_protocol.h =================================================================== RCS file: /home/wine/wine/include/wine/server_protocol.h,v retrieving revision 1.83 diff -u -r1.83 server_protocol.h --- include/wine/server_protocol.h 16 Sep 2003 01:07:22 -0000 1.83 +++ include/wine/server_protocol.h 28 Sep 2003 09:08:49 -0000 @@ -3115,6 +3115,32 @@ #define OPEN_TOKEN_AS_SELF 2 + +struct set_shell_windows_request +{ + struct request_header __header; + user_handle_t shell_window; + user_handle_t shell_listview; +}; +struct set_shell_windows_reply +{ + struct reply_header __header; +}; + + +struct get_shell_windows_request +{ + struct request_header __header; +}; +struct get_shell_windows_reply +{ + struct reply_header __header; + user_handle_t shell_window; + user_handle_t shell_listview; +}; + + + enum request { REQ_new_process, @@ -3295,6 +3321,8 @@ REQ_get_next_hook, REQ_set_clipboard_info, REQ_open_token, + REQ_set_shell_windows, + REQ_get_shell_windows, REQ_NB_REQUESTS }; @@ -3480,6 +3508,8 @@ struct get_next_hook_request get_next_hook_request; struct set_clipboard_info_request set_clipboard_info_request; struct open_token_request open_token_request; + struct set_shell_windows_request set_shell_windows_request; + struct get_shell_windows_request get_shell_windows_request; }; union generic_reply { @@ -3663,6 +3693,8 @@ struct get_next_hook_reply get_next_hook_reply; struct set_clipboard_info_reply set_clipboard_info_reply; struct open_token_reply open_token_reply; + struct set_shell_windows_reply set_shell_windows_reply; + struct get_shell_windows_reply get_shell_windows_reply; }; #define SERVER_PROTOCOL_VERSION 121 Index: server/protocol.def =================================================================== RCS file: /home/wine/wine/server/protocol.def,v retrieving revision 1.82 diff -u -r1.82 protocol.def --- server/protocol.def 16 Sep 2003 01:07:21 -0000 1.82 +++ server/protocol.def 28 Sep 2003 09:08:52 -0000 @@ -2182,3 +2182,18 @@ @END #define OPEN_TOKEN_THREAD 1 #define OPEN_TOKEN_AS_SELF 2 + + +/* Set the shell windows */ +@REQ(set_shell_windows) + user_handle_t shell_window; /* handle to the new shell window */ + user_handle_t shell_listview; /* handle to the new shell listview window */ +@END + +/* Get the shell windows */ +@REQ(get_shell_windows) +@REPLY + user_handle_t shell_window; /* handle to the shell window */ + user_handle_t shell_listview; /* handle to the shell listview window */ +@END + Index: server/request.h =================================================================== RCS file: /home/wine/wine/server/request.h,v retrieving revision 1.88 diff -u -r1.88 request.h --- server/request.h 19 Aug 2003 03:08:17 -0000 1.88 +++ server/request.h 28 Sep 2003 09:08:53 -0000 @@ -281,6 +281,8 @@ DECL_HANDLER(get_next_hook); DECL_HANDLER(set_clipboard_info); DECL_HANDLER(open_token); +DECL_HANDLER(set_shell_windows); +DECL_HANDLER(get_shell_windows); #ifdef WANT_REQUEST_HANDLERS @@ -465,6 +467,8 @@ (req_handler)req_get_next_hook, (req_handler)req_set_clipboard_info, (req_handler)req_open_token, + (req_handler)req_set_shell_windows, + (req_handler)req_get_shell_windows, }; #endif /* WANT_REQUEST_HANDLERS */ Index: server/trace.c =================================================================== RCS file: /home/wine/wine/server/trace.c,v retrieving revision 1.179 diff -u -r1.179 trace.c --- server/trace.c 16 Sep 2003 01:07:21 -0000 1.179 +++ server/trace.c 28 Sep 2003 09:08:54 -0000 @@ -2504,6 +2504,22 @@ fprintf( stderr, " token=%p", req->token ); } +static void dump_set_shell_windows_request( const struct set_shell_windows_request *req ) +{ + fprintf( stderr, " shell_window=%p,", req->shell_window ); + fprintf( stderr, " shell_listview=%p", req->shell_listview ); +} + +static void dump_get_shell_windows_request( const struct get_shell_windows_request *req ) +{ +} + +static void dump_get_shell_windows_reply( const struct get_shell_windows_reply *req ) +{ + fprintf( stderr, " shell_window=%p,", req->shell_window ); + fprintf( stderr, " shell_listview=%p", req->shell_listview ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_get_new_process_info_request, @@ -2683,6 +2699,8 @@ (dump_func)dump_get_next_hook_request, (dump_func)dump_set_clipboard_info_request, (dump_func)dump_open_token_request, + (dump_func)dump_set_shell_windows_request, + (dump_func)dump_get_shell_windows_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -2864,6 +2882,8 @@ (dump_func)dump_get_next_hook_reply, (dump_func)dump_set_clipboard_info_reply, (dump_func)dump_open_token_reply, + (dump_func)0, + (dump_func)dump_get_shell_windows_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -3045,6 +3065,8 @@ "get_next_hook", "set_clipboard_info", "open_token", + "set_shell_windows", + "get_shell_windows", }; /* ### make_requests end ### */ Index: server/window.c =================================================================== RCS file: /home/wine/wine/server/window.c,v retrieving revision 1.23 diff -u -r1.23 window.c --- server/window.c 5 Sep 2003 23:15:41 -0000 1.23 +++ server/window.c 28 Sep 2003 09:08:55 -0000 @@ -82,6 +82,15 @@ static struct window *top_window; /* top-level (desktop) window */ +/* globally stored shell window pointers */ + +static struct window* shell_window = 0; +static struct window* shell_listview = 0; + +/* process, which currently owns the shell window */ +static struct process* shell_window_owner = 0; + + /* retrieve a pointer to a window from its handle */ inline static struct window *get_window( user_handle_t handle ) { @@ -245,6 +254,23 @@ if (win->paint_count) inc_queue_paint_count( win->thread, -win->paint_count ); queue_cleanup_window( win->thread, win->handle ); } + + /* reset shell window pointers, if the corresponding window is destroyed */ + if (win == shell_window) + { + shell_window = 0; + + /* release the shell window owner pointer */ + if (shell_window_owner) + { + release_object(shell_window_owner); + shell_window_owner = 0; + } + } + + if (win == shell_listview) + shell_listview = 0; + free_user_handle( win->handle ); destroy_properties( win ); unlink_window( win ); @@ -454,9 +480,10 @@ if (!(parent = get_window( req->parent ))) return; if (req->owner && !(owner = get_window( req->owner ))) return; - if (owner == top_window) owner = NULL; - else if (owner && parent != top_window) - { + + if (owner == top_window) owner = NULL; + else if (owner && parent != top_window) + { /* an owned window must be created as top-level */ set_error( STATUS_ACCESS_DENIED ); return; @@ -499,6 +526,7 @@ } } } + link_window( win, parent, previous ); } @@ -819,4 +847,37 @@ data++; count--; } +} + + +/* set the shell windows */ +DECL_HANDLER(set_shell_windows) +{ + /* test if we are permitted to change the shell window */ + if (shell_window_owner && current->process!=shell_window_owner) + { + set_error(STATUS_ACCESS_DENIED); + } + else + { + shell_window = req->shell_window? get_window(req->shell_window): 0; + shell_listview = req->shell_listview? get_window(req->shell_listview): 0; + + /* We only have to set shell_window_owner if there was none previously. + It can't be the case, that we have to owerwrite the owner with + another process, since we already checked for this case above. */ + if (shell_window && !shell_window_owner) + { + /* request shell window for the calling process */ + shell_window_owner = (struct process*)grab_object(current->process); + } + } +} + + +/* get the shell windows */ +DECL_HANDLER(get_shell_windows) +{ + reply->shell_window = shell_window? shell_window->handle: 0; + reply->shell_listview = shell_listview? shell_listview->handle: 0; } Index: windows/winpos.c =================================================================== RCS file: /home/wine/wine/windows/winpos.c,v retrieving revision 1.146 diff -u -r1.146 winpos.c --- windows/winpos.c 5 Sep 2003 23:15:39 -0000 1.146 +++ windows/winpos.c 28 Sep 2003 09:08:57 -0000 @@ -67,7 +67,6 @@ /* ----- internal variables ----- */ -static HWND hGlobalShellWindow=0; /*the shell*/ static HWND hGlobalTaskmanWindow=0; static HWND hGlobalProgmanWindow=0; @@ -632,27 +631,6 @@ } -/******************************************************************* - * SetShellWindow (USER32.@) - */ -HWND WINAPI SetShellWindow(HWND hwndshell) -{ WARN("(hWnd=%p) semi stub\n",hwndshell ); - - hGlobalShellWindow = WIN_GetFullHandle( hwndshell ); - return hGlobalShellWindow; -} - - -/******************************************************************* - * GetShellWindow (USER32.@) - */ -HWND WINAPI GetShellWindow(void) -{ WARN("(hWnd=%p) semi stub\n",hGlobalShellWindow ); - - return hGlobalShellWindow; -} - - /*********************************************************************** * BringWindowToTop (USER32.@) */ @@ -1049,7 +1027,9 @@ style = GetWindowLongW( hwnd, GWL_STYLE ); if (!(style & WS_VISIBLE)) return FALSE; if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; - return !(style & WS_DISABLED); + if (style & WS_DISABLED) return FALSE; + if (hwnd == GetShellWindow()) return FALSE; + return TRUE; } @@ -1362,25 +1342,6 @@ HWND WINAPI GetProgmanWindow(void) { return hGlobalProgmanWindow; -} - -/*********************************************************************** - * SetShellWindowEx (USER32.@) - * hwndProgman = Progman[Program Manager] - * |-> SHELLDLL_DefView - * hwndListView = | |-> SysListView32 - * | | |-> tooltips_class32 - * | | - * | |-> SysHeader32 - * | - * |-> ProxyTarget - */ -HWND WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView ) -{ - FIXME("%p %p stub\n",hwndProgman ,hwndListView ); - hGlobalShellWindow = hwndProgman; - return hGlobalShellWindow; - } /***********************************************************************