winex11: Use unixlib interface for systray docking.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e41630612b
commit
21d269f2fc
|
@ -157,6 +157,7 @@ static const kernel_callback kernel_callbacks[] =
|
|||
x11drv_dnd_post_drop,
|
||||
x11drv_ime_set_composition_string,
|
||||
x11drv_ime_set_result,
|
||||
x11drv_systray_change_owner,
|
||||
};
|
||||
|
||||
C_ASSERT( NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == client_func_last );
|
||||
|
|
|
@ -621,8 +621,16 @@ static void set_focus( Display *display, HWND hwnd, Time time )
|
|||
static void handle_manager_message( HWND hwnd, XClientMessageEvent *event )
|
||||
{
|
||||
if (hwnd != NtUserGetDesktopWindow()) return;
|
||||
|
||||
if (systray_atom && event->data.l[1] == systray_atom)
|
||||
change_systray_owner( event->display, event->data.l[2] );
|
||||
{
|
||||
struct systray_change_owner_params params;
|
||||
|
||||
TRACE( "new owner %lx\n", event->data.l[2] );
|
||||
|
||||
params.event_handle = (UINT_PTR)event;
|
||||
x11drv_client_func( client_func_systray_change_owner, ¶ms, sizeof(params) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -75,12 +75,6 @@ static BOOL show_icon( struct tray_icon *icon );
|
|||
static BOOL hide_icon( struct tray_icon *icon );
|
||||
static BOOL delete_icon( struct tray_icon *icon );
|
||||
|
||||
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
||||
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
|
||||
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
|
||||
|
||||
Atom systray_atom = 0;
|
||||
|
||||
#define MIN_DISPLAYED 8
|
||||
#define ICON_BORDER 2
|
||||
|
||||
|
@ -550,39 +544,6 @@ static LRESULT WINAPI tray_icon_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPAR
|
|||
return DefWindowProcW( hwnd, msg, wparam, lparam );
|
||||
}
|
||||
|
||||
/* find the X11 window owner the system tray selection */
|
||||
static Window get_systray_selection_owner( Display *display )
|
||||
{
|
||||
return XGetSelectionOwner( display, systray_atom );
|
||||
}
|
||||
|
||||
static void get_systray_visual_info( Display *display, Window systray_window, XVisualInfo *info )
|
||||
{
|
||||
XVisualInfo *list, template;
|
||||
VisualID *visual_id;
|
||||
Atom type;
|
||||
int format, num;
|
||||
unsigned long count, remaining;
|
||||
|
||||
*info = default_visual;
|
||||
if (XGetWindowProperty( display, systray_window, x11drv_atom(_NET_SYSTEM_TRAY_VISUAL), 0,
|
||||
65536/sizeof(CARD32), False, XA_VISUALID, &type, &format, &count,
|
||||
&remaining, (unsigned char **)&visual_id ))
|
||||
return;
|
||||
|
||||
if (type == XA_VISUALID && format == 32)
|
||||
{
|
||||
template.visualid = visual_id[0];
|
||||
if ((list = XGetVisualInfo( display, VisualIDMask, &template, &num )))
|
||||
{
|
||||
*info = list[0];
|
||||
TRACE( "systray window %lx got visual %lx\n", systray_window, info->visualid );
|
||||
XFree( list );
|
||||
}
|
||||
}
|
||||
XFree( visual_id );
|
||||
}
|
||||
|
||||
static BOOL init_systray(void)
|
||||
{
|
||||
static BOOL init_done;
|
||||
|
@ -627,66 +588,27 @@ static BOOL init_systray(void)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* dock the given icon with the NETWM system tray */
|
||||
static void dock_systray_icon( Display *display, struct tray_icon *icon, Window systray_window )
|
||||
{
|
||||
Window window;
|
||||
XEvent ev;
|
||||
XSetWindowAttributes attr;
|
||||
XVisualInfo visual;
|
||||
struct x11drv_win_data *data;
|
||||
|
||||
get_systray_visual_info( display, systray_window, &visual );
|
||||
|
||||
icon->layered = (visual.depth == 32);
|
||||
CreateWindowExW( icon->layered ? WS_EX_LAYERED : 0,
|
||||
icon_classname, NULL, WS_CLIPSIBLINGS | WS_POPUP,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, icon_cx, icon_cy,
|
||||
NULL, NULL, NULL, icon );
|
||||
|
||||
if (!(data = get_win_data( icon->window ))) return;
|
||||
if (icon->layered) set_window_visual( data, &visual, TRUE );
|
||||
make_window_embedded( data );
|
||||
window = data->whole_window;
|
||||
release_win_data( data );
|
||||
|
||||
ShowWindow( icon->window, SW_SHOWNA );
|
||||
|
||||
TRACE( "icon window %p/%lx\n", icon->window, window );
|
||||
|
||||
/* send the docking request message */
|
||||
ev.xclient.type = ClientMessage;
|
||||
ev.xclient.window = systray_window;
|
||||
ev.xclient.message_type = x11drv_atom( _NET_SYSTEM_TRAY_OPCODE );
|
||||
ev.xclient.format = 32;
|
||||
ev.xclient.data.l[0] = CurrentTime;
|
||||
ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
|
||||
ev.xclient.data.l[2] = window;
|
||||
ev.xclient.data.l[3] = 0;
|
||||
ev.xclient.data.l[4] = 0;
|
||||
XSendEvent( display, systray_window, False, NoEventMask, &ev );
|
||||
|
||||
if (!icon->layered)
|
||||
{
|
||||
attr.background_pixmap = ParentRelative;
|
||||
attr.bit_gravity = ForgetGravity;
|
||||
XChangeWindowAttributes( display, window, CWBackPixmap | CWBitGravity, &attr );
|
||||
}
|
||||
else repaint_tray_icon( icon );
|
||||
}
|
||||
|
||||
/* dock systray windows again with the new owner */
|
||||
void change_systray_owner( Display *display, Window systray_window )
|
||||
NTSTATUS WINAPI x11drv_systray_change_owner( void *arg, ULONG size )
|
||||
{
|
||||
struct systray_change_owner_params *params = arg;
|
||||
struct systray_dock_params dock_params;
|
||||
struct tray_icon *icon;
|
||||
|
||||
TRACE( "new owner %lx\n", systray_window );
|
||||
LIST_FOR_EACH_ENTRY( icon, &icon_list, struct tray_icon, entry )
|
||||
{
|
||||
if (icon->display == -1) continue;
|
||||
hide_icon( icon );
|
||||
dock_systray_icon( display, icon, systray_window );
|
||||
|
||||
dock_params.event_handle = params->event_handle;
|
||||
dock_params.icon = icon;
|
||||
dock_params.cx = icon_cx;
|
||||
dock_params.cy = icon_cy;
|
||||
dock_params.layered = &icon->layered;
|
||||
X11DRV_CALL( systray_dock, &dock_params );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hide a tray icon */
|
||||
|
@ -710,16 +632,19 @@ static BOOL hide_icon( struct tray_icon *icon )
|
|||
/* make the icon visible */
|
||||
static BOOL show_icon( struct tray_icon *icon )
|
||||
{
|
||||
Window systray_window;
|
||||
Display *display = thread_init_display();
|
||||
|
||||
TRACE( "id=0x%x, hwnd=%p\n", icon->id, icon->owner );
|
||||
struct systray_dock_params params;
|
||||
|
||||
if (icon->window) return TRUE; /* already shown */
|
||||
|
||||
if ((systray_window = get_systray_selection_owner( display )))
|
||||
dock_systray_icon( display, icon, systray_window );
|
||||
else
|
||||
TRACE( "id=0x%x, hwnd=%p\n", icon->id, icon->owner );
|
||||
|
||||
params.event_handle = 0;
|
||||
params.icon = icon;
|
||||
params.cx = icon_cx;
|
||||
params.cy = icon_cy;
|
||||
params.layered = &icon->layered;
|
||||
|
||||
if (X11DRV_CALL( systray_dock, ¶ms ))
|
||||
add_to_standalone_tray( icon );
|
||||
|
||||
update_balloon( icon );
|
||||
|
|
|
@ -25,6 +25,7 @@ enum x11drv_funcs
|
|||
unix_create_desktop,
|
||||
unix_init,
|
||||
unix_systray_clear,
|
||||
unix_systray_dock,
|
||||
unix_systray_hide,
|
||||
unix_systray_init,
|
||||
unix_tablet_attach_queue,
|
||||
|
@ -56,6 +57,15 @@ struct create_desktop_params
|
|||
UINT height;
|
||||
};
|
||||
|
||||
struct systray_dock_params
|
||||
{
|
||||
UINT64 event_handle;
|
||||
void *icon;
|
||||
int cx;
|
||||
int cy;
|
||||
BOOL *layered;
|
||||
};
|
||||
|
||||
/* x11drv_tablet_info params */
|
||||
struct tablet_info_params
|
||||
{
|
||||
|
@ -80,6 +90,7 @@ enum x11drv_client_funcs
|
|||
client_func_dnd_post_drop,
|
||||
client_func_ime_set_composition_string,
|
||||
client_func_ime_set_result,
|
||||
client_func_systray_change_owner,
|
||||
client_func_last
|
||||
};
|
||||
|
||||
|
@ -121,3 +132,8 @@ struct dnd_position_event_params
|
|||
POINT point;
|
||||
DWORD effect;
|
||||
};
|
||||
|
||||
struct systray_change_owner_params
|
||||
{
|
||||
UINT64 event_handle;
|
||||
};
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "mwm.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(systray);
|
||||
|
||||
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
|
||||
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
|
||||
|
@ -70,6 +71,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
|
|||
#define _NET_WM_STATE_ADD 1
|
||||
#define _NET_WM_STATE_TOGGLE 2
|
||||
|
||||
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
||||
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
|
||||
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
|
||||
|
||||
static const unsigned int net_wm_state_atoms[NB_NET_WM_STATES] =
|
||||
{
|
||||
XATOM__NET_WM_STATE_FULLSCREEN,
|
||||
|
@ -2138,6 +2143,115 @@ NTSTATUS x11drv_systray_hide( void *arg )
|
|||
}
|
||||
|
||||
|
||||
/* find the X11 window owner the system tray selection */
|
||||
static Window get_systray_selection_owner( Display *display )
|
||||
{
|
||||
return XGetSelectionOwner( display, systray_atom );
|
||||
}
|
||||
|
||||
|
||||
static void get_systray_visual_info( Display *display, Window systray_window, XVisualInfo *info )
|
||||
{
|
||||
XVisualInfo *list, template;
|
||||
VisualID *visual_id;
|
||||
Atom type;
|
||||
int format, num;
|
||||
unsigned long count, remaining;
|
||||
|
||||
*info = default_visual;
|
||||
if (XGetWindowProperty( display, systray_window, x11drv_atom(_NET_SYSTEM_TRAY_VISUAL), 0,
|
||||
65536/sizeof(CARD32), False, XA_VISUALID, &type, &format, &count,
|
||||
&remaining, (unsigned char **)&visual_id ))
|
||||
return;
|
||||
|
||||
if (type == XA_VISUALID && format == 32)
|
||||
{
|
||||
template.visualid = visual_id[0];
|
||||
if ((list = XGetVisualInfo( display, VisualIDMask, &template, &num )))
|
||||
{
|
||||
*info = list[0];
|
||||
TRACE_(systray)( "systray window %lx got visual %lx\n", systray_window, info->visualid );
|
||||
XFree( list );
|
||||
}
|
||||
}
|
||||
XFree( visual_id );
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS x11drv_systray_dock( void *arg )
|
||||
{
|
||||
struct systray_dock_params *params = arg;
|
||||
Window systray_window, window;
|
||||
Display *display;
|
||||
XEvent ev;
|
||||
XSetWindowAttributes attr;
|
||||
XVisualInfo visual;
|
||||
struct x11drv_win_data *data;
|
||||
BOOL layered;
|
||||
HWND hwnd;
|
||||
|
||||
static const WCHAR icon_classname[] =
|
||||
{'_','_','w','i','n','e','x','1','1','_','t','r','a','y','_','i','c','o','n',0};
|
||||
|
||||
if (params->event_handle)
|
||||
{
|
||||
XClientMessageEvent *event = (XClientMessageEvent *)(UINT_PTR)params->event_handle;
|
||||
display = event->display;
|
||||
systray_window = event->data.l[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
display = thread_init_display();
|
||||
if (!(systray_window = get_systray_selection_owner( display ))) return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
get_systray_visual_info( display, systray_window, &visual );
|
||||
|
||||
*params->layered = layered = (visual.depth == 32);
|
||||
|
||||
hwnd = CreateWindowExW( layered ? WS_EX_LAYERED : 0,
|
||||
icon_classname, NULL, WS_CLIPSIBLINGS | WS_POPUP,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, params->cx, params->cy,
|
||||
NULL, NULL, NULL, params->icon );
|
||||
|
||||
if (!(data = get_win_data( hwnd ))) return STATUS_UNSUCCESSFUL;
|
||||
if (layered) set_window_visual( data, &visual, TRUE );
|
||||
make_window_embedded( data );
|
||||
window = data->whole_window;
|
||||
release_win_data( data );
|
||||
|
||||
NtUserShowWindow( hwnd, SW_SHOWNA );
|
||||
|
||||
TRACE_(systray)( "icon window %p/%lx\n", hwnd, window );
|
||||
|
||||
/* send the docking request message */
|
||||
ev.xclient.type = ClientMessage;
|
||||
ev.xclient.window = systray_window;
|
||||
ev.xclient.message_type = x11drv_atom( _NET_SYSTEM_TRAY_OPCODE );
|
||||
ev.xclient.format = 32;
|
||||
ev.xclient.data.l[0] = CurrentTime;
|
||||
ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
|
||||
ev.xclient.data.l[2] = window;
|
||||
ev.xclient.data.l[3] = 0;
|
||||
ev.xclient.data.l[4] = 0;
|
||||
XSendEvent( display, systray_window, False, NoEventMask, &ev );
|
||||
|
||||
if (!layered)
|
||||
{
|
||||
attr.background_pixmap = ParentRelative;
|
||||
attr.bit_gravity = ForgetGravity;
|
||||
XChangeWindowAttributes( display, window, CWBackPixmap | CWBitGravity, &attr );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* force repainig */
|
||||
send_message( hwnd, WM_SIZE, SIZE_RESTORED, MAKELONG( params->cx, params->cy ));
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* X11DRV_get_whole_window
|
||||
*
|
||||
|
|
|
@ -828,6 +828,7 @@ static inline BOOL is_window_rect_mapped( const RECT *rect )
|
|||
extern NTSTATUS x11drv_clipboard_message( void *arg ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS x11drv_create_desktop( void *arg ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS x11drv_systray_clear( void *arg ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS x11drv_systray_dock( void *arg ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS x11drv_systray_hide( void *arg ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS x11drv_systray_init( void *arg ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS x11drv_tablet_attach_queue( void *arg ) DECLSPEC_HIDDEN;
|
||||
|
@ -842,6 +843,7 @@ extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DEC
|
|||
extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS WINAPI x11drv_ime_set_composition_string( void *params, ULONG size ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG size ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -60,6 +60,7 @@ XVisualInfo default_visual = { 0 };
|
|||
XVisualInfo argb_visual = { 0 };
|
||||
Colormap default_colormap = None;
|
||||
XPixmapFormatValues **pixmap_formats;
|
||||
Atom systray_atom = 0;
|
||||
unsigned int screen_bpp;
|
||||
Window root_window;
|
||||
BOOL usexvidmode = TRUE;
|
||||
|
@ -978,6 +979,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
|
|||
x11drv_create_desktop,
|
||||
x11drv_init,
|
||||
x11drv_systray_clear,
|
||||
x11drv_systray_dock,
|
||||
x11drv_systray_hide,
|
||||
x11drv_systray_init,
|
||||
x11drv_tablet_attach_queue,
|
||||
|
|
Loading…
Reference in New Issue