[3/5] winex11: Send XEMBED_REQUEST_FOCUS request for embedded windows

Sebastian Lackner sebastian at fds-team.de
Tue Sep 24 17:59:49 CDT 2013


---
 dlls/winex11.drv/event.c  |   73
++++++++++++++++++++++++++++++++-------------
 dlls/winex11.drv/window.c |   16 ++++++++++
 dlls/winex11.drv/x11drv.h |    1 +
 3 files changed, 70 insertions(+), 20 deletions(-)

-------------- next part --------------
From cf58839244e15b487688c85f4b78aa81a6d2e713 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian at fds-team.de>
Date: Tue, 24 Sep 2013 20:35:38 +0200
Subject: winex11: Send XEMBED_REQUEST_FOCUS request for embedded windows

---
 dlls/winex11.drv/event.c  |   73 ++++++++++++++++++++++++++++++++-------------
 dlls/winex11.drv/window.c |   16 ++++++++++
 dlls/winex11.drv/x11drv.h |    1 +
 3 files changed, 70 insertions(+), 20 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 4dcdd68..93892e5 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -182,6 +182,32 @@ static inline void free_event_data( XEvent *event )
 #endif
 }
 
+
+/***********************************************************************
+ *           xembed_request_focus
+ */
+static void xembed_request_focus( Display *display, Window window, DWORD timestamp )
+{
+    XEvent xev;
+
+    xev.xclient.type = ClientMessage;
+    xev.xclient.window = window;
+    xev.xclient.message_type = x11drv_atom(_XEMBED);
+    xev.xclient.serial = 0;
+    xev.xclient.display = display;
+    xev.xclient.send_event = True;
+    xev.xclient.format = 32;
+
+    xev.xclient.data.l[0] = timestamp;
+    xev.xclient.data.l[1] = XEMBED_REQUEST_FOCUS;
+    xev.xclient.data.l[2] = 0;
+    xev.xclient.data.l[3] = 0;
+    xev.xclient.data.l[4] = 0;
+
+    XSendEvent(display, window, False, NoEventMask, &xev);
+    XSync(display, False);
+}
+
 /***********************************************************************
  *           X11DRV_register_event_handler
  *
@@ -532,26 +558,37 @@ static inline BOOL can_activate_window( HWND hwnd )
 /**********************************************************************
  *              set_input_focus
  *
- * Try to force focus for non-managed windows.
+ * Try to force focus for embedded or non-managed windows.
  */
-static void set_input_focus( Display *display, Window window )
+static void set_input_focus( HWND hwnd )
 {
     XWindowChanges changes;
     DWORD timestamp;
+    struct x11drv_win_data *data;
+    if (!(data = get_win_data( hwnd ))) return;
 
-    if (!window) return;
+    if (data->whole_window && (data->embedder || !data->managed))
+    {
 
-    if (EVENT_x11_time_to_win32_time(0))
-        /* ICCCM says don't use CurrentTime, so try to use last message time if possible */
-        /* FIXME: this is not entirely correct */
-        timestamp = GetMessageTime() - EVENT_x11_time_to_win32_time(0);
-    else
-        timestamp = CurrentTime;
+        if (EVENT_x11_time_to_win32_time(0))
+            /* ICCCM says don't use CurrentTime, so try to use last message time if possible */
+            /* FIXME: this is not entirely correct */
+            timestamp = GetMessageTime() - EVENT_x11_time_to_win32_time(0);
+        else
+            timestamp = CurrentTime;
 
-    /* Set X focus and install colormap */
-    changes.stack_mode = Above;
-    XConfigureWindow( display, window, CWStackMode, &changes );
-    XSetInputFocus( display, window, RevertToParent, timestamp );
+        /* Set X focus and install colormap */
+        changes.stack_mode = Above;
+        XConfigureWindow( data->display, data->whole_window, CWStackMode, &changes );
+
+        if (data->embedder)
+            xembed_request_focus( data->display, data->embedder, timestamp );
+        else
+            XSetInputFocus( data->display, data->whole_window, RevertToParent, timestamp );
+
+    }
+
+    release_win_data( data );
 }
 
 /**********************************************************************
@@ -899,7 +936,7 @@ static void X11DRV_MapNotify( HWND hwnd, XEvent *event )
     {
         HWND hwndFocus = GetFocus();
         if (hwndFocus && IsChild( hwnd, hwndFocus ))
-            set_input_focus( data->display, data->whole_window );
+            set_input_focus( hwnd );
     }
     release_win_data( data );
 }
@@ -1350,12 +1387,8 @@ void wait_for_withdrawn_state( HWND hwnd, BOOL set )
  */
 void CDECL X11DRV_SetFocus( HWND hwnd )
 {
-    struct x11drv_win_data *data;
-
-    if (!(hwnd = GetAncestor( hwnd, GA_ROOT ))) return;
-    if (!(data = get_win_data( hwnd ))) return;
-    if (!data->managed) set_input_focus( data->display, data->whole_window );
-    release_win_data( data );
+    if (!(hwnd = get_ancestor_root_embedded( hwnd ))) return;
+    set_input_focus( hwnd );
 }
 
 
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 1ff36eb..0c7b55f 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1139,6 +1139,22 @@ void make_window_embedded( struct x11drv_win_data *data )
     set_xembed_flags( data, data->mapped ? XEMBED_MAPPED : 0 );
 }
 
+/***********************************************************************
+ *     get_ancestor_root_embedded
+ */
+HWND get_ancestor_root_embedded( HWND hwnd )
+{
+    HWND parent;
+    if (!hwnd) return NULL;
+    for (;;)
+    {
+        parent = GetAncestor(hwnd, GA_PARENT);
+        if (!parent || parent == GetDesktopWindow() || (Window)GetPropA( parent, foreign_window_prop ))
+            break;
+        hwnd = parent;
+    }
+    return hwnd;
+}
 
 /***********************************************************************
  *		X11DRV_window_to_X_rect
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index bfcea89..8920adc 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -585,6 +585,7 @@ extern Window init_clip_window(void) DECLSPEC_HIDDEN;
 extern void update_user_time( Time time ) DECLSPEC_HIDDEN;
 extern void update_net_wm_states( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
 extern void make_window_embedded( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
+extern HWND get_ancestor_root_embedded( HWND hwnd ) DECLSPEC_HIDDEN;
 extern Window create_client_window( struct x11drv_win_data *data, const XVisualInfo *visual ) DECLSPEC_HIDDEN;
 extern void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis ) DECLSPEC_HIDDEN;
 extern void change_systray_owner( Display *display, Window systray_window ) DECLSPEC_HIDDEN;
-- 
1.7.9.5



More information about the wine-patches mailing list