madewokherd / wine-mono

Other
294 stars 39 forks source link

Tooltip stealing window focus #108

Closed IncubusRK closed 3 years ago

IncubusRK commented 3 years ago

In Windows Forms application tooltips steal focus from main window. It happens only in Wine-Mono. (It also can depend of windows manager version in Linux distro) To check error you can create any simple WinForms application with tooltip

Workarroud to prevent this is override function "CreateParams" and add WS_EX_NOACTIVATE style

Suggested fix: https://github.com/madewokherd/mono/blob/e51d7a840c2d998e28928dbbf6f37b59e3b9e799/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolTip.cs#L117 cp.ExStyle = (int)(WindowExStyles.WS_EX_TOOLWINDOW | WindowExStyles.WS_EX_TOPMOST | WindowExStyles.WS_EX_NOACTIVATE);

madewokherd commented 3 years ago

We don't use the System.Windows.Forms library from mono, so that shouldn't make any difference.

IncubusRK commented 3 years ago

Maybe fix must be here https://github.com/madewokherd/winforms/blob/2ccd830395e52bebf300e8a676e4f26db93c4b69/src/System.Windows.Forms/src/System/Windows/Forms/ToolTip.cs#L242

Fix on application side look like this https://sourceforge.net/p/autowikibrowser/code/11270/tree//AWB/WikiFunctions/Controls/AWBToolTip.cs

madewokherd commented 3 years ago

Could be. Does this work on .NET Framework?

Not that it matters, we should be able to do better than .NET Framework, but ideally we should do it in a way that's not visible to the application. We probably need winex11.drv's heuristic to treat the windows as unmanaged here: https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/winex11.drv/window.c#l227

Unfortunately, that seems to only account for window styles, so our options are limited.

madewokherd commented 3 years ago

It's not clear to me why that particular set of styles fixes it. This could use some more investigation to figure out why this doesn't work, and if it can be fixed without doing that.

Since this appears to be using the builtin tooltip class, I feel like winex11's heuristic should account for that, which would allow us to keep the styles the same and also fix this bug for .NET. (Or, if it works in .NET, I'd like to know why.)

madewokherd commented 3 years ago

My guess is that the builtin tooltip class should use ShowWindow or SetWindowPos flags that do not focus the window (SW_SHOWNA or SWP_NOACTIVATE), so that is_window_managed sees that in swp_flags and doesn't treat it as managed. This should be possible to test without involving wine-mono at all.

madewokherd commented 3 years ago

I made a quick test case

diff --git a/dlls/comctl32/tests/tooltips.c b/dlls/comctl32/tests/tooltips.c
index 639d51f7c28..7be7b2fdf82 100644
--- a/dlls/comctl32/tests/tooltips.c
+++ b/dlls/comctl32/tests/tooltips.c
@@ -1228,6 +1228,9 @@ static void test_TTN_SHOW(void)

     ok_sequence(sequences, PARENT_SEQ_INDEX, ttn_show_parent_seq, "TTN_SHOW parent seq", FALSE);

+    ok(GetForegroundWindow() != hwndTip, "got wrong foreground window\n");
+    ok(GetActiveWindow() != hwndTip, "got wrong active window\n");
+
     DestroyWindow(hwndTip);
     DestroyWindow(hwnd);
 }

This passes on Windows but fails on Wine. However, my theory on why it fails is incorrect, as SWP_NOACTIVATE is already correctly being passed to SetWindowPos when showing the tooltip. It seems WS_CAPTION gets implicitly set in the window style somehow during creation, and that causes Wine's heuristic to treat it as managed.

I'm going to move this over to the Wine Bugzilla as it does not appear to be specific to Wine Mono.

madewokherd commented 3 years ago

It seems there are already a few bugs filed that may have the same cause, so I'm not going to file a new one: https://bugs.winehq.org/show_bug.cgi?id=39547 https://bugs.winehq.org/show_bug.cgi?id=41062

I'll add the new information to bug 41062 for now.

madewokherd commented 3 years ago

Closing the issue here, we can track it on the Winehq bug.

IncubusRK commented 3 years ago

Ok, but native C++ MFC application haven't issues with tooltips

madewokherd commented 3 years ago

I went ahead and pushed a work-around anyway: https://github.com/madewokherd/wine-mono/commit/ac9e8ba1fe1c97d2ff35d7819c10e70917f7ecff

The Wine bug depends on the styles passed to CreateWindow, if MFC passes in WS_POPUP then it won't encounter this bug. On Windows, passing in WS_POPUP is not needed.

madewokherd commented 3 years ago

The work-around is in Wine Mono 6.4.0 which will be in Wine 6.18.