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.
oldstable
Alexandre Julliard 2006-03-07 11:50:05 +01:00
parent 1a4f6e579b
commit 576e3b7062
6 changed files with 7 additions and 152 deletions

View File

@ -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'};
/* 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_NotifyIconA [SHELL32.297]
@ -126,16 +83,6 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
TRACE("dwMessage = %ld\n", dwMessage);
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;
cds.dwData = dwMessage;

View File

@ -69,6 +69,9 @@ void manage_desktop(void)
SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)desktop_wnd_proc );
WINE_TRACE( "explorer starting on hwnd %p\n", hwnd );
initialize_systray();
while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
WINE_TRACE( "explorer exiting for hwnd %p\n", hwnd );
}

View File

@ -24,15 +24,11 @@
#include <wine/debug.h>
#include "explorer_private.h"
#include <systray.h>
WINE_DEFAULT_DEBUG_CHANNEL(explorer);
unsigned int shell_refs = 0;
typedef struct parametersTAG {
BOOL explorer_mode;
BOOL systray_mode;
BOOL desktop_mode;
WCHAR root[MAX_PATH];
WCHAR selection[MAX_PATH];
@ -139,11 +135,6 @@ static void ParseCommandLine(LPSTR commandline,parameters_struct *parameters)
CopyPathRoot(parameters->root,
parameters->selection);
}
else if (strncmp(p,"systray",7)==0)
{
parameters->systray_mode = TRUE;
p+=7;
}
else if (strncmp(p,"desktop",7)==0)
{
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,
HINSTANCE previnstance,
LPSTR cmdline,
@ -217,11 +170,6 @@ int WINAPI WinMain(HINSTANCE hinstance,
ParseCommandLine(cmdline,&parameters);
len = lstrlenW(winefile) +1;
if (parameters.systray_mode)
{
do_systray_loop();
return 0;
}
if (parameters.desktop_mode)
{
manage_desktop();

View File

@ -22,5 +22,6 @@
#define __WINE_EXPLORER_PRIVATE_H
extern void manage_desktop(void);
extern void initialize_systray(void);
#endif /* __WINE_EXPLORER_PRIVATE_H */

View File

@ -37,7 +37,7 @@
#include <wine/debug.h>
#include <wine/list.h>
#include "systray.h"
#include "explorer_private.h"
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);
if (!ret && (GetLastError() == ERROR_INVALID_HANDLE))
{
WINE_ERR("application window was destroyed without removing "
"notification icon, removing automatically\n");
WINE_WARN("application window was destroyed without removing "
"notification icon, removing automatically\n");
DestroyWindow(window);
}
return 0;
@ -140,9 +140,6 @@ static LRESULT WINAPI adaptor_wndproc(HWND window, UINT msg,
list_remove(&icon->entry);
DestroyIcon(icon->image);
HeapFree(GetProcessHeap(), 0, icon);
shell_refs--;
WINE_TRACE("shell now has %d refs\n", shell_refs);
break;
}
@ -236,9 +233,6 @@ static void add_icon(const NOTIFYICONDATAW *nid)
list_add_tail(&tray.icons, &icon->entry);
modify_icon(nid);
shell_refs++;
WINE_TRACE("shell now has %d refs\n", shell_refs);
}
static void delete_icon(const NOTIFYICONDATAW *nid)
@ -365,11 +359,9 @@ static BOOL is_systray_hidden(void)
void initialize_systray(void)
{
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 winname[] = /* Wine Systray Listener */
{'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");
@ -419,17 +411,4 @@ void initialize_systray(void)
WINE_ERR("Could not create tray window\n");
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);
}

View File

@ -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;