diff --git a/reactos/subsys/system/explorer/Makefile.MinGW b/reactos/subsys/system/explorer/Makefile.MinGW index e9a2bc63d73..44a78f592ed 100644 --- a/reactos/subsys/system/explorer/Makefile.MinGW +++ b/reactos/subsys/system/explorer/Makefile.MinGW @@ -77,12 +77,15 @@ DELAYIMPORTS = oleaut32 wsock32 all: $(TARGET) -$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) +$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) notifyhook.dll $(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS)) explorer$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico windres $(RCFLAGS) -o $@ $(PROGRAM)_intres.rc +notifyhook.dll: notifyhook/notifyhook.c notifyhook/notifyhook.h + $(CC) -D_WIN32_IE=0x0600 -Wall -D_NOTIFYHOOK_IMPL -Os -s notifyhook/notifyhook.c -shared -o $@ + clean: rm -f $(TARGET) $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) diff --git a/reactos/subsys/system/explorer/doc/TODO.txt b/reactos/subsys/system/explorer/doc/TODO.txt index cb5301c2165..2c3452cf651 100644 --- a/reactos/subsys/system/explorer/doc/TODO.txt +++ b/reactos/subsys/system/explorer/doc/TODO.txt @@ -1,5 +1,4 @@ - read "DESCRIPT.ION" files to display file descriptions -- hiding of notification icons - context menus for quick launch bar - detect display mode changes and adjust desktop bar size - handling of full screen applications diff --git a/reactos/subsys/system/explorer/taskbar/traynotify.cpp b/reactos/subsys/system/explorer/taskbar/traynotify.cpp index 71e86bb043c..e14e8b5b852 100644 --- a/reactos/subsys/system/explorer/taskbar/traynotify.cpp +++ b/reactos/subsys/system/explorer/taskbar/traynotify.cpp @@ -89,6 +89,9 @@ NotifyInfo::NotifyInfo() _dwState = 0; _uCallbackMessage = 0; _version = 0; + + _mode = NIM_AUTO; + _lastChange = GetTickCount(); } @@ -150,6 +153,9 @@ NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid) _tipText.assign(txt, l); } + ///@todo test for real changes + _lastChange = GetTickCount(); + return *this; } @@ -162,6 +168,46 @@ NotifyArea::NotifyArea(HWND hwnd) _clock_width = 0; _last_icon_count = 0; _show_hidden = false; + + ///@todo read from config file --> + NotifyIconConfig cfg; + + cfg._tipText = TEXT("FRITZ!fon"); + cfg._mode = NIM_HIDE; + _cfg.push_back(cfg); + + cfg._tipText = TEXT("FRITZ!fax"); + cfg._mode = NIM_HIDE; + _cfg.push_back(cfg); + + cfg._tipText = TEXT("Volume"); + cfg._mode = NIM_SHOW; + _cfg.push_back(cfg); + + cfg._tipText.erase(); + + cfg._windowTitle = TEXT("Task Manager"); + cfg._mode = NIM_SHOW; + _cfg.push_back(cfg); + + cfg._windowTitle = TEXT("AntiVir"); + cfg._mode = NIM_HIDE; + _cfg.push_back(cfg); + + cfg._windowTitle = TEXT("Apache"); + cfg._mode = NIM_HIDE; + _cfg.push_back(cfg); + + cfg._windowTitle = TEXT("FRITZ!web"); + cfg._mode = NIM_HIDE; + _cfg.push_back(cfg); + + cfg._windowTitle.erase(); + + cfg._modulePath = TEXT("xyz"); //@@ + cfg._mode = NIM_HIDE; + _cfg.push_back(cfg); + /// <-- } LRESULT NotifyArea::Init(LPCREATESTRUCT pcs) @@ -257,10 +303,8 @@ LRESULT NotifyArea::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) String path; HWND hwnd; - if (_hook.ModulePathCopyData(lparam, &hwnd, path)) { + if (_hook.ModulePathCopyData(lparam, &hwnd, path)) _window_modules[hwnd] = path; - //@@ -> trigger DetermineHideState() - } break;} @@ -357,7 +401,7 @@ LRESULT NotifyArea::ProcessTrayNotification(int notify_code, NOTIFYICONDATA* pni entry._idx = ++_next_idx; #if NOTIFYICON_VERSION>=3 // as of 21.08.2003 missing in MinGW headers - if (DetermineHideState(entry)) + if (DetermineHideState(entry) && entry._mode==NIM_HIDE) entry._dwState |= NIS_HIDDEN; #endif @@ -464,7 +508,7 @@ void NotifyArea::TimerTick() bool do_refresh = false; // Look for task icons without valid owner window. - // This is an advanced feature, which is missing in MS Windows. + // This is an extended feature missing in MS Windows. for(NotifyIconSet::const_iterator it=_sorted_icons.begin(); it!=_sorted_icons.end(); ++it) { const NotifyInfo& entry = *it; @@ -473,6 +517,40 @@ void NotifyArea::TimerTick() ++do_refresh; } + DWORD now = GetTickCount(); + + // handle icon hiding + for(NotifyIconMap::iterator it=_icon_map.begin(); it!=_icon_map.end(); ++it) { + NotifyInfo& entry = it->second; + + DetermineHideState(entry); + + switch(entry._mode) { + case NIM_HIDE: + if (!(entry._dwState & NIS_HIDDEN)) { + entry._dwState |= NIS_HIDDEN; + ++do_refresh; + } + break; + + case NIM_SHOW: + if (entry._dwState&NIS_HIDDEN) { + entry._dwState &= ~NIS_HIDDEN; + ++do_refresh; + } + break; + + case NIM_AUTO: + // automatically hide icons after long periods of inactivity + if (!(entry._dwState & NIS_HIDDEN)) + if (now-entry._lastChange > ICON_AUTOHIDE_SECONDS*1000) { + entry._dwState |= NIS_HIDDEN; + ++do_refresh; + } + break; + } + } + if (do_refresh) Refresh(); } @@ -499,44 +577,56 @@ NotifyIconSet::iterator NotifyArea::IconHitTest(const POINT& pos) return it; } + #if NOTIFYICON_VERSION>=3 // as of 21.08.2003 missing in MinGW headers -bool NotifyArea::DetermineHideState(NotifyInfo& entry) + +bool NotifyIconConfig::match(const NotifyIconProps& props) const { - if (entry._tipText == TEXT("FRITZ!fon")) - return true; - - if (entry._tipText == TEXT("FRITZ!fax")) - return true; - - TCHAR title[MAX_PATH]; - - if (GetWindowText(entry._hWnd, title, MAX_PATH)) { - if (_tcsstr(title, TEXT("Task Manager"))) - return false; - - if (_tcsstr(title, TEXT("AntiVir"))) + if (!_tipText.empty() && !props._tipText.empty()) + if (props._tipText == _tipText) return true; - if (_tcsstr(title, TEXT("Apache"))) + if (!_windowTitle.empty() && !props._windowTitle.empty()) + if (_tcsstr(props._windowTitle, _windowTitle)) return true; - if (_tcsstr(title, TEXT("FRITZ!web"))) + if (!_modulePath.empty() && !props._modulePath.empty()) + if (!_tcsicmp(props._modulePath, _modulePath)) return true; - } - - const String& modulePath = _window_modules[entry._hWnd]; - - // request module path for new windows (We will get an asynchronous answer by a WM_COPYDATA message.) - if (modulePath.empty()) { - _hook.GetModulePath(entry._hWnd, _hwnd); - return false; - } - - if (modulePath == TEXT("xyz")) //@@ - return true; return false; } + +bool NotifyArea::DetermineHideState(NotifyInfo& entry) +{ + for(NotifyIconCfgList::const_iterator it=_cfg.begin(); it!=_cfg.end(); ++it) { + const NotifyIconConfig& cfg = *it; + + NotifyIconProps props; + + props._tipText = entry._tipText; + + TCHAR title[MAX_PATH]; + if (GetWindowText(entry._hWnd, title, MAX_PATH)) + props._windowTitle = title; + + const String& modulePath = _window_modules[entry._hWnd]; + + // request module path for new windows (We will get an asynchronous answer by a WM_COPYDATA message.) + if (!modulePath.empty()) + props._modulePath = modulePath; + else + _hook.GetModulePath(entry._hWnd, _hwnd); + + if (cfg.match(props)) { + entry._mode = cfg._mode; + return true; + } + } + + return false; +} + #endif diff --git a/reactos/subsys/system/explorer/taskbar/traynotify.h b/reactos/subsys/system/explorer/taskbar/traynotify.h index 4f1e53a9108..07a8f229460 100644 --- a/reactos/subsys/system/explorer/taskbar/traynotify.h +++ b/reactos/subsys/system/explorer/taskbar/traynotify.h @@ -37,6 +37,8 @@ #define PM_GETMODULEPATH_CB (WM_APP+0x21) +#define ICON_AUTOHIDE_SECONDS 300 + /// NotifyIconIndex is used for maintaining the order of notification icons. struct NotifyIconIndex @@ -54,7 +56,34 @@ protected: NotifyIconIndex(); }; - /// structure for maintaining informations of one notification icons + +enum NOTIFYICONMODE { + NIM_AUTO, NIM_SHOW, NIM_HIDE +}; + + /// properties used to identify a notification icon +struct NotifyIconProps +{ + String _tipText; + String _windowTitle; // To look at the window title and at the window module path of the notify icon owner window + String _modulePath; // to identify notification icons is an extension above XP's behaviour. +}; // (XP seems to store icon image data in the registry instead.) + + /// configuration for the display mode of a notification icon +struct NotifyIconConfig : public NotifyIconProps +{ + NotifyIconConfig() : _mode(NIM_AUTO) {} + + bool match(const NotifyIconProps& props) const; + + NOTIFYICONMODE _mode; +}; + + /// list of NotifyIconConfig structures +typedef list NotifyIconCfgList; + + + /// structure for maintaining informations about one notification icon struct NotifyInfo : public NotifyIconIndex { NotifyInfo(); @@ -71,6 +100,9 @@ struct NotifyInfo : public NotifyIconIndex UINT _uCallbackMessage; UINT _version; String _tipText; + + NOTIFYICONMODE _mode; + DWORD _lastChange; // timer tick value of the last change }; typedef map NotifyIconMap; @@ -127,6 +159,8 @@ protected: NotifyIconSet::iterator IconHitTest(const POINT& pos); bool DetermineHideState(NotifyInfo& entry); + NotifyIconCfgList _cfg; + NotifyHook _hook; map _window_modules; };