From: Dmitry Timoshkov dmitry@baikal.ru
Fixes https://bugs.winehq.org/show_bug.cgi?id=2155.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Changes from Staging patch: send message inside of SetFocus() handler instead of adding a new driver message.
dlls/winex11.drv/event.c | 30 ++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 2 ++ dlls/winex11.drv/x11drv_main.c | 1 + 3 files changed, 33 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index a0bfe05..873f0db 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -818,6 +818,8 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev )
if (!focus_win) { + x11drv_thread_data()->active_window = 0; + /* Abey : 6-Oct-99. Check again if the focus out window is the Foreground window, because in most cases the messages sent above must have already changed the foreground window, in which @@ -1380,6 +1382,7 @@ void wait_for_withdrawn_state( HWND hwnd, BOOL set ) */ void CDECL X11DRV_SetFocus( HWND hwnd ) { + struct x11drv_thread_data *thread_data = x11drv_thread_data(); struct x11drv_win_data *data;
HWND parent; @@ -1395,6 +1398,33 @@ void CDECL X11DRV_SetFocus( HWND hwnd ) } if (!data->managed || data->embedder) set_input_focus( data ); release_win_data( data ); + + if (data->mapped && data->managed && thread_data->active_window != hwnd) + { + struct x11drv_win_data *active = get_win_data( thread_data->active_window ); + DWORD timestamp = GetMessageTime() - EVENT_x11_time_to_win32_time( 0 ); + XEvent xev; + + TRACE("setting _NET_ACTIVE_WINDOW to %p/%lx, current active %p/%lx\n", + data->hwnd, data->whole_window, active ? active->hwnd : NULL, active ? active->whole_window : 0 ); + + xev.xclient.type = ClientMessage; + xev.xclient.window = data->whole_window; + xev.xclient.message_type = x11drv_atom(_NET_ACTIVE_WINDOW); + xev.xclient.serial = 0; + xev.xclient.display = data->display; + xev.xclient.send_event = True; + xev.xclient.format = 32; + + xev.xclient.data.l[0] = 1; /* source: application */ + xev.xclient.data.l[1] = timestamp; + xev.xclient.data.l[2] = active ? active->whole_window : 0; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + XSendEvent( data->display, root_window, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev ); + + if (active) release_win_data( active ); + } }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 85a05a9..3ad4ffe 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -325,6 +325,7 @@ struct x11drv_thread_data Display *display; XEvent *current_event; /* event currently being processed */ HWND grab_hwnd; /* window that currently grabs the mouse */ + HWND active_window; /* active window */ HWND last_focus; /* last window that had focus */ XIM xim; /* input method */ HWND last_xic_hwnd; /* last xic window */ @@ -433,6 +434,7 @@ enum x11drv_atoms XATOM_DndSelection, XATOM__ICC_PROFILE, XATOM__MOTIF_WM_HINTS, + XATOM__NET_ACTIVE_WINDOW, XATOM__NET_STARTUP_INFO_BEGIN, XATOM__NET_STARTUP_INFO, XATOM__NET_SUPPORTED, diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index e67a3c0..4654556 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -128,6 +128,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = "DndSelection", "_ICC_PROFILE", "_MOTIF_WM_HINTS", + "_NET_ACTIVE_WINDOW", "_NET_STARTUP_INFO_BEGIN", "_NET_STARTUP_INFO", "_NET_SUPPORTED",
Zebediah Figura zfigura@codeweavers.com wrote:
From: Dmitry Timoshkov dmitry@baikal.ru
Fixes https://bugs.winehq.org/show_bug.cgi?id=2155.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
Changes from Staging patch: send message inside of SetFocus() handler instead of adding a new driver message.
These changes broke the patch, test program attached to the bug 2155 enters an infinite loop (flickering windows constantly changing the focus) here with Mate as a WM.
On 05/30/2018 10:00 PM, Dmitry Timoshkov wrote:
Zebediah Figura zfigura@codeweavers.com wrote:
From: Dmitry Timoshkov dmitry@baikal.ru
Fixes https://bugs.winehq.org/show_bug.cgi?id=2155.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
Changes from Staging patch: send message inside of SetFocus() handler instead of adding a new driver message.
These changes broke the patch, test program attached to the bug 2155 enters an infinite loop (flickering windows constantly changing the focus) here with Mate as a WM.
Thanks, I've sent an updated version. Please let me know if the patch still breaks; it works here with Xfce4 and passes all of the user32 tests (or at least doesn't introduce any new failures).
Zebediah Figura zfigura@codeweavers.com wrote:
Changes from Staging patch: send message inside of SetFocus() handler instead of adding a new driver message.
These changes broke the patch, test program attached to the bug 2155 enters an infinite loop (flickering windows constantly changing the focus) here with Mate as a WM.
Thanks, I've sent an updated version. Please let me know if the patch still breaks; it works here with Xfce4 and passes all of the user32 tests (or at least doesn't introduce any new failures).
New version of the patch still doesn't work here, same flickering in an infinite loop until I move mouse over the test's window.
On 05/31/2018 09:40 AM, Dmitry Timoshkov wrote:
Zebediah Figura zfigura@codeweavers.com wrote:
Changes from Staging patch: send message inside of SetFocus() handler instead of adding a new driver message.
These changes broke the patch, test program attached to the bug 2155 enters an infinite loop (flickering windows constantly changing the focus) here with Mate as a WM.
Thanks, I've sent an updated version. Please let me know if the patch still breaks; it works here with Xfce4 and passes all of the user32 tests (or at least doesn't introduce any new failures).
New version of the patch still doesn't work here, same flickering in an infinite loop until I move mouse over the test's window.
Thanks. It looks like Marco sends a WM_TAKE_FOCUS message when honouring a request to become the active window. Since we call SetForegroundWindow() inside of our WM_TAKE_FOCUS handler, we generate a loop. This wouldn't be a problem, except that the application creates two windows in quick succession before processing events, and Marco generates one WM_TAKE_FOCUS message for each, so we essentially start out one WM_TAKE_FOCUS message behind the most recent one.
It's not clear to me what we should do about this; the spec doesn't seem to explicitly forbid any of this behaviour, but neither does it say we can depend on receiving WM_TAKE_FOCUS in response to a _NET_ACTIVE_WINDOW request. Could someone more knowledgeable about X11 provide input?
Zebediah Figura zfigura@codeweavers.com wrote:
New version of the patch still doesn't work here, same flickering in an infinite loop until I move mouse over the test's window.
Thanks. It looks like Marco sends a WM_TAKE_FOCUS message when honouring a request to become the active window. Since we call SetForegroundWindow() inside of our WM_TAKE_FOCUS handler, we generate a loop. This wouldn't be a problem, except that the application creates two windows in quick succession before processing events, and Marco generates one WM_TAKE_FOCUS message for each, so we essentially start out one WM_TAKE_FOCUS message behind the most recent one.
It's not clear to me what we should do about this; the spec doesn't seem to explicitly forbid any of this behaviour, but neither does it say we can depend on receiving WM_TAKE_FOCUS in response to a _NET_ACTIVE_WINDOW request. Could someone more knowledgeable about X11 provide input?
Does the original version of the patch work for you? What is the reason of the changes you've made in the staged patch?
On 05/31/2018 10:10 AM, Dmitry Timoshkov wrote:
Zebediah Figura zfigura@codeweavers.com wrote:
New version of the patch still doesn't work here, same flickering in an infinite loop until I move mouse over the test's window.
Thanks. It looks like Marco sends a WM_TAKE_FOCUS message when honouring a request to become the active window. Since we call SetForegroundWindow() inside of our WM_TAKE_FOCUS handler, we generate a loop. This wouldn't be a problem, except that the application creates two windows in quick succession before processing events, and Marco generates one WM_TAKE_FOCUS message for each, so we essentially start out one WM_TAKE_FOCUS message behind the most recent one.
It's not clear to me what we should do about this; the spec doesn't seem to explicitly forbid any of this behaviour, but neither does it say we can depend on receiving WM_TAKE_FOCUS in response to a _NET_ACTIVE_WINDOW request. Could someone more knowledgeable about X11 provide input?
Does the original version of the patch work for you? What is the reason of the changes you've made in the staged patch?
It seems unnecessary to add a new driver function for SetActiveWindow. All three focus functions have the effect of raising/activating the window in the same way that _NET_ACTIVE_WINDOW does, and the Mac driver already activates and raises windows in its SetFocus() handler.