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) */
|
||||
#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 */
|
||||
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);
|
||||
|
||||
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;
|
||||
if (hide)
|
||||
{
|
||||
DestroyWindow(icon->window);
|
||||
DestroyWindow(icon->tooltip);
|
||||
/* At startup icon->hidden == FALSE and icon->window == NULL */
|
||||
if (icon->window)
|
||||
{
|
||||
DestroyWindow(icon->window);
|
||||
DestroyWindow(icon->tooltip);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -264,7 +197,7 @@ static BOOL display_icon(struct icon *icon, BOOL hide)
|
|||
}
|
||||
|
||||
/* Modifies an existing icon record */
|
||||
static BOOL modify_icon(NOTIFYICONDATAW *nid, BOOL modify_tooltip)
|
||||
static BOOL modify_icon(NOTIFYICONDATAW *nid)
|
||||
{
|
||||
struct icon *icon;
|
||||
|
||||
|
@ -278,14 +211,11 @@ static BOOL modify_icon(NOTIFYICONDATAW *nid, BOOL modify_tooltip)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (nid->uFlags & NIF_STATE)
|
||||
{
|
||||
if (nid->dwStateMask & NIS_HIDDEN)
|
||||
display_icon(icon, !!(nid->dwState & NIS_HIDDEN));
|
||||
else
|
||||
display_icon(icon, FALSE);
|
||||
}
|
||||
else
|
||||
if ((nid->uFlags & NIF_STATE) && (nid->dwStateMask & NIS_HIDDEN))
|
||||
display_icon(icon, !!(nid->dwState & NIS_HIDDEN));
|
||||
|
||||
/* startup case*/
|
||||
if ((!icon->window) && (!icon->hidden))
|
||||
display_icon(icon, FALSE);
|
||||
|
||||
if (nid->uFlags & NIF_ICON)
|
||||
|
@ -333,31 +263,45 @@ static BOOL add_icon(NOTIFYICONDATAW *nid)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(icon, sizeof(struct icon));
|
||||
icon->id = nid->uID;
|
||||
icon->owner = nid->hWnd;
|
||||
icon->image = NULL;
|
||||
icon->window = NULL;
|
||||
icon->hidden = TRUE;
|
||||
|
||||
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)
|
||||
{
|
||||
struct icon *icon = get_icon(nid->hWnd, nid->uID);
|
||||
|
||||
WINE_TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd);
|
||||
|
||||
|
||||
if (!icon)
|
||||
{
|
||||
WINE_WARN("invalid tray icon ID specified: %u\n", nid->uID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
display_icon(icon, TRUE);
|
||||
return TRUE;
|
||||
return delete_icon_directly(icon);
|
||||
}
|
||||
|
||||
static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
|
||||
|
@ -420,7 +364,7 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
|
|||
ret = delete_icon(&nid);
|
||||
break;
|
||||
case NIM_MODIFY:
|
||||
ret = modify_icon(&nid, TRUE);
|
||||
ret = modify_icon(&nid);
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue