auto-hiding of inactive notification icons

svn path=/trunk/; revision=8807
This commit is contained in:
Martin Fuchs 2004-03-20 11:42:22 +00:00
parent 5ac2148058
commit f06e49faea
4 changed files with 162 additions and 36 deletions

View file

@ -77,12 +77,15 @@ DELAYIMPORTS = oleaut32 wsock32
all: $(TARGET) all: $(TARGET)
$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) $(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) notifyhook.dll
$(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS)) $(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS))
explorer$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico explorer$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico
windres $(RCFLAGS) -o $@ $(PROGRAM)_intres.rc 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: clean:
rm -f $(TARGET) $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) rm -f $(TARGET) $(OBJECTS) $(PROGRAM)$(RES_SUFFIX)

View file

@ -1,5 +1,4 @@
- read "DESCRIPT.ION" files to display file descriptions - read "DESCRIPT.ION" files to display file descriptions
- hiding of notification icons
- context menus for quick launch bar - context menus for quick launch bar
- detect display mode changes and adjust desktop bar size - detect display mode changes and adjust desktop bar size
- handling of full screen applications - handling of full screen applications

View file

@ -89,6 +89,9 @@ NotifyInfo::NotifyInfo()
_dwState = 0; _dwState = 0;
_uCallbackMessage = 0; _uCallbackMessage = 0;
_version = 0; _version = 0;
_mode = NIM_AUTO;
_lastChange = GetTickCount();
} }
@ -150,6 +153,9 @@ NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid)
_tipText.assign(txt, l); _tipText.assign(txt, l);
} }
///@todo test for real changes
_lastChange = GetTickCount();
return *this; return *this;
} }
@ -162,6 +168,46 @@ NotifyArea::NotifyArea(HWND hwnd)
_clock_width = 0; _clock_width = 0;
_last_icon_count = 0; _last_icon_count = 0;
_show_hidden = false; _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) LRESULT NotifyArea::Init(LPCREATESTRUCT pcs)
@ -257,10 +303,8 @@ LRESULT NotifyArea::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
String path; String path;
HWND hwnd; HWND hwnd;
if (_hook.ModulePathCopyData(lparam, &hwnd, path)) { if (_hook.ModulePathCopyData(lparam, &hwnd, path))
_window_modules[hwnd] = path; _window_modules[hwnd] = path;
//@@ -> trigger DetermineHideState()
}
break;} break;}
@ -357,7 +401,7 @@ LRESULT NotifyArea::ProcessTrayNotification(int notify_code, NOTIFYICONDATA* pni
entry._idx = ++_next_idx; entry._idx = ++_next_idx;
#if NOTIFYICON_VERSION>=3 // as of 21.08.2003 missing in MinGW headers #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; entry._dwState |= NIS_HIDDEN;
#endif #endif
@ -464,7 +508,7 @@ void NotifyArea::TimerTick()
bool do_refresh = false; bool do_refresh = false;
// Look for task icons without valid owner window. // 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) { for(NotifyIconSet::const_iterator it=_sorted_icons.begin(); it!=_sorted_icons.end(); ++it) {
const NotifyInfo& entry = *it; const NotifyInfo& entry = *it;
@ -473,6 +517,40 @@ void NotifyArea::TimerTick()
++do_refresh; ++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) if (do_refresh)
Refresh(); Refresh();
} }
@ -499,44 +577,56 @@ NotifyIconSet::iterator NotifyArea::IconHitTest(const POINT& pos)
return it; return it;
} }
#if NOTIFYICON_VERSION>=3 // as of 21.08.2003 missing in MinGW headers #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")) if (!_tipText.empty() && !props._tipText.empty())
return true; if (props._tipText == _tipText)
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")))
return true; return true;
if (_tcsstr(title, TEXT("Apache"))) if (!_windowTitle.empty() && !props._windowTitle.empty())
if (_tcsstr(props._windowTitle, _windowTitle))
return true; return true;
if (_tcsstr(title, TEXT("FRITZ!web"))) if (!_modulePath.empty() && !props._modulePath.empty())
if (!_tcsicmp(props._modulePath, _modulePath))
return true; 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; 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 #endif

View file

@ -37,6 +37,8 @@
#define PM_GETMODULEPATH_CB (WM_APP+0x21) #define PM_GETMODULEPATH_CB (WM_APP+0x21)
#define ICON_AUTOHIDE_SECONDS 300
/// NotifyIconIndex is used for maintaining the order of notification icons. /// NotifyIconIndex is used for maintaining the order of notification icons.
struct NotifyIconIndex struct NotifyIconIndex
@ -54,7 +56,34 @@ protected:
NotifyIconIndex(); 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<NotifyIconConfig> NotifyIconCfgList;
/// structure for maintaining informations about one notification icon
struct NotifyInfo : public NotifyIconIndex struct NotifyInfo : public NotifyIconIndex
{ {
NotifyInfo(); NotifyInfo();
@ -71,6 +100,9 @@ struct NotifyInfo : public NotifyIconIndex
UINT _uCallbackMessage; UINT _uCallbackMessage;
UINT _version; UINT _version;
String _tipText; String _tipText;
NOTIFYICONMODE _mode;
DWORD _lastChange; // timer tick value of the last change
}; };
typedef map<NotifyIconIndex, NotifyInfo> NotifyIconMap; typedef map<NotifyIconIndex, NotifyInfo> NotifyIconMap;
@ -127,6 +159,8 @@ protected:
NotifyIconSet::iterator IconHitTest(const POINT& pos); NotifyIconSet::iterator IconHitTest(const POINT& pos);
bool DetermineHideState(NotifyInfo& entry); bool DetermineHideState(NotifyInfo& entry);
NotifyIconCfgList _cfg;
NotifyHook _hook; NotifyHook _hook;
map<HWND, String> _window_modules; map<HWND, String> _window_modules;
}; };