Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
698805d8
Commit
698805d8
authored
Apr 08, 2008
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
explorer: Implement a global system tray window.
parent
49f467c3
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
229 additions
and
204 deletions
+229
-204
systray.c
programs/explorer/systray.c
+229
-204
No files found.
programs/explorer/systray.c
View file @
698805d8
/*
* Copyright (C) 2004 Mike Hearn, for CodeWeavers
* Copyright (C) 2005 Robert Shearman
* Copyright (C) 2008 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -17,17 +18,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* There are two types of window involved here. The first is the
* listener window. This is like the taskbar in Windows. It doesn't
* ever appear on-screen in our implementation, instead we create
* individual mini "adaptor" windows which are docked by the native
* systray host.
*
* In future for those who don't have a systray we could make the
* listener window more clever so it can draw itself like the Windows
* tray area does (with a clock and stuff).
*/
#include <assert.h>
#define UNICODE
...
...
@@ -47,38 +37,31 @@ WINE_DEFAULT_DEBUG_CHANNEL(systray);
static
BOOL
(
*
wine_notify_icon
)(
DWORD
,
NOTIFYICONDATAW
*
);
static
const
WCHAR
adaptor_classname
[]
=
/* Adaptor */
{
'A'
,
'd'
,
'a'
,
'p'
,
't'
,
'o'
,
'r'
,
0
};
/* tray state */
struct
tray
{
HWND
window
;
struct
list
icons
;
};
/* an individual systray icon, unpacked from the NOTIFYICONDATA and always in unicode */
struct
icon
{
struct
list
entry
;
HICON
image
;
/* the image to render */
HWND
owner
;
/* the HWND passed in to the Shell_NotifyIcon call */
HWND
window
;
/* the adaptor window */
HWND
tooltip
;
/* Icon tooltip */
UINT
id
;
/* the unique id given by the app */
UINT
callback_message
;
BOOL
hidden
;
/* icon display state
*/
int
display
;
/* index in display list, or -1 if hidden
*/
WCHAR
tiptext
[
128
];
/* Tooltip text. If empty => tooltip disabled */
};
static
struct
tray
tray
;
static
BOOL
hide_systray
;
static
struct
list
icon_list
=
LIST_INIT
(
icon_list
)
;
static
HWND
tray_window
;
/* adaptor code */
static
unsigned
int
alloc_displayed
;
static
unsigned
int
nb_displayed
;
static
struct
icon
**
displayed
;
/* array of currently displayed icons */
#define ICON_SIZE GetSystemMetrics(SM_CXSMICON)
/* space around icon (forces icon to center of KDE systray area) */
#define ICON_BORDER 4
static
BOOL
hide_systray
;
static
int
icon_cx
,
icon_cy
;
#define MIN_DISPLAYED 8
#define ICON_BORDER 2
/* Retrieves icon record by owner window and ID */
static
struct
icon
*
get_icon
(
HWND
owner
,
UINT
id
)
...
...
@@ -86,12 +69,28 @@ static struct icon *get_icon(HWND owner, UINT id)
struct
icon
*
this
;
/* search for the icon */
LIST_FOR_EACH_ENTRY
(
this
,
&
tray
.
icons
,
struct
icon
,
entry
)
LIST_FOR_EACH_ENTRY
(
this
,
&
icon_list
,
struct
icon
,
entry
)
if
((
this
->
id
==
id
)
&&
(
this
->
owner
==
owner
))
return
this
;
return
NULL
;
}
/* compute the size of the tray window */
static
SIZE
get_window_size
(
void
)
{
SIZE
size
;
RECT
rect
;
rect
.
left
=
0
;
rect
.
top
=
0
;
rect
.
right
=
icon_cx
*
max
(
nb_displayed
,
MIN_DISPLAYED
);
rect
.
bottom
=
icon_cy
;
AdjustWindowRect
(
&
rect
,
WS_CAPTION
,
FALSE
);
size
.
cx
=
rect
.
right
-
rect
.
left
;
size
.
cy
=
rect
.
bottom
-
rect
.
top
;
return
size
;
}
/* Creates tooltip window for icon. */
static
void
create_tooltip
(
struct
icon
*
icon
)
{
...
...
@@ -114,14 +113,19 @@ static void create_tooltip(struct icon *icon)
WS_POPUP
|
TTS_ALWAYSTIP
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
icon
->
window
,
NULL
,
NULL
,
NULL
);
tray_
window
,
NULL
,
NULL
,
NULL
);
ZeroMemory
(
&
ti
,
sizeof
(
ti
));
ti
.
cbSize
=
sizeof
(
TTTOOLINFOW
);
ti
.
uFlags
=
TTF_SUBCLASS
|
TTF_IDISHWND
;
ti
.
hwnd
=
icon
->
window
;
ti
.
uId
=
(
UINT_PTR
)
icon
->
window
;
ti
.
hwnd
=
tray_window
;
ti
.
lpszText
=
icon
->
tiptext
;
if
(
icon
->
display
!=
-
1
)
{
ti
.
rect
.
left
=
icon_cx
*
icon
->
display
;
ti
.
rect
.
right
=
icon_cx
*
(
icon
->
display
+
1
);
ti
.
rect
.
top
=
0
;
ti
.
rect
.
bottom
=
icon_cy
;
}
SendMessageW
(
icon
->
tooltip
,
TTM_ADDTOOLW
,
0
,
(
LPARAM
)
&
ti
);
}
...
...
@@ -132,75 +136,127 @@ static void update_tooltip_text(struct icon *icon)
ZeroMemory
(
&
ti
,
sizeof
(
ti
));
ti
.
cbSize
=
sizeof
(
TTTOOLINFOW
);
ti
.
uFlags
=
TTF_SUBCLASS
|
TTF_IDISHWND
;
ti
.
hwnd
=
icon
->
window
;
ti
.
uId
=
(
UINT_PTR
)
icon
->
window
;
ti
.
hwnd
=
tray_window
;
ti
.
lpszText
=
icon
->
tiptext
;
SendMessageW
(
icon
->
tooltip
,
TTM_UPDATETIPTEXTW
,
0
,
(
LPARAM
)
&
ti
);
}
/*
* Sets visibility status of tray icon. Creates/deletes icon window.
* Does not create/delete icon record.
*
* The purpose is similar to ShowWindow function.
*/
static
BOOL
display_icon
(
struct
icon
*
icon
,
BOOL
hide
)
/* synchronize tooltip position with tooltip window */
static
void
update_tooltip_position
(
struct
icon
*
icon
)
{
TTTOOLINFOW
ti
;
ZeroMemory
(
&
ti
,
sizeof
(
ti
));
ti
.
cbSize
=
sizeof
(
TTTOOLINFOW
);
ti
.
hwnd
=
tray_window
;
if
(
icon
->
display
!=
-
1
)
{
ti
.
rect
.
left
=
icon_cx
*
icon
->
display
;
ti
.
rect
.
right
=
icon_cx
*
(
icon
->
display
+
1
);
ti
.
rect
.
top
=
0
;
ti
.
rect
.
bottom
=
icon_cy
;
}
SendMessageW
(
icon
->
tooltip
,
TTM_NEWTOOLRECTW
,
0
,
(
LPARAM
)
&
ti
);
}
/* find the icon located at a certain point in the tray window */
static
struct
icon
*
icon_from_point
(
int
x
,
int
y
)
{
if
(
y
<
0
||
y
>=
icon_cy
)
return
NULL
;
if
(
x
<
0
||
x
>=
icon_cx
*
nb_displayed
)
return
NULL
;
return
displayed
[
x
/
icon_cx
];
}
/* invalidate the portion of the tray window that contains the specified icons */
static
void
invalidate_icons
(
unsigned
int
start
,
unsigned
int
end
)
{
RECT
rect
;
static
const
WCHAR
adaptor_windowname
[]
=
/* Wine System Tray Adaptor */
{
'W'
,
'i'
,
'n'
,
'e'
,
' '
,
'S'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
' '
,
'T'
,
'r'
,
'a'
,
'y'
,
' '
,
'A'
,
'd'
,
'a'
,
'p'
,
't'
,
'o'
,
'r'
,
0
};
WINE_TRACE
(
"id=0x%x, hwnd=%p, hide=%d
\n
"
,
icon
->
id
,
icon
->
owner
,
hide
);
rect
.
left
=
start
*
icon_cx
;
rect
.
top
=
0
;
rect
.
right
=
(
end
+
1
)
*
icon_cx
;
rect
.
bottom
=
icon_cy
;
InvalidateRect
(
tray_window
,
&
rect
,
TRUE
);
}
/* make an icon visible */
static
BOOL
show_icon
(
struct
icon
*
icon
)
{
WINE_TRACE
(
"id=0x%x, hwnd=%p
\n
"
,
icon
->
id
,
icon
->
owner
);
/* not a startup case and nothing to do */
if
(
icon
->
window
&&
!
icon
->
hidden
==
!
hide
)
return
TRUE
;
if
(
icon
->
display
!=
-
1
)
return
TRUE
;
/* already displayed */
icon
->
hidden
=
hide
;
if
(
hide
)
if
(
nb_displayed
>=
alloc_displayed
)
{
/* At startup icon->hidden == FALSE and icon->window == NULL */
if
(
icon
->
window
)
{
DestroyWindow
(
icon
->
window
);
DestroyWindow
(
icon
->
tooltip
)
;
}
return
TRUE
;
unsigned
int
new_count
=
max
(
alloc_displayed
*
2
,
32
);
struct
icon
**
ptr
;
if
(
displayed
)
ptr
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
displayed
,
new_count
*
sizeof
(
*
ptr
)
);
else
ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
new_count
*
sizeof
(
*
ptr
)
);
if
(
!
ptr
)
return
FALSE
;
displayed
=
ptr
;
alloc_displayed
=
new_count
;
}
rect
.
left
=
0
;
rect
.
top
=
0
;
rect
.
right
=
GetSystemMetrics
(
SM_CXSMICON
)
+
ICON_BORDER
;
rect
.
bottom
=
GetSystemMetrics
(
SM_CYSMICON
)
+
ICON_BORDER
;
AdjustWindowRect
(
&
rect
,
WS_CLIPSIBLINGS
|
WS_CAPTION
,
FALSE
);
/* create the adaptor window */
icon
->
window
=
CreateWindowEx
(
0
,
adaptor_classname
,
adaptor_windowname
,
WS_CLIPSIBLINGS
|
WS_CAPTION
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
rect
.
right
-
rect
.
left
,
rect
.
bottom
-
rect
.
top
,
NULL
,
NULL
,
NULL
,
icon
);
if
(
!
hide_systray
)
ShowWindow
(
icon
->
window
,
SW_SHOWNA
);
icon
->
display
=
nb_displayed
;
displayed
[
nb_displayed
++
]
=
icon
;
update_tooltip_position
(
icon
);
invalidate_icons
(
nb_displayed
-
1
,
nb_displayed
-
1
);
if
(
nb_displayed
>
MIN_DISPLAYED
)
{
SIZE
size
=
get_window_size
();
SetWindowPos
(
tray_window
,
0
,
0
,
0
,
size
.
cx
,
size
.
cy
,
SWP_NOZORDER
|
SWP_NOACTIVATE
|
SWP_NOMOVE
);
}
else
if
(
nb_displayed
==
1
)
{
if
(
!
hide_systray
)
ShowWindow
(
tray_window
,
SW_SHOWNA
);
}
create_tooltip
(
icon
);
return
TRUE
;
}
/* make an icon invisible */
static
BOOL
hide_icon
(
struct
icon
*
icon
)
{
unsigned
int
i
;
WINE_TRACE
(
"id=0x%x, hwnd=%p
\n
"
,
icon
->
id
,
icon
->
owner
);
if
(
icon
->
display
==
-
1
)
return
TRUE
;
/* already hidden */
assert
(
nb_displayed
);
for
(
i
=
icon
->
display
;
i
<
nb_displayed
-
1
;
i
++
)
{
displayed
[
i
]
=
displayed
[
i
+
1
];
displayed
[
i
]
->
display
=
i
;
update_tooltip_position
(
displayed
[
i
]
);
}
nb_displayed
--
;
invalidate_icons
(
icon
->
display
,
nb_displayed
);
icon
->
display
=
-
1
;
if
(
nb_displayed
>=
MIN_DISPLAYED
)
{
SIZE
size
=
get_window_size
();
SetWindowPos
(
tray_window
,
0
,
0
,
0
,
size
.
cx
,
size
.
cy
,
SWP_NOZORDER
|
SWP_NOACTIVATE
|
SWP_NOMOVE
);
}
else
if
(
!
nb_displayed
)
{
ShowWindow
(
tray_window
,
SW_HIDE
);
}
update_tooltip_position
(
icon
);
return
TRUE
;
}
/* Modifies an existing icon record */
static
BOOL
modify_icon
(
NOTIFYICONDATAW
*
nid
)
static
BOOL
modify_icon
(
struct
icon
*
icon
,
NOTIFYICONDATAW
*
nid
)
{
struct
icon
*
icon
;
WINE_TRACE
(
"id=0x%x, hwnd=%p
\n
"
,
nid
->
uID
,
nid
->
hWnd
);
/* demarshal the request from the NID */
icon
=
get_icon
(
nid
->
hWnd
,
nid
->
uID
);
if
(
!
icon
)
{
WINE_WARN
(
"Invalid icon ID (0x%x) for HWND %p
\n
"
,
nid
->
uID
,
nid
->
hWnd
);
...
...
@@ -208,19 +264,16 @@ static BOOL modify_icon(NOTIFYICONDATAW *nid)
}
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
->
dwState
&
NIS_HIDDEN
)
hide_icon
(
icon
);
else
show_icon
(
icon
);
}
if
(
nid
->
uFlags
&
NIF_ICON
)
{
if
(
icon
->
image
)
DestroyIcon
(
icon
->
image
);
icon
->
image
=
CopyIcon
(
nid
->
hIcon
);
if
(
!
icon
->
hidden
)
RedrawWindow
(
icon
->
window
,
NULL
,
NULL
,
RDW_ERASE
|
RDW_INVALIDATE
|
RDW_UPDATENOW
);
if
(
icon
->
display
!=
-
1
)
invalidate_icons
(
icon
->
display
,
icon
->
display
);
}
if
(
nid
->
uFlags
&
NIF_MESSAGE
)
...
...
@@ -230,8 +283,7 @@ static BOOL modify_icon(NOTIFYICONDATAW *nid)
if
(
nid
->
uFlags
&
NIF_TIP
)
{
lstrcpynW
(
icon
->
tiptext
,
nid
->
szTip
,
sizeof
(
icon
->
tiptext
)
/
sizeof
(
WCHAR
));
if
(
!
icon
->
hidden
)
update_tooltip_text
(
icon
);
if
(
icon
->
display
!=
-
1
)
update_tooltip_text
(
icon
);
}
if
(
nid
->
uFlags
&
NIF_INFO
&&
nid
->
cbSize
>=
NOTIFYICONDATAA_V2_SIZE
)
{
...
...
@@ -262,46 +314,38 @@ static BOOL add_icon(NOTIFYICONDATAW *nid)
ZeroMemory
(
icon
,
sizeof
(
struct
icon
));
icon
->
id
=
nid
->
uID
;
icon
->
owner
=
nid
->
hWnd
;
icon
->
display
=
-
1
;
list_add_tail
(
&
tray
.
icons
,
&
icon
->
entry
);
list_add_tail
(
&
icon_list
,
&
icon
->
entry
);
/*
* 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
);
modify_icon
(
icon
,
nid
);
/* show icon, unless hidden state was explicitly specified */
if
(
!
((
nid
->
uFlags
&
NIF_STATE
)
&&
(
nid
->
dwStateMask
&
NIS_HIDDEN
)))
show_icon
(
icon
);
return
TRUE
;
}
/* Deletes tray icon window and icon record */
static
BOOL
delete_icon
_directly
(
struct
icon
*
icon
)
static
BOOL
delete_icon
(
struct
icon
*
icon
)
{
display_icon
(
icon
,
TRUE
);
hide_icon
(
icon
);
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
*
n
id
)
/*
cleanup icons belonging to windows that have been destroyed
*/
static
void
cleanup_destroyed_windows
(
vo
id
)
{
struct
icon
*
icon
=
get_icon
(
nid
->
hWnd
,
nid
->
uID
);
WINE_TRACE
(
"id=0x%x, hwnd=%p
\n
"
,
nid
->
uID
,
nid
->
hWnd
);
struct
icon
*
icon
,
*
next
;
if
(
!
icon
)
{
WINE_WARN
(
"invalid tray icon ID specified: %u
\n
"
,
nid
->
uID
);
return
FALSE
;
}
return
delete_icon_directly
(
icon
);
LIST_FOR_EACH_ENTRY_SAFE
(
icon
,
next
,
&
icon_list
,
struct
icon
,
entry
)
if
(
!
IsWindow
(
icon
->
owner
))
delete_icon
(
icon
);
}
static
BOOL
handle_incoming
(
HWND
hwndSource
,
COPYDATASTRUCT
*
cds
)
{
struct
icon
*
icon
=
NULL
;
NOTIFYICONDATAW
nid
;
DWORD
cbSize
;
BOOL
ret
=
FALSE
;
...
...
@@ -351,10 +395,14 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
buffer
,
buffer
+
cbMaskBits
);
}
if
(
wine_notify_icon
&&
wine_notify_icon
(
cds
->
dwData
,
&
nid
))
/* try forward to x11drv first */
if
(
cds
->
dwData
==
NIM_ADD
||
!
(
icon
=
get_icon
(
nid
.
hWnd
,
nid
.
uID
)))
{
if
(
nid
.
uFlags
&
NIF_ICON
)
DestroyIcon
(
nid
.
hIcon
);
return
TRUE
;
if
(
wine_notify_icon
&&
wine_notify_icon
(
cds
->
dwData
,
&
nid
))
{
if
(
nid
.
uFlags
&
NIF_ICON
)
DestroyIcon
(
nid
.
hIcon
);
return
TRUE
;
}
}
switch
(
cds
->
dwData
)
...
...
@@ -363,10 +411,10 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
ret
=
add_icon
(
&
nid
);
break
;
case
NIM_DELETE
:
ret
=
delete_icon
(
&
nid
);
if
(
icon
)
ret
=
delete_icon
(
icon
);
break
;
case
NIM_MODIFY
:
ret
=
modify_icon
(
&
nid
);
if
(
icon
)
ret
=
modify_icon
(
icon
,
&
nid
);
break
;
default:
WINE_FIXME
(
"unhandled tray message: %ld
\n
"
,
cds
->
dwData
);
...
...
@@ -381,86 +429,81 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
return
ret
;
}
static
LRESULT
WINAPI
listener_wndproc
(
HWND
window
,
UINT
msg
,
WPARAM
wparam
,
LPARAM
lparam
)
{
if
(
msg
==
WM_COPYDATA
)
return
handle_incoming
((
HWND
)
wparam
,
(
COPYDATASTRUCT
*
)
lparam
);
return
DefWindowProc
(
window
,
msg
,
wparam
,
lparam
);
}
static
LRESULT
WINAPI
adaptor_wndproc
(
HWND
window
,
UINT
msg
,
WPARAM
wparam
,
LPARAM
lparam
)
static
LRESULT
WINAPI
tray_wndproc
(
HWND
hwnd
,
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
);
case
WM_COPYDATA
:
return
handle_incoming
((
HWND
)
wparam
,
(
COPYDATASTRUCT
*
)
lparam
);
DrawIconEx
(
hdc
,
(
ICON_BORDER
/
2
),
top
,
icon
->
image
,
ICON_SIZE
,
ICON_SIZE
,
0
,
0
,
DI_DEFAULTSIZE
|
DI_NORMAL
);
case
WM_TIMER
:
cleanup_destroyed_windows
();
break
;
EndPaint
(
window
,
&
ps
);
case
WM_PAINT
:
{
unsigned
int
i
;
PAINTSTRUCT
ps
;
HDC
hdc
;
hdc
=
BeginPaint
(
hwnd
,
&
ps
);
for
(
i
=
ps
.
rcPaint
.
left
/
icon_cx
;
(
i
<
(
ps
.
rcPaint
.
right
+
icon_cx
-
1
)
/
icon_cx
)
&&
(
i
<
nb_displayed
);
i
++
)
{
DrawIconEx
(
hdc
,
i
*
icon_cx
+
ICON_BORDER
,
ICON_BORDER
,
displayed
[
i
]
->
image
,
icon_cx
-
2
*
ICON_BORDER
,
icon_cy
-
2
*
ICON_BORDER
,
0
,
0
,
DI_DEFAULTSIZE
|
DI_NORMAL
);
}
EndPaint
(
hwnd
,
&
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
:
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
:
{
MSG
message
;
struct
icon
*
icon
=
icon_from_point
(
(
short
)
LOWORD
(
lparam
),
(
short
)
HIWORD
(
lparam
)
);
if
(
!
icon
)
break
;
/* 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_WINDOW_HANDLE
))
message
.
hwnd
=
hwnd
;
message
.
message
=
msg
;
message
.
wParam
=
wparam
;
message
.
lParam
=
lparam
;
SendMessageW
(
icon
->
tooltip
,
TTM_RELAYEVENT
,
0
,
(
LPARAM
)
&
message
);
if
(
!
PostMessageW
(
icon
->
owner
,
icon
->
callback_message
,
(
WPARAM
)
icon
->
id
,
(
LPARAM
)
msg
)
&&
GetLastError
()
==
ERROR_INVALID_WINDOW_HANDLE
)
{
WINE_WARN
(
"application window was destroyed without removing "
"notification icon, removing automatically
\n
"
);
delete_icon
_directly
(
icon
);
delete_icon
(
icon
);
}
break
;
}
case
WM_NCDESTROY
:
SetWindowLongPtr
(
window
,
GWLP_USERDATA
,
0
);
break
;
case
WM_CLOSE
:
/* don't destroy the tray window, just hide it */
ShowWindow
(
hwnd
,
SW_HIDE
);
return
0
;
default:
return
DefWindowProc
(
window
,
msg
,
wparam
,
lparam
);
default:
return
DefWindowProcW
(
hwnd
,
msg
,
wparam
,
lparam
);
}
return
0
;
}
static
BOOL
is_systray_hidden
(
void
)
{
const
WCHAR
show_systray_keyname
[]
=
{
'S'
,
'o'
,
'f'
,
't'
,
'w'
,
'a'
,
'r'
,
'e'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
'\\'
,
...
...
@@ -487,24 +530,23 @@ static BOOL is_systray_hidden(void)
void
initialize_systray
(
void
)
{
HMODULE
x11drv
;
SIZE
size
;
WNDCLASSEX
class
;
static
const
WCHAR
classname
[]
=
/* Shell_TrayWnd */
{
'S'
,
'h'
,
'e'
,
'l'
,
'l'
,
'_'
,
'T'
,
'r'
,
'a'
,
'y'
,
'W'
,
'n'
,
'd'
,
0
};
static
const
WCHAR
winname
[]
=
/* Wine Systray Listener */
{
'W'
,
'i'
,
'n'
,
'e'
,
' '
,
'S'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
' '
,
'L'
,
'i'
,
's'
,
't'
,
'e'
,
'n'
,
'e'
,
'r'
,
0
};
WINE_TRACE
(
"initiaizing
\n
"
);
static
const
WCHAR
classname
[]
=
{
'S'
,
'h'
,
'e'
,
'l'
,
'l'
,
'_'
,
'T'
,
'r'
,
'a'
,
'y'
,
'W'
,
'n'
,
'd'
,
0
};
static
const
WCHAR
winname
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
' '
,
'S'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
' '
,
'T'
,
'r'
,
'a'
,
'y'
,
0
};
if
((
x11drv
=
GetModuleHandleA
(
"winex11.drv"
)))
wine_notify_icon
=
(
void
*
)
GetProcAddress
(
x11drv
,
"wine_notify_icon"
);
icon_cx
=
GetSystemMetrics
(
SM_CXSMICON
)
+
2
*
ICON_BORDER
;
icon_cy
=
GetSystemMetrics
(
SM_CYSMICON
)
+
2
*
ICON_BORDER
;
hide_systray
=
is_systray_hidden
();
list_init
(
&
tray
.
icons
);
/* register the systray listener window class */
ZeroMemory
(
&
class
,
sizeof
(
class
));
class
.
cbSize
=
sizeof
(
class
);
class
.
lpfnWndProc
=
&
listener_wndproc
;
class
.
style
=
CS_DBLCLKS
;
class
.
lpfnWndProc
=
tray_wndproc
;
class
.
hInstance
=
NULL
;
class
.
hIcon
=
LoadIcon
(
0
,
IDI_WINLOGO
);
class
.
hCursor
=
LoadCursor
(
0
,
IDC_ARROW
);
...
...
@@ -517,30 +559,13 @@ void initialize_systray(void)
return
;
}
/* now register the adaptor window class */
ZeroMemory
(
&
class
,
sizeof
(
class
));
class
.
cbSize
=
sizeof
(
class
);
class
.
lpfnWndProc
=
adaptor_wndproc
;
class
.
hInstance
=
NULL
;
class
.
hIcon
=
LoadIcon
(
0
,
IDI_WINLOGO
);
class
.
hCursor
=
LoadCursor
(
0
,
IDC_ARROW
);
class
.
hbrBackground
=
(
HBRUSH
)
COLOR_WINDOW
;
class
.
lpszClassName
=
adaptor_classname
;
class
.
style
=
CS_SAVEBITS
|
CS_DBLCLKS
;
if
(
!
RegisterClassEx
(
&
class
))
{
WINE_ERR
(
"Could not register adaptor class
\n
"
);
return
;
}
tray
.
window
=
CreateWindow
(
classname
,
winname
,
WS_OVERLAPPED
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
0
,
0
,
0
,
0
,
0
,
0
);
if
(
!
tray
.
window
)
size
=
get_window_size
();
tray_window
=
CreateWindowW
(
classname
,
winname
,
WS_OVERLAPPED
|
WS_CAPTION
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
size
.
cx
,
size
.
cy
,
0
,
0
,
0
,
0
);
if
(
!
tray_window
)
{
WINE_ERR
(
"Could not create tray window
\n
"
);
return
;
}
SetTimer
(
tray_window
,
1
,
2000
,
NULL
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment