[1/3] winex11: Splitted functions X11DRV_FocusOut (try 2)

Sebastian Lackner sebastian at fds-team.de
Mon Sep 23 12:39:59 CDT 2013


Summary:
This patch adds XEmbed client support as described in the corresponding
protocol specification. This allows external applications to re-parent a
wine window inside any X11 window with proper event handling. The code
has been developed as part of the Pipelight project, which allows to
embed (for example) Silverlight directly into the native Linux browser.


Changelog (try 2):
* Cleaned up style issues
* Splitted some functions to make it possible to reuse existing code
* Added XEMBED_FOCUS_IN event


Design decisions, which should make clear why it is implemented in
exactly this way: Currently it is not possible to reuse the
make_window_embedded or X11DRV_ReparentNotify code:

  - most browsers/window managers don't remap the window - the
specification only states that they should unmap it as soon as the
xembed flag is removed, which would happen immediately afterwards, when
calling make_window_embedded

  - when "virtually" reparenting the plugin window as a child of a
"foreign" window (similar to the systray code) its not possible to get
the focus anymore - the focus code always tries to request the focus for
the WS_POPUP parent, which is a foreign window in this case, and thus
fails. I don't see an easy way to detect/handle if a window is embedded
from user32-code without changing a lot of stuff there - thats why
Pipelight creates the plugin window as a WS_POPUP and makes wine think
it doesn't have any parent (which only has the disadvantage that wine
cannot track the correct window position).

  - Its better to handle XEMBED_WINDOW_DEACTIVATE the same way as
XEMBED_FOCUS_OUT, as (cite)"no XEMBED_FOCUS_IN or XEMBED_FOCUS_OUT
messages should be sent when the toplevel window gains or loses focus" -
without handling this event too it would be possible that the wine
application still thinks it has the focus, even if the toplevel window
has been deactivated.


The protocol specification can be seen for example here:
http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html

Please note that this is still a bit tricky for several reasons:
* The wine application cannot do the re-parent itself, but instead an
other application has to do that.
* This patch doesn't implement all possible XEMBED_* messages, but only
a minimal set which is required to get the event handling working
appropriately. TAB chain handling or accelerator support for example is
still missing.

---
 dlls/winex11.drv/event.c |   44
++++++++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 18 deletions(-)



-------------- next part --------------
From e6b780a76df21554bea9ae2ffdac408042810ed7 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian at fds-team.de>
Date: Sun, 22 Sep 2013 02:18:29 +0200
Subject: winex11: Splitted functions X11DRV_FocusOut

---
 dlls/winex11.drv/event.c |   44 ++++++++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 5e5b19e..0942ae7 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -748,34 +748,22 @@ static void X11DRV_FocusIn( HWND hwnd, XEvent *xev )
     else SetForegroundWindow( hwnd );
 }
 
-
 /**********************************************************************
- *              X11DRV_FocusOut
- *
- * Note: only top-level windows get FocusOut events.
+ *              focus_out
  */
-static void X11DRV_FocusOut( HWND hwnd, XEvent *xev )
-{
-    XFocusChangeEvent *event = &xev->xfocus;
+ static void focus_out( Display *display , HWND hwnd )
+ {
     HWND hwnd_tmp;
     Window focus_win;
     int revert;
     XIC xic;
 
-    TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
-
-    if (event->detail == NotifyPointer)
-    {
-        if (!hwnd && event->window == x11drv_thread_data()->clip_window) reset_clipping_window();
-        return;
-    }
-    if (!hwnd) return;
     if (ximInComposeMode) return;
 
     x11drv_thread_data()->last_focus = hwnd;
     if ((xic = X11DRV_get_ic( hwnd ))) XUnsetICFocus( xic );
 
-    if (root_window != DefaultRootWindow(event->display))
+    if (root_window != DefaultRootWindow(display))
     {
         if (hwnd == GetDesktopWindow()) reset_clipping_window();
         return;
@@ -786,10 +774,10 @@ static void X11DRV_FocusOut( HWND hwnd, XEvent *xev )
     /* don't reset the foreground window, if the window which is
        getting the focus is a Wine window */
 
-    XGetInputFocus( event->display, &focus_win, &revert );
+    XGetInputFocus( display, &focus_win, &revert );
     if (focus_win)
     {
-        if (XFindContext( event->display, focus_win, winContext, (char **)&hwnd_tmp ) != 0)
+        if (XFindContext( display, focus_win, winContext, (char **)&hwnd_tmp ) != 0)
             focus_win = 0;
     }
 
@@ -805,6 +793,26 @@ static void X11DRV_FocusOut( HWND hwnd, XEvent *xev )
             SetForegroundWindow( GetDesktopWindow() );
         }
     }
+ }
+
+/**********************************************************************
+ *              X11DRV_FocusOut
+ *
+ * Note: only top-level windows get FocusOut events.
+ */
+static void X11DRV_FocusOut( HWND hwnd, XEvent *xev )
+{
+    XFocusChangeEvent *event = &xev->xfocus;
+
+    TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
+
+    if (event->detail == NotifyPointer)
+    {
+        if (!hwnd && event->window == x11drv_thread_data()->clip_window) reset_clipping_window();
+        return;
+    }
+    if (!hwnd) return;
+    focus_out( event->display, hwnd );
 }
 
 
-- 
1.7.9.5


More information about the wine-patches mailing list