From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 27 +++++++++++++++++++++++ dlls/winex11.drv/window.c | 45 +++++++++++++++++++++++++++++++++------ dlls/winex11.drv/x11drv.h | 4 ++++ 3 files changed, 69 insertions(+), 7 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 3a57e3ea256..6df35c7f397 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1218,6 +1218,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 @@ -1261,6 +1276,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(); @@ -1287,6 +1313,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 );
return TRUE; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index a6a887e5862..49785b9a416 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); @@ -111,6 +110,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 ) @@ -887,6 +891,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) return; /* no window, 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 */ @@ -921,15 +942,12 @@ 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) ); + TRACE( "%p setting mwm hints to %s (style %x exstyle %x)\n", + data->hwnd, debugstr_mwm_hints(&mwm_hints), style, ex_style ); + window_set_mwm_hints( data, &mwm_hints ); }
@@ -1684,6 +1702,19 @@ 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; + + 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( data, serial, expect_serial, sizeof(*value), value, + desired, pending, current, expected, 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; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9cd471d547a..5c5607dfccd 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
@@ -610,6 +611,7 @@ struct window_state { UINT wm_state; UINT net_wm_state; + MwmHints mwm_hints; RECT rect; };
@@ -647,6 +649,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 */ };
@@ -665,6 +668,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 BOOL get_window_state_updates( HWND hwnd, UINT *state_cmd, UINT *config_cmd, RECT *rect );