From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 27 ++++++++++++++++++++++ dlls/winex11.drv/window.c | 47 +++++++++++++++++++++++++++++++++------ dlls/winex11.drv/x11drv.h | 4 ++++ 3 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 723f3204dd8..9385d2a2ec4 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1206,6 +1206,21 @@ static int get_window_xembed_info( Display *display, Window window ) return ret; }
+static void get_window_mwm_hints( Display *display, Window window, MwmHints *hints ) +{ + unsigned long count, remaining; + MwmHints *value; + int format; + Atom type; + + if (!XGetWindowProperty( display, window, x11drv_atom(_MOTIF_WM_HINTS), 0, 65535, False, x11drv_atom(_MOTIF_WM_HINTS), + &type, &format, &count, &remaining, (unsigned char **)&value )) + { + if (type == x11drv_atom(_MOTIF_WM_HINTS) && get_property_size( format, count ) >= sizeof(*value)) + *hints = *value; + XFree( value ); + } +}
/*********************************************************************** * handle_wm_state_notify @@ -1252,6 +1267,17 @@ static void handle_net_wm_state_notify( HWND hwnd, XPropertyEvent *event ) NtUserPostMessage( hwnd, WM_WINE_WINDOW_STATE_CHANGED, 0, 0 ); }
+static void handle_mwm_hints_notify( HWND hwnd, XPropertyEvent *event ) +{ + struct x11drv_win_data *data; + MwmHints hints = {0}; + + if (!(data = get_win_data( hwnd ))) return; + if (event->state == PropertyNewValue) get_window_mwm_hints( event->display, event->window, &hints ); + window_mwm_hints_notify( data, event->serial, &hints ); + release_win_data( data ); +} + static void handle_net_supported_notify( XPropertyEvent *event ) { struct x11drv_thread_data *data = x11drv_thread_data(); @@ -1286,6 +1312,7 @@ static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *xev ) if (event->atom == x11drv_atom(WM_STATE)) handle_wm_state_notify( hwnd, event ); if (event->atom == x11drv_atom(_XEMBED_INFO)) handle_xembed_info_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_WM_STATE)) handle_net_wm_state_notify( hwnd, event ); + if (event->atom == x11drv_atom(_MOTIF_WM_HINTS)) handle_mwm_hints_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_SUPPORTED)) handle_net_supported_notify( event ); if (event->atom == x11drv_atom(_NET_ACTIVE_WINDOW)) handle_net_active_window( event );
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 683c8037f9b..a5925fec96c 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -53,7 +53,6 @@
#include "wine/debug.h" #include "wine/server.h" -#include "mwm.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv); WINE_DECLARE_DEBUG_CHANNEL(systray); @@ -107,6 +106,11 @@ static const WCHAR clip_window_prop[] = static const WCHAR focus_time_prop[] = {'_','_','w','i','n','e','_','x','1','1','_','f','o','c','u','s','_','t','i','m','e',0};
+static const char *debugstr_mwm_hints( const MwmHints *hints ) +{ + return wine_dbg_sprintf( "%lx,%lx", hints->functions, hints->decorations ); +} + static pthread_mutex_t win_data_mutex = PTHREAD_MUTEX_INITIALIZER;
static void host_window_add_ref( struct host_window *win ) @@ -897,6 +901,23 @@ static void set_size_hints( struct x11drv_win_data *data, DWORD style ) }
+static void window_set_mwm_hints( struct x11drv_win_data *data, const MwmHints *new_hints ) +{ + const MwmHints *old_hints = &data->pending_state.mwm_hints; + + data->desired_state.mwm_hints = *new_hints; + if (!data->whole_window || !data->managed) return; /* no window or not managed, nothing to update */ + if (!memcmp( old_hints, new_hints, sizeof(*new_hints) )) return; /* hints are the same, nothing to update */ + + data->pending_state.mwm_hints = *new_hints; + data->mwm_hints_serial = NextRequest( data->display ); + TRACE( "window %p/%lx, requesting _MOTIF_WM_HINTS %s serial %lu\n", data->hwnd, data->whole_window, + debugstr_mwm_hints(&data->pending_state.mwm_hints), data->mwm_hints_serial ); + XChangeProperty( data->display, data->whole_window, x11drv_atom(_MOTIF_WM_HINTS), x11drv_atom(_MOTIF_WM_HINTS), + 32, PropModeReplace, (unsigned char *)new_hints, sizeof(*new_hints) / sizeof(long) ); +} + + /*********************************************************************** * set_mwm_hints */ @@ -934,15 +955,10 @@ static void set_mwm_hints( struct x11drv_win_data *data, UINT style, UINT ex_sty } }
- TRACE( "%p setting mwm hints to %lx,%lx (style %x exstyle %x)\n", - data->hwnd, mwm_hints.decorations, mwm_hints.functions, style, ex_style ); - mwm_hints.flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS; mwm_hints.input_mode = 0; mwm_hints.status = 0; - XChangeProperty( data->display, data->whole_window, x11drv_atom(_MOTIF_WM_HINTS), - x11drv_atom(_MOTIF_WM_HINTS), 32, PropModeReplace, - (unsigned char*)&mwm_hints, sizeof(mwm_hints)/sizeof(long) ); + window_set_mwm_hints( data, &mwm_hints ); }
@@ -1526,6 +1542,7 @@ static UINT window_update_client_state( struct x11drv_win_data *data )
if (data->wm_state_serial) return 0; /* another WM_STATE update is pending, wait for it to complete */ if (data->net_wm_state_serial) return 0; /* another _NET_WM_STATE update is pending, wait for it to complete */ + if (data->mwm_hints_serial) return 0; /* another MWM_HINT update is pending, wait for it to complete */ if (data->configure_serial) return 0; /* another config update is pending, wait for it to complete */
new_style = old_style & ~(WS_VISIBLE | WS_MINIMIZE | WS_MAXIMIZE); @@ -1573,6 +1590,7 @@ static UINT window_update_client_config( struct x11drv_win_data *data )
if (data->wm_state_serial) return 0; /* another WM_STATE update is pending, wait for it to complete */ if (data->net_wm_state_serial) return 0; /* another _NET_WM_STATE update is pending, wait for it to complete */ + if (data->mwm_hints_serial) return 0; /* another MWM_HINT update is pending, wait for it to complete */ if (data->configure_serial) return 0; /* another config update is pending, wait for it to complete */
if ((old_style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen) @@ -1720,6 +1738,20 @@ void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long ser window_set_config( data, &data->desired_state.rect, FALSE ); }
+void window_mwm_hints_notify( struct x11drv_win_data *data, unsigned long serial, const MwmHints *value ) +{ + MwmHints *desired = &data->desired_state.mwm_hints, *pending = &data->pending_state.mwm_hints, *current = &data->current_state.mwm_hints; + unsigned long *expect_serial = &data->mwm_hints_serial; + const char *expected, *received, *prefix; + + prefix = wine_dbg_sprintf( "window %p/%lx ", data->hwnd, data->whole_window ); + received = wine_dbg_sprintf( "_MOTIF_WM_HINTS %s/%lu", debugstr_mwm_hints(value), serial ); + expected = *expect_serial ? wine_dbg_sprintf( ", expected %s/%lu", debugstr_mwm_hints(pending), *expect_serial ) : ""; + + handle_state_change( serial, expect_serial, sizeof(*value), value, desired, pending, + current, expected, prefix, received, NULL ); +} + void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *value ) { RECT *desired = &data->desired_state.rect, *pending = &data->pending_state.rect, *current = &data->current_state.rect; @@ -2274,6 +2306,7 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des memset( &data->current_state, 0, sizeof(data->current_state) ); data->wm_state_serial = 0; data->net_wm_state_serial = 0; + data->mwm_hints_serial = 0; data->configure_serial = 0;
if (data->xic) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 4cd2c7fa48f..61567c7319e 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -67,6 +67,7 @@ typedef int Status; #include "unixlib.h" #include "wine/list.h" #include "wine/debug.h" +#include "mwm.h"
#define MAX_DASHLEN 16
@@ -623,6 +624,7 @@ struct window_state UINT wm_state; BOOL activate; UINT net_wm_state; + MwmHints mwm_hints; RECT rect; };
@@ -660,6 +662,7 @@ struct x11drv_win_data struct window_state current_state; /* window state tracking the current X11 state */ unsigned long wm_state_serial; /* serial of last pending WM_STATE request */ unsigned long net_wm_state_serial; /* serial of last pending _NET_WM_STATE request */ + unsigned long mwm_hints_serial; /* serial of last pending _MOTIF_WM_HINTS request */ unsigned long configure_serial; /* serial of last pending configure request */ };
@@ -678,6 +681,7 @@ extern BOOL window_should_take_focus( HWND hwnd, Time time ); extern BOOL window_has_pending_wm_state( HWND hwnd, UINT state ); extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value, Time time ); extern void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ); +extern void window_mwm_hints_notify( struct x11drv_win_data *data, unsigned long serial, const MwmHints *hints ); extern void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *rect );
extern void set_net_active_window( HWND hwnd, HWND previous );