explorer: Merged systray support with the desktop window main loop.
Systray is now always available as part of the desktop and doesn't need to be started from shell32.
This commit is contained in:
parent
1a4f6e579b
commit
576e3b7062
|
@ -38,49 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(systray);
|
||||||
|
|
||||||
const static WCHAR classname[] = /* Shell_TrayWnd */ {'S','h','e','l','l','_','T','r','a','y','W','n','d','\0'};
|
const static WCHAR classname[] = /* Shell_TrayWnd */ {'S','h','e','l','l','_','T','r','a','y','W','n','d','\0'};
|
||||||
|
|
||||||
/* start timeout of 1 second */
|
|
||||||
#define SYSTRAY_START_TIMEOUT 1000
|
|
||||||
|
|
||||||
static BOOL start_systray_process(void)
|
|
||||||
{
|
|
||||||
STARTUPINFOW sinfo;
|
|
||||||
PROCESS_INFORMATION pinfo;
|
|
||||||
WCHAR command_line[] = {'e','x','p','l','o','r','e','r',' ','/','s','y','s','t','r','a','y',0};
|
|
||||||
static const WCHAR event_name[] = {'W','i','n','e','S','y','s','t','r','a','y','I','n','i','t','e','d',0};
|
|
||||||
HANDLE systray_ready_event;
|
|
||||||
DWORD wait;
|
|
||||||
|
|
||||||
TRACE("No tray window found, starting %s\n", debugstr_w(command_line));
|
|
||||||
|
|
||||||
ZeroMemory(&sinfo, sizeof(sinfo));
|
|
||||||
sinfo.cb = sizeof(sinfo);
|
|
||||||
|
|
||||||
if (CreateProcessW(NULL, command_line, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo) == 0)
|
|
||||||
{
|
|
||||||
ERR("Could not start %s, error 0x%lx\n", debugstr_w(command_line), GetLastError());
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(pinfo.hThread);
|
|
||||||
CloseHandle(pinfo.hProcess);
|
|
||||||
|
|
||||||
systray_ready_event = CreateEventW(NULL, TRUE, FALSE, event_name);
|
|
||||||
if (!systray_ready_event) return FALSE;
|
|
||||||
|
|
||||||
/* don't guess how long to wait, just wait for process to signal to us
|
|
||||||
* that it has created the Shell_TrayWnd class before continuing */
|
|
||||||
wait = WaitForSingleObject(systray_ready_event, SYSTRAY_START_TIMEOUT);
|
|
||||||
CloseHandle(systray_ready_event);
|
|
||||||
|
|
||||||
if (wait == WAIT_TIMEOUT)
|
|
||||||
{
|
|
||||||
ERR("timeout waiting for %s to start\n", debugstr_w(command_line));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* Shell_NotifyIcon [SHELL32.296]
|
* Shell_NotifyIcon [SHELL32.296]
|
||||||
* Shell_NotifyIconA [SHELL32.297]
|
* Shell_NotifyIconA [SHELL32.297]
|
||||||
|
@ -126,16 +83,6 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
|
||||||
TRACE("dwMessage = %ld\n", dwMessage);
|
TRACE("dwMessage = %ld\n", dwMessage);
|
||||||
|
|
||||||
tray = FindWindowExW(0, NULL, classname, NULL);
|
tray = FindWindowExW(0, NULL, classname, NULL);
|
||||||
|
|
||||||
/* this isn't how native does it - it assumes that Explorer is always
|
|
||||||
* running */
|
|
||||||
if (!tray)
|
|
||||||
{
|
|
||||||
if (!start_systray_process())
|
|
||||||
return FALSE;
|
|
||||||
tray = FindWindowExW(0, NULL, classname, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tray) return FALSE;
|
if (!tray) return FALSE;
|
||||||
|
|
||||||
cds.dwData = dwMessage;
|
cds.dwData = dwMessage;
|
||||||
|
|
|
@ -69,6 +69,9 @@ void manage_desktop(void)
|
||||||
SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)desktop_wnd_proc );
|
SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)desktop_wnd_proc );
|
||||||
|
|
||||||
WINE_TRACE( "explorer starting on hwnd %p\n", hwnd );
|
WINE_TRACE( "explorer starting on hwnd %p\n", hwnd );
|
||||||
|
|
||||||
|
initialize_systray();
|
||||||
while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
|
while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
|
||||||
|
|
||||||
WINE_TRACE( "explorer exiting for hwnd %p\n", hwnd );
|
WINE_TRACE( "explorer exiting for hwnd %p\n", hwnd );
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,15 +24,11 @@
|
||||||
|
|
||||||
#include <wine/debug.h>
|
#include <wine/debug.h>
|
||||||
#include "explorer_private.h"
|
#include "explorer_private.h"
|
||||||
#include <systray.h>
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(explorer);
|
WINE_DEFAULT_DEBUG_CHANNEL(explorer);
|
||||||
|
|
||||||
unsigned int shell_refs = 0;
|
|
||||||
|
|
||||||
typedef struct parametersTAG {
|
typedef struct parametersTAG {
|
||||||
BOOL explorer_mode;
|
BOOL explorer_mode;
|
||||||
BOOL systray_mode;
|
|
||||||
BOOL desktop_mode;
|
BOOL desktop_mode;
|
||||||
WCHAR root[MAX_PATH];
|
WCHAR root[MAX_PATH];
|
||||||
WCHAR selection[MAX_PATH];
|
WCHAR selection[MAX_PATH];
|
||||||
|
@ -139,11 +135,6 @@ static void ParseCommandLine(LPSTR commandline,parameters_struct *parameters)
|
||||||
CopyPathRoot(parameters->root,
|
CopyPathRoot(parameters->root,
|
||||||
parameters->selection);
|
parameters->selection);
|
||||||
}
|
}
|
||||||
else if (strncmp(p,"systray",7)==0)
|
|
||||||
{
|
|
||||||
parameters->systray_mode = TRUE;
|
|
||||||
p+=7;
|
|
||||||
}
|
|
||||||
else if (strncmp(p,"desktop",7)==0)
|
else if (strncmp(p,"desktop",7)==0)
|
||||||
{
|
{
|
||||||
parameters->desktop_mode = TRUE;
|
parameters->desktop_mode = TRUE;
|
||||||
|
@ -159,44 +150,6 @@ static void ParseCommandLine(LPSTR commandline,parameters_struct *parameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_systray_loop(void)
|
|
||||||
{
|
|
||||||
initialize_systray();
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
const int timeout = 5;
|
|
||||||
MSG message;
|
|
||||||
DWORD res;
|
|
||||||
|
|
||||||
res = MsgWaitForMultipleObjectsEx(0, NULL, shell_refs ? INFINITE : timeout * 1000,
|
|
||||||
QS_ALLINPUT, MWMO_WAITALL);
|
|
||||||
if (res == WAIT_TIMEOUT) break;
|
|
||||||
|
|
||||||
res = PeekMessage(&message, 0, 0, 0, PM_REMOVE);
|
|
||||||
if (!res) continue;
|
|
||||||
|
|
||||||
if (message.message == WM_QUIT)
|
|
||||||
{
|
|
||||||
WINE_FIXME("Somebody sent the shell a WM_QUIT message, should we reboot?");
|
|
||||||
|
|
||||||
/* Sending the tray window a WM_QUIT message is actually a
|
|
||||||
* tip given by some programming websites as a way of
|
|
||||||
* forcing a reboot! let's delay implementing this hack
|
|
||||||
* until we find a program that really needs it. for now
|
|
||||||
* just bail out.
|
|
||||||
*/
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TranslateMessage(&message);
|
|
||||||
DispatchMessage(&message);
|
|
||||||
}
|
|
||||||
|
|
||||||
shutdown_systray();
|
|
||||||
}
|
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hinstance,
|
int WINAPI WinMain(HINSTANCE hinstance,
|
||||||
HINSTANCE previnstance,
|
HINSTANCE previnstance,
|
||||||
LPSTR cmdline,
|
LPSTR cmdline,
|
||||||
|
@ -217,11 +170,6 @@ int WINAPI WinMain(HINSTANCE hinstance,
|
||||||
ParseCommandLine(cmdline,¶meters);
|
ParseCommandLine(cmdline,¶meters);
|
||||||
len = lstrlenW(winefile) +1;
|
len = lstrlenW(winefile) +1;
|
||||||
|
|
||||||
if (parameters.systray_mode)
|
|
||||||
{
|
|
||||||
do_systray_loop();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (parameters.desktop_mode)
|
if (parameters.desktop_mode)
|
||||||
{
|
{
|
||||||
manage_desktop();
|
manage_desktop();
|
||||||
|
|
|
@ -22,5 +22,6 @@
|
||||||
#define __WINE_EXPLORER_PRIVATE_H
|
#define __WINE_EXPLORER_PRIVATE_H
|
||||||
|
|
||||||
extern void manage_desktop(void);
|
extern void manage_desktop(void);
|
||||||
|
extern void initialize_systray(void);
|
||||||
|
|
||||||
#endif /* __WINE_EXPLORER_PRIVATE_H */
|
#endif /* __WINE_EXPLORER_PRIVATE_H */
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
#include <wine/debug.h>
|
#include <wine/debug.h>
|
||||||
#include <wine/list.h>
|
#include <wine/list.h>
|
||||||
|
|
||||||
#include "systray.h"
|
#include "explorer_private.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(systray);
|
WINE_DEFAULT_DEBUG_CHANNEL(systray);
|
||||||
|
|
||||||
|
@ -127,8 +127,8 @@ static LRESULT WINAPI adaptor_wndproc(HWND window, UINT msg,
|
||||||
ret = PostMessage(icon->owner, icon->callback_message, (WPARAM) icon->id, (LPARAM) msg);
|
ret = PostMessage(icon->owner, icon->callback_message, (WPARAM) icon->id, (LPARAM) msg);
|
||||||
if (!ret && (GetLastError() == ERROR_INVALID_HANDLE))
|
if (!ret && (GetLastError() == ERROR_INVALID_HANDLE))
|
||||||
{
|
{
|
||||||
WINE_ERR("application window was destroyed without removing "
|
WINE_WARN("application window was destroyed without removing "
|
||||||
"notification icon, removing automatically\n");
|
"notification icon, removing automatically\n");
|
||||||
DestroyWindow(window);
|
DestroyWindow(window);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -140,9 +140,6 @@ static LRESULT WINAPI adaptor_wndproc(HWND window, UINT msg,
|
||||||
list_remove(&icon->entry);
|
list_remove(&icon->entry);
|
||||||
DestroyIcon(icon->image);
|
DestroyIcon(icon->image);
|
||||||
HeapFree(GetProcessHeap(), 0, icon);
|
HeapFree(GetProcessHeap(), 0, icon);
|
||||||
|
|
||||||
shell_refs--;
|
|
||||||
WINE_TRACE("shell now has %d refs\n", shell_refs);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,9 +233,6 @@ static void add_icon(const NOTIFYICONDATAW *nid)
|
||||||
list_add_tail(&tray.icons, &icon->entry);
|
list_add_tail(&tray.icons, &icon->entry);
|
||||||
|
|
||||||
modify_icon(nid);
|
modify_icon(nid);
|
||||||
|
|
||||||
shell_refs++;
|
|
||||||
WINE_TRACE("shell now has %d refs\n", shell_refs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delete_icon(const NOTIFYICONDATAW *nid)
|
static void delete_icon(const NOTIFYICONDATAW *nid)
|
||||||
|
@ -365,11 +359,9 @@ static BOOL is_systray_hidden(void)
|
||||||
void initialize_systray(void)
|
void initialize_systray(void)
|
||||||
{
|
{
|
||||||
WNDCLASSEX class;
|
WNDCLASSEX class;
|
||||||
HANDLE event;
|
|
||||||
static const WCHAR classname[] = /* Shell_TrayWnd */ {'S','h','e','l','l','_','T','r','a','y','W','n','d',0};
|
static const WCHAR classname[] = /* Shell_TrayWnd */ {'S','h','e','l','l','_','T','r','a','y','W','n','d',0};
|
||||||
static const WCHAR winname[] = /* Wine Systray Listener */
|
static const WCHAR winname[] = /* Wine Systray Listener */
|
||||||
{'W','i','n','e',' ','S','y','s','t','r','a','y',' ','L','i','s','t','e','n','e','r',0};
|
{'W','i','n','e',' ','S','y','s','t','r','a','y',' ','L','i','s','t','e','n','e','r',0};
|
||||||
static const WCHAR event_name[] = {'W','i','n','e','S','y','s','t','r','a','y','I','n','i','t','e','d',0};
|
|
||||||
|
|
||||||
WINE_TRACE("initiaizing\n");
|
WINE_TRACE("initiaizing\n");
|
||||||
|
|
||||||
|
@ -419,17 +411,4 @@ void initialize_systray(void)
|
||||||
WINE_ERR("Could not create tray window\n");
|
WINE_ERR("Could not create tray window\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tell shell32 that we're ready */
|
|
||||||
event = OpenEventW(EVENT_MODIFY_STATE, FALSE, event_name);
|
|
||||||
if (event)
|
|
||||||
{
|
|
||||||
SetEvent(event);
|
|
||||||
CloseHandle(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void shutdown_systray(void)
|
|
||||||
{
|
|
||||||
DestroyWindow(tray.window);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2004 Mike Hearn, for CodeWeavers
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
void initialize_systray(void);
|
|
||||||
void shutdown_systray(void);
|
|
||||||
|
|
||||||
/* when this drops to zero, a few seconds later the shell will shut down */
|
|
||||||
extern unsigned int shell_refs;
|
|
Loading…
Reference in New Issue