winex11: Re-create the client window when setting the pixel format on a top-level window.

This commit is contained in:
Alexandre Julliard 2008-02-22 10:40:22 +01:00
parent e9307d09a6
commit 42ad345852
1 changed files with 96 additions and 83 deletions

View File

@ -206,6 +206,65 @@ static int get_window_attributes( Display *display, struct x11drv_win_data *data
} }
/***********************************************************************
* create_client_window
*/
static Window create_client_window( Display *display, struct x11drv_win_data *data, XVisualInfo *vis )
{
int cx, cy, mask;
XSetWindowAttributes attr;
Window client;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.backing_store = NotUseful;
attr.event_mask = (ExposureMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
mask = CWEventMask | CWBitGravity | CWWinGravity | CWBackingStore;
if ((cx = data->client_rect.right - data->client_rect.left) <= 0) cx = 1;
if ((cy = data->client_rect.bottom - data->client_rect.top) <= 0) cy = 1;
wine_tsx11_lock();
if (vis)
{
attr.colormap = XCreateColormap( display, root_window, vis->visual,
(vis->class == PseudoColor || vis->class == GrayScale ||
vis->class == DirectColor) ? AllocAll : AllocNone );
mask |= CWColormap;
}
client = XCreateWindow( display, data->whole_window,
data->client_rect.left - data->whole_rect.left,
data->client_rect.top - data->whole_rect.top,
cx, cy, 0, screen_depth, InputOutput,
vis ? vis->visual : visual, mask, &attr );
if (!client)
{
wine_tsx11_unlock();
return 0;
}
if (data->client_window)
{
XDeleteContext( display, data->client_window, winContext );
XDestroyWindow( display, data->client_window );
}
data->client_window = client;
if (data->colormap) XFreeColormap( display, data->colormap );
data->colormap = vis ? attr.colormap : 0;
XMapWindow( display, data->client_window );
XSaveContext( display, data->client_window, winContext, (char *)data->hwnd );
wine_tsx11_unlock();
SetPropA( data->hwnd, client_window_prop, (HANDLE)data->client_window );
return data->client_window;
}
/*********************************************************************** /***********************************************************************
* X11DRV_sync_window_style * X11DRV_sync_window_style
* *
@ -311,41 +370,32 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
Display *display = thread_display(); Display *display = thread_display();
struct x11drv_win_data *data; struct x11drv_win_data *data;
XVisualInfo *vis; XVisualInfo *vis;
Drawable parent;
HWND next_hwnd;
int w, h; int w, h;
if (!(data = X11DRV_get_win_data(hwnd)) && if (!(data = X11DRV_get_win_data(hwnd)) &&
!(data = X11DRV_create_win_data(hwnd))) return FALSE; !(data = X11DRV_create_win_data(hwnd))) return FALSE;
if (data->fbconfig_id) return FALSE; /* can't change it twice */
wine_tsx11_lock(); wine_tsx11_lock();
vis = visual_from_fbconfig_id(fbconfig_id); vis = visual_from_fbconfig_id(fbconfig_id);
if(!vis)
{
wine_tsx11_unlock();
return FALSE;
}
if(data->whole_window && vis->visualid == XVisualIDFromVisual(visual))
{
TRACE("Whole window available and visual match, rendering onscreen\n");
goto done;
}
wine_tsx11_unlock(); wine_tsx11_unlock();
if (!vis) return FALSE;
parent = data->whole_window; if (data->whole_window)
next_hwnd = hwnd;
while(!parent)
{ {
next_hwnd = GetAncestor(next_hwnd, GA_PARENT); Window client = data->client_window;
if(!next_hwnd)
if (vis->visualid != XVisualIDFromVisual(visual))
{ {
ERR("Could not find parent HWND with a drawable!\n"); client = create_client_window( display, data, vis );
return FALSE; TRACE( "re-created client window %lx for %p fbconfig %lx\n", client, data->hwnd, fbconfig_id );
} }
parent = X11DRV_get_whole_window(next_hwnd); wine_tsx11_lock();
XFree(vis);
wine_tsx11_unlock();
if (client) goto done;
return FALSE;
} }
w = data->client_rect.right - data->client_rect.left; w = data->client_rect.right - data->client_rect.left;
@ -354,12 +404,14 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
if(w <= 0) w = 1; if(w <= 0) w = 1;
if(h <= 0) h = 1; if(h <= 0) h = 1;
wine_tsx11_lock();
#ifdef SONAME_LIBXCOMPOSITE #ifdef SONAME_LIBXCOMPOSITE
if(usexcomposite) if(usexcomposite)
{ {
XSetWindowAttributes attrib; XSetWindowAttributes attrib;
Window parent = X11DRV_get_whole_window( GetAncestor( hwnd, GA_ROOT ));
if (!parent) parent = root_window;
wine_tsx11_lock();
data->colormap = XCreateColormap(display, parent, vis->visual, data->colormap = XCreateColormap(display, parent, vis->visual,
(vis->class == PseudoColor || (vis->class == PseudoColor ||
vis->class == GrayScale || vis->class == GrayScale ||
@ -379,16 +431,18 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
CompositeRedirectManual); CompositeRedirectManual);
XMapWindow(display, data->gl_drawable); XMapWindow(display, data->gl_drawable);
} }
XFree(vis);
wine_tsx11_unlock();
} }
else else
#endif #endif
{ {
WARN("XComposite is not available, using GLXPixmap hack\n"); WARN("XComposite is not available, using GLXPixmap hack\n");
data->pixmap = XCreatePixmap(display, parent, w, h, vis->depth); wine_tsx11_lock();
data->pixmap = XCreatePixmap(display, root_window, w, h, vis->depth);
if(!data->pixmap) if(!data->pixmap)
{ {
ERR("Failed to create pixmap for offscreen rendering\n");
XFree(vis); XFree(vis);
wine_tsx11_unlock(); wine_tsx11_unlock();
return FALSE; return FALSE;
@ -400,29 +454,23 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
XFreePixmap(display, data->pixmap); XFreePixmap(display, data->pixmap);
data->pixmap = 0; data->pixmap = 0;
} }
}
if(!data->gl_drawable)
{
ERR("Failed to create drawable for offscreen rendering\n");
XFree(vis); XFree(vis);
wine_tsx11_unlock(); wine_tsx11_unlock();
return FALSE; if (data->pixmap) SetPropA(hwnd, pixmap_prop, (HANDLE)data->pixmap);
} }
done: if (!data->gl_drawable) return FALSE;
XFree(vis);
XFlush(display);
wine_tsx11_unlock();
TRACE("Created GL drawable 0x%lx, using FBConfigID 0x%lx\n", TRACE("Created GL drawable 0x%lx, using FBConfigID 0x%lx\n",
data->gl_drawable, fbconfig_id); data->gl_drawable, fbconfig_id);
SetPropA(hwnd, gl_drawable_prop, (HANDLE)data->gl_drawable);
done:
data->fbconfig_id = fbconfig_id; data->fbconfig_id = fbconfig_id;
SetPropA(hwnd, fbconfig_id_prop, (HANDLE)data->fbconfig_id); SetPropA(hwnd, fbconfig_id_prop, (HANDLE)data->fbconfig_id);
SetPropA(hwnd, gl_drawable_prop, (HANDLE)data->gl_drawable); wine_tsx11_lock();
SetPropA(hwnd, pixmap_prop, (HANDLE)data->pixmap); XFlush( display );
wine_tsx11_unlock();
invalidate_dce( hwnd, &data->window_rect ); invalidate_dce( hwnd, &data->window_rect );
return TRUE; return TRUE;
} }
@ -435,8 +483,6 @@ static void sync_gl_drawable(Display *display, struct x11drv_win_data *data)
int w = data->client_rect.right - data->client_rect.left; int w = data->client_rect.right - data->client_rect.left;
int h = data->client_rect.bottom - data->client_rect.top; int h = data->client_rect.bottom - data->client_rect.top;
XVisualInfo *vis; XVisualInfo *vis;
Drawable parent;
HWND next_hwnd;
Drawable glxp; Drawable glxp;
Pixmap pix; Pixmap pix;
@ -451,19 +497,6 @@ static void sync_gl_drawable(Display *display, struct x11drv_win_data *data)
} }
#endif #endif
parent = data->whole_window;
next_hwnd = data->hwnd;
while(!parent)
{
next_hwnd = GetAncestor(next_hwnd, GA_PARENT);
if(!next_hwnd)
{
ERR("Could not find parent HWND with a drawable!\n");
return;
}
parent = X11DRV_get_whole_window(next_hwnd);
}
wine_tsx11_lock(); wine_tsx11_lock();
vis = visual_from_fbconfig_id(data->fbconfig_id); vis = visual_from_fbconfig_id(data->fbconfig_id);
@ -473,7 +506,7 @@ static void sync_gl_drawable(Display *display, struct x11drv_win_data *data)
return; return;
} }
pix = XCreatePixmap(display, parent, w, h, vis->depth); pix = XCreatePixmap(display, root_window, w, h, vis->depth);
if(!pix) if(!pix)
{ {
ERR("Failed to create pixmap for offscreen rendering\n"); ERR("Failed to create pixmap for offscreen rendering\n");
@ -1161,40 +1194,21 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
cx, cy, 0, screen_depth, InputOutput, cx, cy, 0, screen_depth, InputOutput,
visual, mask, &attr ); visual, mask, &attr );
if (!data->whole_window) if (data->whole_window) XSaveContext( display, data->whole_window, winContext, (char *)data->hwnd );
{ wine_tsx11_unlock();
wine_tsx11_unlock();
return 0; if (!data->whole_window) return 0;
}
if (!create_client_window( display, data, NULL ))
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.backing_store = NotUseful;
attr.event_mask = (ExposureMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
mask = CWEventMask | CWBitGravity | CWWinGravity | CWBackingStore;
if ((cx = data->client_rect.right - data->client_rect.left) <= 0) cx = 1;
if ((cy = data->client_rect.bottom - data->client_rect.top) <= 0) cy = 1;
data->client_window = XCreateWindow( display, data->whole_window,
data->client_rect.left - data->window_rect.left,
data->client_rect.top - data->window_rect.top,
cx, cy, 0, screen_depth, InputOutput,
visual, mask, &attr );
if (!data->client_window)
{ {
wine_tsx11_lock();
XDeleteContext( display, data->whole_window, winContext );
XDestroyWindow( display, data->whole_window ); XDestroyWindow( display, data->whole_window );
data->whole_window = 0; data->whole_window = 0;
wine_tsx11_unlock(); wine_tsx11_unlock();
return 0; return 0;
} }
XMapWindow( display, data->client_window );
XSaveContext( display, data->whole_window, winContext, (char *)data->hwnd );
XSaveContext( display, data->client_window, winContext, (char *)data->hwnd );
wine_tsx11_unlock();
xim = x11drv_thread_data()->xim; xim = x11drv_thread_data()->xim;
if (xim) data->xic = X11DRV_CreateIC( xim, display, data->whole_window ); if (xim) data->xic = X11DRV_CreateIC( xim, display, data->whole_window );
@ -1202,7 +1216,6 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
X11DRV_set_wm_hints( display, data ); X11DRV_set_wm_hints( display, data );
SetPropA( data->hwnd, whole_window_prop, (HANDLE)data->whole_window ); SetPropA( data->hwnd, whole_window_prop, (HANDLE)data->whole_window );
SetPropA( data->hwnd, client_window_prop, (HANDLE)data->client_window );
/* set the window text */ /* set the window text */
if (!InternalGetWindowText( data->hwnd, text, sizeof(text)/sizeof(WCHAR) )) text[0] = 0; if (!InternalGetWindowText( data->hwnd, text, sizeof(text)/sizeof(WCHAR) )) text[0] = 0;