systray: Correctly handle icon addition/deletion.
This commit is contained in:
parent
7515f312f9
commit
be2911a180
|
@ -77,80 +77,6 @@ static BOOL hide_systray;
|
||||||
/* space around icon (forces icon to center of KDE systray area) */
|
/* space around icon (forces icon to center of KDE systray area) */
|
||||||
#define ICON_BORDER 4
|
#define ICON_BORDER 4
|
||||||
|
|
||||||
static LRESULT WINAPI adaptor_wndproc(HWND window, UINT msg,
|
|
||||||
WPARAM wparam, LPARAM lparam)
|
|
||||||
{
|
|
||||||
struct icon *icon = NULL;
|
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
WINE_TRACE("hwnd=%p, msg=0x%x\n", window, msg);
|
|
||||||
|
|
||||||
/* set the icon data for the window from the data passed into CreateWindow */
|
|
||||||
if (msg == WM_NCCREATE)
|
|
||||||
SetWindowLongPtrW(window, GWLP_USERDATA, (LPARAM)((const CREATESTRUCT *)lparam)->lpCreateParams);
|
|
||||||
|
|
||||||
icon = (struct icon *) GetWindowLongPtr(window, GWLP_USERDATA);
|
|
||||||
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_PAINT:
|
|
||||||
{
|
|
||||||
RECT rc;
|
|
||||||
int top;
|
|
||||||
PAINTSTRUCT ps;
|
|
||||||
HDC hdc;
|
|
||||||
|
|
||||||
WINE_TRACE("painting\n");
|
|
||||||
|
|
||||||
hdc = BeginPaint(window, &ps);
|
|
||||||
GetClientRect(window, &rc);
|
|
||||||
|
|
||||||
/* calculate top so we can deal with arbitrary sized trays */
|
|
||||||
top = ((rc.bottom-rc.top)/2) - ((ICON_SIZE)/2);
|
|
||||||
|
|
||||||
DrawIconEx(hdc, (ICON_BORDER/2), top, icon->image,
|
|
||||||
ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL);
|
|
||||||
|
|
||||||
EndPaint(window, &ps);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_MOUSEMOVE:
|
|
||||||
case WM_LBUTTONDOWN:
|
|
||||||
case WM_LBUTTONUP:
|
|
||||||
case WM_RBUTTONDOWN:
|
|
||||||
case WM_RBUTTONUP:
|
|
||||||
case WM_MBUTTONDOWN:
|
|
||||||
case WM_MBUTTONUP:
|
|
||||||
case WM_LBUTTONDBLCLK:
|
|
||||||
case WM_RBUTTONDBLCLK:
|
|
||||||
case WM_MBUTTONDBLCLK:
|
|
||||||
/* notify the owner hwnd of the message */
|
|
||||||
WINE_TRACE("relaying 0x%x\n", msg);
|
|
||||||
ret = PostMessage(icon->owner, icon->callback_message, (WPARAM) icon->id, (LPARAM) msg);
|
|
||||||
if (!ret && (GetLastError() == ERROR_INVALID_HANDLE))
|
|
||||||
{
|
|
||||||
WINE_WARN("application window was destroyed without removing "
|
|
||||||
"notification icon, removing automatically\n");
|
|
||||||
DestroyWindow(window);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_NCDESTROY:
|
|
||||||
SetWindowLongPtr(window, GWLP_USERDATA, 0);
|
|
||||||
|
|
||||||
list_remove(&icon->entry);
|
|
||||||
DestroyIcon(icon->image);
|
|
||||||
HeapFree(GetProcessHeap(), 0, icon);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return DefWindowProc(window, msg, wparam, lparam);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Retrieves icon record by owner window and ID */
|
/* Retrieves icon record by owner window and ID */
|
||||||
static struct icon *get_icon(HWND owner, UINT id)
|
static struct icon *get_icon(HWND owner, UINT id)
|
||||||
|
@ -226,12 +152,19 @@ static BOOL display_icon(struct icon *icon, BOOL hide)
|
||||||
|
|
||||||
WINE_TRACE("id=0x%x, hwnd=%p, hide=%d\n", icon->id, icon->owner, hide);
|
WINE_TRACE("id=0x%x, hwnd=%p, hide=%d\n", icon->id, icon->owner, hide);
|
||||||
|
|
||||||
if (icon->hidden == hide || (!icon->hidden) == (!hide)) return TRUE;
|
/* not a startup case and nothing to do */
|
||||||
|
if (icon->window && !icon->hidden == !hide)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
icon->hidden = hide;
|
icon->hidden = hide;
|
||||||
if (hide)
|
if (hide)
|
||||||
{
|
{
|
||||||
DestroyWindow(icon->window);
|
/* At startup icon->hidden == FALSE and icon->window == NULL */
|
||||||
DestroyWindow(icon->tooltip);
|
if (icon->window)
|
||||||
|
{
|
||||||
|
DestroyWindow(icon->window);
|
||||||
|
DestroyWindow(icon->tooltip);
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +197,7 @@ static BOOL display_icon(struct icon *icon, BOOL hide)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modifies an existing icon record */
|
/* Modifies an existing icon record */
|
||||||
static BOOL modify_icon(NOTIFYICONDATAW *nid, BOOL modify_tooltip)
|
static BOOL modify_icon(NOTIFYICONDATAW *nid)
|
||||||
{
|
{
|
||||||
struct icon *icon;
|
struct icon *icon;
|
||||||
|
|
||||||
|
@ -278,14 +211,11 @@ static BOOL modify_icon(NOTIFYICONDATAW *nid, BOOL modify_tooltip)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nid->uFlags & NIF_STATE)
|
if ((nid->uFlags & NIF_STATE) && (nid->dwStateMask & NIS_HIDDEN))
|
||||||
{
|
display_icon(icon, !!(nid->dwState & NIS_HIDDEN));
|
||||||
if (nid->dwStateMask & NIS_HIDDEN)
|
|
||||||
display_icon(icon, !!(nid->dwState & NIS_HIDDEN));
|
/* startup case*/
|
||||||
else
|
if ((!icon->window) && (!icon->hidden))
|
||||||
display_icon(icon, FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
display_icon(icon, FALSE);
|
display_icon(icon, FALSE);
|
||||||
|
|
||||||
if (nid->uFlags & NIF_ICON)
|
if (nid->uFlags & NIF_ICON)
|
||||||
|
@ -333,31 +263,45 @@ static BOOL add_icon(NOTIFYICONDATAW *nid)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZeroMemory(icon, sizeof(struct icon));
|
||||||
icon->id = nid->uID;
|
icon->id = nid->uID;
|
||||||
icon->owner = nid->hWnd;
|
icon->owner = nid->hWnd;
|
||||||
icon->image = NULL;
|
|
||||||
icon->window = NULL;
|
|
||||||
icon->hidden = TRUE;
|
|
||||||
|
|
||||||
list_add_tail(&tray.icons, &icon->entry);
|
list_add_tail(&tray.icons, &icon->entry);
|
||||||
|
|
||||||
return modify_icon(nid, FALSE);
|
/*
|
||||||
|
* Both icon->window and icon->hidden are zero. modify_icon function
|
||||||
|
* will treat this case as a startup, i.e. icon window will be created if
|
||||||
|
* NIS_HIDDEN flag is not set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return modify_icon(nid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Deletes tray icon window and icon record */
|
||||||
|
static BOOL delete_icon_directly(struct icon *icon)
|
||||||
|
{
|
||||||
|
display_icon(icon, TRUE);
|
||||||
|
list_remove(&icon->entry);
|
||||||
|
DestroyIcon(icon->image);
|
||||||
|
HeapFree(GetProcessHeap(), 0, icon);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deletes tray icon window and icon structure */
|
||||||
static BOOL delete_icon(const NOTIFYICONDATAW *nid)
|
static BOOL delete_icon(const NOTIFYICONDATAW *nid)
|
||||||
{
|
{
|
||||||
struct icon *icon = get_icon(nid->hWnd, nid->uID);
|
struct icon *icon = get_icon(nid->hWnd, nid->uID);
|
||||||
|
|
||||||
WINE_TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd);
|
WINE_TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd);
|
||||||
|
|
||||||
if (!icon)
|
if (!icon)
|
||||||
{
|
{
|
||||||
WINE_WARN("invalid tray icon ID specified: %u\n", nid->uID);
|
WINE_WARN("invalid tray icon ID specified: %u\n", nid->uID);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
display_icon(icon, TRUE);
|
return delete_icon_directly(icon);
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
|
static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
|
||||||
|
@ -420,7 +364,7 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
|
||||||
ret = delete_icon(&nid);
|
ret = delete_icon(&nid);
|
||||||
break;
|
break;
|
||||||
case NIM_MODIFY:
|
case NIM_MODIFY:
|
||||||
ret = modify_icon(&nid, TRUE);
|
ret = modify_icon(&nid);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WINE_FIXME("unhandled tray message: %ld\n", cds->dwData);
|
WINE_FIXME("unhandled tray message: %ld\n", cds->dwData);
|
||||||
|
@ -444,6 +388,76 @@ static LRESULT WINAPI listener_wndproc(HWND window, UINT msg,
|
||||||
return DefWindowProc(window, msg, wparam, lparam);
|
return DefWindowProc(window, msg, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LRESULT WINAPI adaptor_wndproc(HWND window, UINT msg,
|
||||||
|
WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
struct icon *icon = NULL;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
WINE_TRACE("hwnd=%p, msg=0x%x\n", window, msg);
|
||||||
|
|
||||||
|
/* set the icon data for the window from the data passed into CreateWindow */
|
||||||
|
if (msg == WM_NCCREATE)
|
||||||
|
SetWindowLongPtrW(window, GWLP_USERDATA, (LPARAM)((const CREATESTRUCT *)lparam)->lpCreateParams);
|
||||||
|
|
||||||
|
icon = (struct icon *) GetWindowLongPtr(window, GWLP_USERDATA);
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_PAINT:
|
||||||
|
{
|
||||||
|
RECT rc;
|
||||||
|
int top;
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
HDC hdc;
|
||||||
|
|
||||||
|
WINE_TRACE("painting\n");
|
||||||
|
|
||||||
|
hdc = BeginPaint(window, &ps);
|
||||||
|
GetClientRect(window, &rc);
|
||||||
|
|
||||||
|
/* calculate top so we can deal with arbitrary sized trays */
|
||||||
|
top = ((rc.bottom-rc.top)/2) - ((ICON_SIZE)/2);
|
||||||
|
|
||||||
|
DrawIconEx(hdc, (ICON_BORDER/2), top, icon->image,
|
||||||
|
ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL);
|
||||||
|
|
||||||
|
EndPaint(window, &ps);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
case WM_MBUTTONDOWN:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_RBUTTONDBLCLK:
|
||||||
|
case WM_MBUTTONDBLCLK:
|
||||||
|
/* notify the owner hwnd of the message */
|
||||||
|
WINE_TRACE("relaying 0x%x\n", msg);
|
||||||
|
ret = PostMessage(icon->owner, icon->callback_message, (WPARAM) icon->id, (LPARAM) msg);
|
||||||
|
if (!ret && (GetLastError() == ERROR_INVALID_HANDLE))
|
||||||
|
{
|
||||||
|
WINE_WARN("application window was destroyed without removing "
|
||||||
|
"notification icon, removing automatically\n");
|
||||||
|
delete_icon_directly(icon);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_NCDESTROY:
|
||||||
|
SetWindowLongPtr(window, GWLP_USERDATA, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DefWindowProc(window, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOL is_systray_hidden(void)
|
static BOOL is_systray_hidden(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue