Making all the windows handled by the driver to be either GL/VK client surfaces, or top-level windows. This avoids leaking host windows into the Win32 space, and makes it possible to get rid of some remaining NtUserMapWindowPoints in `map_event_coords` for mouse input.
-- v2: winex11: Get rid of the now unnecessary foreign windows. winex11: Generate relative ConfigureNotify on parent ConfigureNotify events. winex11: Use the new host windows to register foreign window events. winex11: Keep track of the host windows children window rects. winex11: Keep track of the host windows relative rects. winex11: Keep track of the host window children of interest. winex11: Create host windows recursively up to root_window. winex11: Introduce a new struct host_window for host-only windows.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 61 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/window.c | 12 +++++++ dlls/winex11.drv/x11drv.h | 14 ++++++++ dlls/winex11.drv/x11drv_main.c | 9 +++++ 4 files changed, 96 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 34a364e11e3..f1f5fced091 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -172,6 +172,55 @@ static inline void free_event_data( XEvent *event ) #endif }
+static void host_window_add_ref( struct host_window *win ) +{ + int ref = InterlockedIncrement( &win->refcount ); + TRACE( "host window %p/%lx increasing refcount to %d\n", win, win->window, ref ); +} + +void host_window_destroy( struct host_window *win ) +{ + TRACE( "host window %p/%lx\n", win, win->window ); + + free( win ); +} + +void host_window_release( struct host_window *win ) +{ + int ref = InterlockedDecrement( &win->refcount ); + + TRACE( "host window %p/%lx decreasing refcount to %d\n", win, win->window, ref ); + + if (!ref) + { + list_remove( &win->entry ); + host_window_destroy( win ); + } +} + +static struct host_window *find_host_window( Window window, BOOL create ) +{ + struct x11drv_thread_data *data = x11drv_thread_data(); + struct host_window *win; + + LIST_FOR_EACH_ENTRY( win, &data->host_windows, struct host_window, entry ) + if (win->window == window) return win; + + if (!create || !(win = calloc( 1, sizeof(*win) ))) return NULL; + win->window = window; + + TRACE( "created host window %p/%lx\n", win, win->window ); + list_add_tail( &data->host_windows, &win->entry ); + return win; +} + +void host_window_reparent( struct host_window **win, Window parent, Window window ) +{ + struct host_window *old = *win, *new = find_host_window( parent, TRUE ); + if ((*win = new)) host_window_add_ref( new ); + if (old) host_window_release( old ); +} + /*********************************************************************** * xembed_request_focus */ @@ -997,6 +1046,12 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *xev )
if (!(data = get_win_data( hwnd ))) return FALSE;
+ if (data->whole_window) + { + TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, event->parent ); + host_window_reparent( &data->parent, event->parent, data->whole_window ); + } + if (!data->embedded) { release_win_data( data ); @@ -1592,6 +1647,12 @@ static void handle_xembed_protocol( HWND hwnd, XClientMessageEvent *event ) break; }
+ if (data->whole_window) + { + TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, data->embedder ); + host_window_reparent( &data->parent, data->embedder, data->whole_window ); + } + make_window_embedded( data ); release_win_data( data ); reparent_notify( event->display, hwnd, event->data.l[3], 0, 0 ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index ab17cb40a1c..403ba346c45 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1686,6 +1686,7 @@ static void create_whole_window( struct x11drv_win_data *data ) cx, cy, 0, data->vis.depth, InputOutput, data->vis.visual, mask, &attr ); if (!data->whole_window) goto done; + host_window_reparent( &data->parent, root_window, data->whole_window );
x11drv_xinput2_enable( data->display, data->whole_window ); set_initial_wm_hints( data->display, data->whole_window ); @@ -1762,6 +1763,12 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des /* Outlook stops processing messages after destroying a dialog, so we need an explicit flush */ XFlush( data->display ); NtUserRemoveProp( data->hwnd, whole_window_prop ); + + if (data->parent) + { + host_window_release( data->parent ); + data->parent = NULL; + } }
@@ -1864,6 +1871,11 @@ BOOL X11DRV_DestroyNotify( HWND hwnd, XEvent *event ) BOOL embedded;
if (!(data = get_win_data( hwnd ))) return FALSE; + if (data->parent) + { + host_window_release( data->parent ); + data->parent = NULL; + } embedded = data->embedded; if (!embedded) FIXME( "window %p/%lx destroyed from the outside\n", hwnd, data->whole_window );
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 622658a6377..e77eaafc215 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -361,6 +361,18 @@ extern HRGN get_dc_monitor_region( HWND hwnd, HDC hdc ); * X11 USER driver */
+/* host-only window, for X11 relative position tracking */ +struct host_window +{ + struct list entry; + LONG refcount; + Window window; +}; + +extern void host_window_destroy( struct host_window *win ); +extern void host_window_release( struct host_window *win ); +extern void host_window_reparent( struct host_window **win, Window parent, Window window ); + struct x11drv_thread_data { Display *display; @@ -380,6 +392,7 @@ struct x11drv_thread_data XIValuatorClassInfo y_valuator; int xinput2_pointer; /* XInput2 master pointer device id */ #endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */ + struct list host_windows; /* list of host windows tracked from this thread */ };
extern struct x11drv_thread_data *x11drv_init_thread_data(void); @@ -600,6 +613,7 @@ struct x11drv_win_data Window whole_window; /* X window for the complete window */ Window client_window; /* X window for the client area */ struct window_rects rects; /* window rects in monitor DPI, relative to parent client area */ + struct host_window *parent; /* the host window parent, frame, root window or embedder */ XIC xic; /* X input context */ UINT managed : 1; /* is window managed? */ UINT mapped : 1; /* is window mapped? (in either normal or iconic state) */ diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 3f8e48a7a8d..63e8ff04d44 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -699,6 +699,7 @@ static NTSTATUS x11drv_init( void *arg ) void X11DRV_ThreadDetach(void) { struct x11drv_thread_data *data = x11drv_thread_data(); + struct host_window *win, *next;
if (data) { @@ -706,6 +707,13 @@ void X11DRV_ThreadDetach(void) if (data->font_set) XFreeFontSet( data->display, data->font_set ); XSync( gdi_display, False ); /* make sure XReparentWindow requests have completed before closing the thread display */ XCloseDisplay( data->display ); + + LIST_FOR_EACH_ENTRY_SAFE( win, next, &data->host_windows, struct host_window, entry ) + { + list_remove( &win->entry ); + host_window_destroy( win ); + } + free( data ); /* clear data in case we get re-entered from user32 before the thread is truly dead */ NtUserGetThreadInfo()->driver_data = 0; @@ -758,6 +766,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) ERR_(winediag)( "x11drv: Can't open display: %s. Please ensure that your X server is running and that $DISPLAY is set correctly.\n", XDisplayName(NULL)); NtTerminateProcess( 0, 1 ); } + list_init( &data->host_windows );
fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 44 ++++++++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 1 + 2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index f1f5fced091..05ecbeb8050 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -182,6 +182,7 @@ void host_window_destroy( struct host_window *win ) { TRACE( "host window %p/%lx\n", win, win->window );
+ if (win->parent) host_window_release( win->parent ); free( win ); }
@@ -198,10 +199,17 @@ void host_window_release( struct host_window *win ) } }
+static int host_window_error( Display *display, XErrorEvent *event, void *arg ) +{ + return (event->error_code == BadWindow); +} + static struct host_window *find_host_window( Window window, BOOL create ) { struct x11drv_thread_data *data = x11drv_thread_data(); + Window xparent = 0, xroot, *xchildren; struct host_window *win; + unsigned int nchildren;
LIST_FOR_EACH_ENTRY( win, &data->host_windows, struct host_window, entry ) if (win->window == window) return win; @@ -209,7 +217,17 @@ static struct host_window *find_host_window( Window window, BOOL create ) if (!create || !(win = calloc( 1, sizeof(*win) ))) return NULL; win->window = window;
- TRACE( "created host window %p/%lx\n", win, win->window ); + if (window != root_window) + { + X11DRV_expect_error( data->display, host_window_error, NULL ); + if (!XQueryTree( data->display, window, &xroot, &xparent, &xchildren, &nchildren )) xparent = root_window; + else XFree( xchildren ); + if (X11DRV_check_error()) WARN( "window %lx already destroyed\n", window ); + + host_window_reparent( &win->parent, xparent, win->window ); + } + + TRACE( "created host window %p/%lx, parent %lx\n", win, win->window, xparent ); list_add_tail( &data->host_windows, &win->entry ); return win; } @@ -221,6 +239,27 @@ void host_window_reparent( struct host_window **win, Window parent, Window windo if (old) host_window_release( old ); }
+static BOOL host_window_filter_event( XEvent *event ) +{ + struct host_window *win; + + if (!(win = find_host_window( event->xany.window, FALSE ))) return FALSE; + + switch (event->type) + { + case ReparentNotify: + { + XReparentEvent *reparent = (XReparentEvent *)event; + TRACE( "host window %p/%lx ReparentNotify, parent %lx\n", win, win->window, reparent->parent ); + host_window_reparent( &win->parent, reparent->parent, win->window ); + break; + } + } + + /* keep processing the event for foreign windows */ + return FALSE; +} + /*********************************************************************** * xembed_request_focus */ @@ -494,6 +533,9 @@ BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,XPointer else continue; /* filtered, ignore it */ } + + if (host_window_filter_event( &event )) continue; + get_event_data( &event ); if (prev_event.type) action = merge_events( &prev_event, &event ); switch( action ) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e77eaafc215..8aa678e9f92 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -367,6 +367,7 @@ struct host_window struct list entry; LONG refcount; Window window; + struct host_window *parent; };
extern void host_window_destroy( struct host_window *win );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 26 ++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 2 ++ 2 files changed, 28 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 05ecbeb8050..41d486c8922 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -183,6 +183,7 @@ void host_window_destroy( struct host_window *win ) TRACE( "host window %p/%lx\n", win, win->window );
if (win->parent) host_window_release( win->parent ); + free( win->children ); free( win ); }
@@ -199,6 +200,13 @@ void host_window_release( struct host_window *win ) } }
+static unsigned int find_host_window_child( struct host_window *win, Window child ) +{ + unsigned int i; + for (i = 0; i < win->children_count; i++) if (win->children[i].window == child) break; + return i; +} + static int host_window_error( Display *display, XErrorEvent *event, void *arg ) { return (event->error_code == BadWindow); @@ -235,7 +243,25 @@ static struct host_window *find_host_window( Window window, BOOL create ) void host_window_reparent( struct host_window **win, Window parent, Window window ) { struct host_window *old = *win, *new = find_host_window( parent, TRUE ); + unsigned int index; + void *tmp; + if ((*win = new)) host_window_add_ref( new ); + + if (old && (index = find_host_window_child( old, window )) < old->children_count) + { + old->children[index] = old->children[old->children_count - 1]; + old->children_count--; + } + + if (new && (index = find_host_window_child( new, window )) == new->children_count) + { + if (!(tmp = realloc( new->children, (index + 1) * sizeof(*new->children) ))) return; + new->children = tmp; + new->children[index].window = window; + new->children_count++; + } + if (old) host_window_release( old ); }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 8aa678e9f92..fc5ab81f282 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -368,6 +368,8 @@ struct host_window LONG refcount; Window window; struct host_window *parent; + unsigned int children_count; + struct { Window window; } *children; };
extern void host_window_destroy( struct host_window *win );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 38 +++++++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 1 + 2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 41d486c8922..2b857340c78 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -200,6 +200,21 @@ void host_window_release( struct host_window *win ) } }
+static POINT host_window_map_point( struct host_window *win, int x, int y ) +{ + POINT pos = {x, y}; + + if (!win) return pos; + while (win->parent) + { + pos.x += win->rect.left; + pos.y += win->rect.top; + win = win->parent; + } + + return pos; +} + static unsigned int find_host_window_child( struct host_window *win, Window child ) { unsigned int i; @@ -217,6 +232,7 @@ static struct host_window *find_host_window( Window window, BOOL create ) struct x11drv_thread_data *data = x11drv_thread_data(); Window xparent = 0, xroot, *xchildren; struct host_window *win; + XWindowAttributes attr; unsigned int nchildren;
LIST_FOR_EACH_ENTRY( win, &data->host_windows, struct host_window, entry ) @@ -228,14 +244,17 @@ static struct host_window *find_host_window( Window window, BOOL create ) if (window != root_window) { X11DRV_expect_error( data->display, host_window_error, NULL ); + if (!XGetWindowAttributes( data->display, window, &attr )) memset( &attr, 0, sizeof(attr) ); if (!XQueryTree( data->display, window, &xroot, &xparent, &xchildren, &nchildren )) xparent = root_window; else XFree( xchildren ); if (X11DRV_check_error()) WARN( "window %lx already destroyed\n", window );
host_window_reparent( &win->parent, xparent, win->window ); + SetRect( &win->rect, attr.x, attr.y, attr.x + attr.width, attr.y + attr.height ); }
- TRACE( "created host window %p/%lx, parent %lx\n", win, win->window, xparent ); + TRACE( "created host window %p/%lx, parent %lx rect %s\n", win, win->window, + xparent, wine_dbgstr_rect(&win->rect) ); list_add_tail( &data->host_windows, &win->entry ); return win; } @@ -280,6 +299,23 @@ static BOOL host_window_filter_event( XEvent *event ) host_window_reparent( &win->parent, reparent->parent, win->window ); break; } + case GravityNotify: + { + XGravityEvent *gravity = (XGravityEvent *)event; + OffsetRect( &win->rect, gravity->x - win->rect.left, gravity->y - win->rect.top ); + TRACE( "host window %p/%lx GravityNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); + break; + } + case ConfigureNotify: + { + XConfigureEvent *configure = (XConfigureEvent *)event; + POINT offset = {0}; + SetRect( &win->rect, configure->x, configure->y, configure->x + configure->width, configure->y + configure->height ); + if (configure->send_event) offset = host_window_map_point( win->parent, 0, 0 ); + OffsetRect( &win->rect, -offset.x, -offset.y ); + TRACE( "host window %p/%lx ConfigureNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); + break; + } }
/* keep processing the event for foreign windows */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index fc5ab81f282..3518f005f6c 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -367,6 +367,7 @@ struct host_window struct list entry; LONG refcount; Window window; + RECT rect; /* host window rect, relative to parent */ struct host_window *parent; unsigned int children_count; struct { Window window; } *children;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 36 +++++++++++++++++++++++++++++++++--- dlls/winex11.drv/window.c | 1 + dlls/winex11.drv/x11drv.h | 3 ++- 3 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 2b857340c78..34778fd6c5d 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -222,6 +222,21 @@ static unsigned int find_host_window_child( struct host_window *win, Window chil return i; }
+RECT host_window_configure_child( struct host_window *parent, Window window, RECT rect, BOOL root_coords ) +{ + unsigned int index; + POINT offset = {0}; + + if (parent && (index = find_host_window_child( parent, window )) != parent->children_count) + { + if (root_coords) offset = host_window_map_point( parent, 0, 0 ); + OffsetRect( &rect, -offset.x, -offset.y ); + parent->children[index].rect = rect; + } + + return rect; +} + static int host_window_error( Display *display, XErrorEvent *event, void *arg ) { return (event->error_code == BadWindow); @@ -251,6 +266,7 @@ static struct host_window *find_host_window( Window window, BOOL create )
host_window_reparent( &win->parent, xparent, win->window ); SetRect( &win->rect, attr.x, attr.y, attr.x + attr.width, attr.y + attr.height ); + host_window_configure_child( win->parent, win->window, win->rect, FALSE ); }
TRACE( "created host window %p/%lx, parent %lx rect %s\n", win, win->window, @@ -263,12 +279,14 @@ void host_window_reparent( struct host_window **win, Window parent, Window windo { struct host_window *old = *win, *new = find_host_window( parent, TRUE ); unsigned int index; + RECT rect = {0}; void *tmp;
if ((*win = new)) host_window_add_ref( new );
if (old && (index = find_host_window_child( old, window )) < old->children_count) { + rect = old->children[index].rect; old->children[index] = old->children[old->children_count - 1]; old->children_count--; } @@ -277,7 +295,11 @@ void host_window_reparent( struct host_window **win, Window parent, Window windo { if (!(tmp = realloc( new->children, (index + 1) * sizeof(*new->children) ))) return; new->children = tmp; + + OffsetRect( &rect, -rect.left, -rect.top ); new->children[index].window = window; + new->children[index].rect = rect; + new->children_count++; }
@@ -303,16 +325,15 @@ static BOOL host_window_filter_event( XEvent *event ) { XGravityEvent *gravity = (XGravityEvent *)event; OffsetRect( &win->rect, gravity->x - win->rect.left, gravity->y - win->rect.top ); + win->rect = host_window_configure_child( win->parent, win->window, win->rect, FALSE ); TRACE( "host window %p/%lx GravityNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); break; } case ConfigureNotify: { XConfigureEvent *configure = (XConfigureEvent *)event; - POINT offset = {0}; SetRect( &win->rect, configure->x, configure->y, configure->x + configure->width, configure->y + configure->height ); - if (configure->send_event) offset = host_window_map_point( win->parent, 0, 0 ); - OffsetRect( &win->rect, -offset.x, -offset.y ); + win->rect = host_window_configure_child( win->parent, win->window, win->rect, configure->send_event ); TRACE( "host window %p/%lx ConfigureNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); break; } @@ -1154,6 +1175,7 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *xev ) { TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, event->parent ); host_window_reparent( &data->parent, event->parent, data->whole_window ); + host_window_configure_child( data->parent, data->whole_window, data->rects.visible, TRUE ); }
if (!data->embedded) @@ -1225,6 +1247,13 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
if (!hwnd) return FALSE; if (!(data = get_win_data( hwnd ))) return FALSE; + + if (data->whole_window) + { + SetRect( &rect, event->x, event->y, event->x + event->width, event->y + event->height ); + host_window_configure_child( data->parent, data->whole_window, rect, event->send_event ); + } + if (!data->mapped || data->iconic) goto done; if (data->whole_window && !data->managed) goto done; /* ignore synthetic events on foreign windows */ @@ -1755,6 +1784,7 @@ static void handle_xembed_protocol( HWND hwnd, XClientMessageEvent *event ) { TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, data->embedder ); host_window_reparent( &data->parent, data->embedder, data->whole_window ); + host_window_configure_child( data->parent, data->whole_window, data->rects.visible, TRUE ); }
make_window_embedded( data ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 403ba346c45..bc15837190a 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1687,6 +1687,7 @@ static void create_whole_window( struct x11drv_win_data *data ) data->vis.visual, mask, &attr ); if (!data->whole_window) goto done; host_window_reparent( &data->parent, root_window, data->whole_window ); + host_window_configure_child( data->parent, data->whole_window, data->rects.visible, TRUE );
x11drv_xinput2_enable( data->display, data->whole_window ); set_initial_wm_hints( data->display, data->whole_window ); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 3518f005f6c..e447c81e5df 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -370,12 +370,13 @@ struct host_window RECT rect; /* host window rect, relative to parent */ struct host_window *parent; unsigned int children_count; - struct { Window window; } *children; + struct { Window window; RECT rect; } *children; };
extern void host_window_destroy( struct host_window *win ); extern void host_window_release( struct host_window *win ); extern void host_window_reparent( struct host_window **win, Window parent, Window window ); +extern RECT host_window_configure_child( struct host_window *win, Window window, RECT rect, BOOL root_coords );
struct x11drv_thread_data {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 8 ++++++++ dlls/winex11.drv/window.c | 5 ----- dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 34778fd6c5d..0c16d8151d2 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -180,9 +180,12 @@ static void host_window_add_ref( struct host_window *win )
void host_window_destroy( struct host_window *win ) { + struct x11drv_thread_data *data = x11drv_thread_data(); + TRACE( "host window %p/%lx\n", win, win->window );
if (win->parent) host_window_release( win->parent ); + if (!win->destroyed) XSelectInput( data->display, win->window, 0 ); free( win->children ); free( win ); } @@ -259,6 +262,7 @@ static struct host_window *find_host_window( Window window, BOOL create ) if (window != root_window) { X11DRV_expect_error( data->display, host_window_error, NULL ); + XSelectInput( data->display, window, StructureNotifyMask ); if (!XGetWindowAttributes( data->display, window, &attr )) memset( &attr, 0, sizeof(attr) ); if (!XQueryTree( data->display, window, &xroot, &xparent, &xchildren, &nchildren )) xparent = root_window; else XFree( xchildren ); @@ -314,6 +318,10 @@ static BOOL host_window_filter_event( XEvent *event )
switch (event->type) { + case DestroyNotify: + TRACE( "host window %p/%lx DestroyNotify\n", win, win->window ); + win->destroyed = TRUE; + break; case ReparentNotify: { XReparentEvent *reparent = (XReparentEvent *)event; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index bc15837190a..8caa7fc72a3 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1731,7 +1731,6 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des Window xwin = (Window)NtUserGetProp( data->hwnd, foreign_window_prop ); if (xwin) { - if (!already_destroyed) XSelectInput( data->display, xwin, 0 ); XDeleteContext( data->display, xwin, winContext ); NtUserRemoveProp( data->hwnd, foreign_window_prop ); } @@ -2125,13 +2124,9 @@ HWND create_foreign_window( Display *display, Window xwin ) if (XFindContext( display, xwin, winContext, (char **)&hwnd )) hwnd = 0; if (hwnd) return hwnd; /* already created */
- XSelectInput( display, xwin, StructureNotifyMask ); if (!XGetWindowAttributes( display, xwin, &attr ) || !XQueryTree( display, xwin, &xroot, &xparent, &xchildren, &nchildren )) - { - XSelectInput( display, xwin, 0 ); return 0; - } XFree( xchildren );
if (xparent == xroot) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e447c81e5df..ff63220df9a 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -367,6 +367,7 @@ struct host_window struct list entry; LONG refcount; Window window; + BOOL destroyed; /* host window has already been destroyed */ RECT rect; /* host window rect, relative to parent */ struct host_window *parent; unsigned int children_count;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 0c16d8151d2..44198cae371 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -313,8 +313,10 @@ void host_window_reparent( struct host_window **win, Window parent, Window windo static BOOL host_window_filter_event( XEvent *event ) { struct host_window *win; + RECT old_rect;
if (!(win = find_host_window( event->xany.window, FALSE ))) return FALSE; + old_rect = win->rect;
switch (event->type) { @@ -347,6 +349,27 @@ static BOOL host_window_filter_event( XEvent *event ) } }
+ if (old_rect.left != win->rect.left || old_rect.top != win->rect.top) + { + XConfigureEvent configure = {.type = ConfigureNotify, .serial = event->xany.serial, .display = event->xany.display}; + unsigned int i; + + for (i = 0; i < win->children_count; i++) + { + RECT rect = win->children[i].rect; + + configure.event = win->children[i].window; + configure.window = configure.event; + configure.x = rect.left; + configure.y = rect.top; + configure.width = rect.right - rect.left; + configure.height = rect.bottom - rect.top; + configure.send_event = 0; + + XPutBackEvent( configure.display, (XEvent *)&configure ); + } + } + /* keep processing the event for foreign windows */ return FALSE; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/Makefile.in | 1 - dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/event.c | 122 +++------------------------------ dlls/winex11.drv/mouse.c | 16 ++--- dlls/winex11.drv/systray.c | 55 --------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/window.c | 96 +------------------------- dlls/winex11.drv/x11drv.h | 2 - dlls/winex11.drv/x11drv_dll.h | 3 - dlls/winex11.drv/x11drv_main.c | 2 - 10 files changed, 17 insertions(+), 282 deletions(-) delete mode 100644 dlls/winex11.drv/systray.c
diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in index f570b026db4..155c0be5345 100644 --- a/dlls/winex11.drv/Makefile.in +++ b/dlls/winex11.drv/Makefile.in @@ -20,7 +20,6 @@ SOURCES = \ opengl.c \ palette.c \ pen.c \ - systray.c \ version.rc \ vulkan.c \ window.c \ diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 14336adf583..01e5d417800 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -34,7 +34,6 @@ BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved ) .dnd_post_drop_callback = (UINT_PTR)x11drv_dnd_post_drop, .dnd_drop_event_callback = (UINT_PTR)x11drv_dnd_drop_event, .dnd_leave_event_callback = (UINT_PTR)x11drv_dnd_leave_event, - .foreign_window_proc = (UINT_PTR)foreign_window_proc, };
if (reason != DLL_PROCESS_ATTACH) return TRUE; diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 44198cae371..5e6611c5676 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -89,7 +89,6 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_ClientMessage( HWND hwnd, XEvent *event ); -static BOOL X11DRV_GravityNotify( HWND hwnd, XEvent *event );
#define MAX_EVENT_HANDLERS 128
@@ -119,7 +118,7 @@ static x11drv_event_handler handlers[MAX_EVENT_HANDLERS] = X11DRV_ReparentNotify, /* 21 ReparentNotify */ X11DRV_ConfigureNotify, /* 22 ConfigureNotify */ NULL, /* 23 ConfigureRequest */ - X11DRV_GravityNotify, /* 24 GravityNotify */ + NULL, /* 24 GravityNotify */ NULL, /* 25 ResizeRequest */ NULL, /* 26 CirculateNotify */ NULL, /* 27 CirculateRequest */ @@ -370,8 +369,7 @@ static BOOL host_window_filter_event( XEvent *event ) } }
- /* keep processing the event for foreign windows */ - return FALSE; + return TRUE; }
/*********************************************************************** @@ -1158,40 +1156,6 @@ static BOOL X11DRV_UnmapNotify( HWND hwnd, XEvent *event ) }
-/*********************************************************************** - * reparent_notify - */ -static void reparent_notify( Display *display, HWND hwnd, Window xparent, int x, int y ) -{ - HWND parent, old_parent; - DWORD style, flags = 0; - RECT rect; - - style = NtUserGetWindowLongW( hwnd, GWL_STYLE ); - if (xparent == root_window) - { - parent = NtUserGetDesktopWindow(); - style = (style & ~WS_CHILD) | WS_POPUP; - } - else - { - if (!(parent = create_foreign_window( display, xparent ))) return; - style = (style & ~WS_POPUP) | WS_CHILD; - } - - NtUserShowWindow( hwnd, SW_HIDE ); - old_parent = NtUserSetParent( hwnd, parent ); - NtUserSetWindowLong( hwnd, GWL_STYLE, style, FALSE ); - - if (style & WS_VISIBLE) flags = SWP_SHOWWINDOW; - SetRect( &rect, x, y, x, y ); - NtUserSetRawWindowPos( hwnd, rect, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS | flags, FALSE ); - - /* make old parent destroy itself if it no longer has children */ - if (old_parent != NtUserGetDesktopWindow()) NtUserPostMessage( old_parent, WM_CLOSE, 0, 0 ); -} - - /*********************************************************************** * X11DRV_ReparentNotify */ @@ -1230,39 +1194,9 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *xev )
TRACE( "%p/%lx reparented to %lx\n", hwnd, data->whole_window, event->parent ); release_win_data( data ); - - reparent_notify( event->display, hwnd, event->parent, event->x, event->y ); return TRUE; }
-/* map XConfigureNotify event coordinates to parent-relative monitor DPI coordinates */ -static POINT map_configure_event_coords( struct x11drv_win_data *data, XConfigureEvent *event ) -{ - Window child, parent = data->embedder ? data->embedder : root_window; - POINT pos; - - if (event->send_event && parent == DefaultRootWindow( event->display )) - { - pos.x = event->x; - pos.y = event->y; - } - else if (event->send_event) - { - /* synthetic events are always in root coords */ - XTranslateCoordinates( event->display, DefaultRootWindow( event->display ), parent, - event->x, event->y, (int *)&pos.x, (int *)&pos.y, &child ); - } - else - { - /* query the current window position, events are relative to their parent */ - XTranslateCoordinates( event->display, event->window, parent, 0, 0, - (int *)&pos.x, (int *)&pos.y, &child ); - } - - if (parent == root_window) pos = root_to_virtual_screen( pos.x, pos.y ); - return pos; -} - /*********************************************************************** * X11DRV_ConfigureNotify */ @@ -1271,9 +1205,9 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) XConfigureEvent *event = &xev->xconfigure; struct x11drv_win_data *data; RECT rect; - POINT pos; + POINT pos = {event->x, event->y}; UINT flags; - int cx, cy, x = event->x, y = event->y; + int cx, cy, x, y; DWORD style;
if (!hwnd) return FALSE; @@ -1286,9 +1220,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) }
if (!data->mapped || data->iconic) goto done; - if (data->whole_window && !data->managed) goto done; - /* ignore synthetic events on foreign windows */ - if (event->send_event && !data->whole_window) goto done; + if (!data->whole_window || !data->managed) goto done; if (data->configure_serial && (long)(data->configure_serial - event->serial) > 0) { TRACE( "win %p/%lx event %d,%d,%dx%d ignoring old serial %lu/%lu\n", @@ -1297,9 +1229,11 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) goto done; }
- /* Get geometry */ + /* synthetic events are already in absolute coordinates */ + if (!event->send_event) pos = host_window_map_point( data->parent, event->x, event->y ); + else if (is_virtual_desktop()) FIXME( "synthetic event mapping not implemented\n" );
- pos = map_configure_event_coords( data, event ); + pos = root_to_virtual_screen( pos.x, pos.y ); SetRect( &rect, pos.x, pos.y, pos.x + event->width, pos.y + event->height ); rect = window_rect_from_visible( &data->rects, rect );
@@ -1368,43 +1302,6 @@ done: }
-/********************************************************************** - * X11DRV_GravityNotify - */ -static BOOL X11DRV_GravityNotify( HWND hwnd, XEvent *xev ) -{ - XGravityEvent *event = &xev->xgravity; - struct x11drv_win_data *data = get_win_data( hwnd ); - RECT window_rect; - int x, y; - - if (!data) return FALSE; - - if (data->whole_window) /* only handle this for foreign windows */ - { - release_win_data( data ); - return FALSE; - } - - x = event->x + data->rects.window.left - data->rects.visible.left; - y = event->y + data->rects.window.top - data->rects.visible.top; - - TRACE( "win %p/%lx new X pos %d,%d (event %d,%d)\n", - hwnd, data->whole_window, x, y, event->x, event->y ); - - window_rect = data->rects.window; - release_win_data( data ); - - if (window_rect.left != x || window_rect.top != y) - { - RECT rect = {x, y, x, y}; - NtUserSetRawWindowPos( hwnd, rect, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS, FALSE ); - } - - return TRUE; -} - - /*********************************************************************** * get_window_wm_state */ @@ -1820,7 +1717,6 @@ static void handle_xembed_protocol( HWND hwnd, XClientMessageEvent *event )
make_window_embedded( data ); release_win_data( data ); - reparent_notify( event->display, hwnd, event->data.l[3], 0, 0 ); } break;
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 15557c3d917..cbbb27d6798 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -509,17 +509,15 @@ static void map_event_coords( HWND hwnd, Window window, Window event_root, int x { if (window == root_window) pt = root_to_virtual_screen( pt.x, pt.y ); else if (event_root == root_window) pt = root_to_virtual_screen( x_root, y_root ); + else if (window == data->client_window) + { + pt.x += data->rects.client.left; + pt.y += data->rects.client.top; + } else { - if (window == data->whole_window) - { - pt.x += data->rects.visible.left - data->rects.client.left; - pt.y += data->rects.visible.top - data->rects.client.top; - } - - if (NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) - pt.x = data->rects.client.right - data->rects.client.left - 1 - pt.x; - NtUserMapWindowPoints( hwnd, 0, &pt, 1, 0 /* per-monitor DPI */ ); + pt.x += data->rects.visible.left; + pt.y += data->rects.visible.top; } release_win_data( data ); } diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c deleted file mode 100644 index e21ce481f9b..00000000000 --- a/dlls/winex11.drv/systray.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * X11 system tray management - * - * Copyright (C) 2004 Mike Hearn, for CodeWeavers - * Copyright (C) 2005 Robert Shearman - * Copyright (C) 2008 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "x11drv_dll.h" -#include "commctrl.h" -#include "shellapi.h" - -#include "wine/list.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(systray); - -/* window procedure for foreign windows */ -LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) -{ - switch(msg) - { - case WM_WINDOWPOSCHANGED: - { - HWND hwnd = FindWindowW( L"Shell_TrayWnd", NULL ); - PostMessageW( hwnd, WM_USER + 0, 0, 0 ); - break; - } - case WM_PARENTNOTIFY: - if (LOWORD(wparam) == WM_DESTROY) - { - TRACE( "%p: got parent notify destroy for win %Ix\n", hwnd, lparam ); - PostMessageW( hwnd, WM_CLOSE, 0, 0 ); /* so that we come back here once the child is gone */ - } - return 0; - case WM_CLOSE: - if (GetWindow( hwnd, GW_CHILD )) return 0; /* refuse to die if we still have children */ - break; - } - return DefWindowProcW( hwnd, msg, wparam, lparam ); -} diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 522411f8e55..f23d7204bcd 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -40,7 +40,6 @@ struct init_params UINT64 dnd_post_drop_callback; UINT64 dnd_drop_event_callback; UINT64 dnd_leave_event_callback; - UINT64 foreign_window_proc; };
/* x11drv_tablet_info params */ diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 8caa7fc72a3..9f01eb46f6c 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -103,8 +103,6 @@ static XContext win_data_context = 0; static Time last_user_time; static Window user_time_window;
-static const WCHAR foreign_window_prop[] = - {'_','_','w','i','n','e','_','x','1','1','_','f','o','r','e','i','g','n','_','w','i','n','d','o','w',0}; static const WCHAR whole_window_prop[] = {'_','_','w','i','n','e','_','x','1','1','_','w','h','o','l','e','_','w','i','n','d','o','w',0}; static const WCHAR clip_window_prop[] = @@ -1726,16 +1724,7 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des
if (!data->whole_window) { - if (data->embedded) - { - Window xwin = (Window)NtUserGetProp( data->hwnd, foreign_window_prop ); - if (xwin) - { - XDeleteContext( data->display, xwin, winContext ); - NtUserRemoveProp( data->hwnd, foreign_window_prop ); - } - return; - } + if (data->embedded) return; } else { @@ -2085,89 +2074,6 @@ static struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd, const struct w }
-/*********************************************************************** - * create_foreign_window - * - * Create a foreign window for the specified X window and its ancestors - */ -HWND create_foreign_window( Display *display, Window xwin ) -{ - static BOOL class_registered; - struct x11drv_win_data *data; - HWND hwnd, parent; - POINT pos; - Window xparent, xroot; - Window *xchildren; - unsigned int nchildren; - XWindowAttributes attr; - UINT style = WS_CLIPCHILDREN; - UNICODE_STRING class_name = RTL_CONSTANT_STRING( foreign_window_prop ); - - if (!class_registered) - { - UNICODE_STRING version = { 0 }; - WNDCLASSEXW class; - - memset( &class, 0, sizeof(class) ); - class.cbSize = sizeof(class); - class.lpfnWndProc = (WNDPROC)(UINT_PTR)client_foreign_window_proc; - class.lpszClassName = foreign_window_prop; - if (!NtUserRegisterClassExWOW( &class, &class_name, &version, NULL, 0, 0, NULL ) && - RtlGetLastWin32Error() != ERROR_CLASS_ALREADY_EXISTS) - { - ERR( "Could not register foreign window class\n" ); - return FALSE; - } - class_registered = TRUE; - } - - if (XFindContext( display, xwin, winContext, (char **)&hwnd )) hwnd = 0; - if (hwnd) return hwnd; /* already created */ - - if (!XGetWindowAttributes( display, xwin, &attr ) || - !XQueryTree( display, xwin, &xroot, &xparent, &xchildren, &nchildren )) - return 0; - XFree( xchildren ); - - if (xparent == xroot) - { - parent = NtUserGetDesktopWindow(); - style |= WS_POPUP; - pos = root_to_virtual_screen( attr.x, attr.y ); - } - else - { - parent = create_foreign_window( display, xparent ); - style |= WS_CHILD; - pos.x = attr.x; - pos.y = attr.y; - } - - hwnd = NtUserCreateWindowEx( 0, &class_name, &class_name, NULL, style, pos.x, pos.y, - attr.width, attr.height, parent, 0, NULL, NULL, 0, NULL, - 0, FALSE ); - if (!(data = get_win_data( hwnd ))) - { - NtUserDestroyWindow( hwnd ); - return 0; - } - destroy_whole_window( data, FALSE ); - data->embedded = TRUE; - data->mapped = TRUE; - - NtUserSetProp( hwnd, foreign_window_prop, (HANDLE)xwin ); - XSaveContext( display, xwin, winContext, (char *)data->hwnd ); - - TRACE( "win %lx parent %p style %08x %s -> hwnd %p\n", - xwin, parent, style, wine_dbgstr_rect(&data->rects.window), hwnd ); - - release_win_data( data ); - - NtUserShowWindow( hwnd, SW_SHOW ); - return hwnd; -} - - /*********************************************************************** * SystrayDockInit (X11DRV.@) */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index ff63220df9a..26e9016cd34 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -452,7 +452,6 @@ extern int alloc_system_colors; extern int xrender_error_base; extern char *process_name; extern Display *clipboard_display; -extern UINT64 client_foreign_window_proc; extern UINT64 dnd_enter_event_callback; extern UINT64 dnd_position_event_callback; extern UINT64 dnd_post_drop_callback; @@ -664,7 +663,6 @@ extern void attach_client_window( struct x11drv_win_data *data, Window client_wi extern void destroy_client_window( HWND hwnd, Window client_window ); extern void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis, BOOL use_alpha ); extern void change_systray_owner( Display *display, Window systray_window ); -extern HWND create_foreign_window( Display *display, Window window ); extern BOOL update_clipboard( HWND hwnd ); extern void init_win_context(void); extern DROPFILES *file_list_to_drop_files( const void *data, size_t size, size_t *ret_size ); diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index bc68c3996c3..6113f01344a 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -33,9 +33,6 @@ extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ); extern NTSTATUS WINAPI x11drv_dnd_drop_event( void *params, ULONG size ); extern NTSTATUS WINAPI x11drv_dnd_leave_event( void *params, ULONG size );
-extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, - LPARAM lparam ); - extern HMODULE x11drv_module;
#endif /* __WINE_X11DRV_DLL_H */ diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 63e8ff04d44..551cf6fd4fe 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -85,7 +85,6 @@ int copy_default_colors = 128; int alloc_system_colors = 256; int xrender_error_base = 0; char *process_name = NULL; -UINT64 client_foreign_window_proc = 0; UINT64 dnd_enter_event_callback = 0; UINT64 dnd_position_event_callback = 0; UINT64 dnd_post_drop_callback = 0; @@ -653,7 +652,6 @@ static NTSTATUS x11drv_init( void *arg ) dnd_post_drop_callback = params->dnd_post_drop_callback; dnd_drop_event_callback = params->dnd_drop_event_callback; dnd_leave_event_callback = params->dnd_leave_event_callback; - client_foreign_window_proc = params->foreign_window_proc;
fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */ root_window = DefaultRootWindow( display );