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)
$(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)

View file

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

View file

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

View file

@ -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<NotifyIconConfig> 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<NotifyIconIndex, NotifyInfo> NotifyIconMap;
@ -127,6 +159,8 @@ protected:
NotifyIconSet::iterator IconHitTest(const POINT& pos);
bool DetermineHideState(NotifyInfo& entry);
NotifyIconCfgList _cfg;
NotifyHook _hook;
map<HWND, String> _window_modules;
};