[2/4] winex11: Send XEMBED_REQUEST_FOCUS request for embedded windows

Sebastian Lackner sebastian at fds-team.de
Mon Nov 4 18:35:09 CST 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 6793fcadedd65993394e21a4fe22dd0b3cf15296 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian at fds-team.de>
Date: Sat, 26 Oct 2013 18:39:07 +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 64188bc..df27468 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 );
 }
 
 /**********************************************************************
@@ -904,7 +941,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 );
 }
@@ -1363,12 +1400,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 e78f226..ebbfd45 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1140,6 +1140,22 @@ void make_window_embedded( struct x11drv_win_data *data )
     set_xembed_flags( data, (data->mapped || data->embedder) ? 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 98386ce..71881fe 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -582,6 +582,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