winex11: Switch to an ARGB visual for layered windows with per-pixel alpha.

oldstable
Alexandre Julliard 2012-09-26 13:12:17 +02:00
parent 8dcbeff760
commit f12c1c6630
4 changed files with 105 additions and 35 deletions

View File

@ -833,6 +833,8 @@ static void X11DRV_Expose( HWND hwnd, XEvent *xev )
data->surface->funcs->lock( data->surface );
add_bounds_rect( data->surface->funcs->get_bounds( data->surface ), &rect );
data->surface->funcs->unlock( data->surface );
if (data->vis.visualid != default_visual.visualid)
data->surface->funcs->flush( data->surface );
}
if (event->window != root_window)

View File

@ -1083,6 +1083,8 @@ static void map_window( HWND hwnd, DWORD new_style )
sync_window_style( data );
XMapWindow( data->display, data->whole_window );
XFlush( data->display );
if (data->surface && data->vis.visualid != default_visual.visualid)
data->surface->funcs->flush( data->surface );
}
else set_xembed_flags( data, XEMBED_MAPPED );
@ -1457,6 +1459,22 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des
}
/**********************************************************************
* set_window_visual
*
* Change the visual by destroying and recreating the X window if needed.
*/
void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis )
{
if (data->vis.visualid == vis->visualid) return;
destroy_whole_window( data, FALSE );
if (data->surface) window_surface_release( data->surface );
data->surface = NULL;
data->vis = *vis;
create_whole_window( data );
}
/*****************************************************************
* SetWindowText (X11DRV.@)
*/
@ -1490,6 +1508,7 @@ void CDECL X11DRV_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style )
if (offset == GWL_EXSTYLE && (changed & WS_EX_LAYERED)) /* changing WS_EX_LAYERED resets attributes */
{
set_window_visual( data, &default_visual );
sync_window_opacity( data->display, data->whole_window, 0, 0, 0 );
if (data->surface) set_surface_color_key( data->surface, CLR_INVALID );
}
@ -2096,9 +2115,12 @@ void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags
data->window_rect = *rectWindow;
data->whole_rect = *visible_rect;
data->client_rect = *rectClient;
if (surface) window_surface_add_ref( surface );
if (data->surface) window_surface_release( data->surface );
data->surface = surface;
if (data->vis.visualid == default_visual.visualid)
{
if (surface) window_surface_add_ref( surface );
if (data->surface) window_surface_release( data->surface );
data->surface = surface;
}
TRACE( "win %p window %s client %s style %08x flags %08x\n",
hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style, swp_flags );
@ -2204,6 +2226,9 @@ void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags
}
XFlush( data->display ); /* make sure changes are done before we start painting again */
if (data->surface && data->vis.visualid != default_visual.visualid)
data->surface->funcs->flush( data->surface );
done:
release_win_data( data );
}
@ -2337,40 +2362,64 @@ void CDECL X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alph
BOOL CDECL X11DRV_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
const RECT *window_rect )
{
BYTE alpha = 0xff;
struct window_surface *surface;
struct x11drv_win_data *data;
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
COLORREF color_key = (info->dwFlags & ULW_COLORKEY) ? info->crKey : CLR_INVALID;
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
BITMAPINFO *bmi = (BITMAPINFO *)buffer;
void *src_bits, *dst_bits;
RECT rect;
HDC hdc = 0;
HBITMAP dib;
BOOL ret = FALSE;
if (info->hdcSrc)
if (!(data = get_win_data( hwnd ))) return FALSE;
set_window_visual( data, &argb_visual );
rect = *window_rect;
OffsetRect( &rect, -window_rect->left, -window_rect->top );
surface = data->surface;
if (!surface || memcmp( &surface->rect, &rect, sizeof(RECT) ))
{
HDC hdc = GetWindowDC( hwnd );
if (hdc)
{
int x = 0, y = 0;
RECT rect;
GetWindowRect( hwnd, &rect );
OffsetRect( &rect, -rect.left, -rect.top);
if (info->pptSrc)
{
x = info->pptSrc->x;
y = info->pptSrc->y;
}
if (!info->prcDirty || (info->prcDirty && IntersectRect(&rect, &rect, info->prcDirty)))
{
TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
}
ReleaseDC( hwnd, hdc );
}
data->surface = create_surface( data->whole_window, &data->vis, &rect, color_key );
if (surface) window_surface_release( surface );
surface = data->surface;
}
else set_surface_color_key( surface, color_key );
if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
TRACE( "setting window %p alpha %u\n", hwnd, alpha );
X11DRV_SetLayeredWindowAttributes( hwnd, info->crKey, alpha,
info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
return TRUE;
release_win_data( data );
if (!surface) return FALSE;
if (!info->hdcSrc) return TRUE;
if (info->prcDirty && !IntersectRect( &rect, &rect, info->prcDirty )) return TRUE;
dst_bits = surface->funcs->get_info( surface, bmi );
if (!(dib = CreateDIBSection( info->hdcDst, bmi, DIB_RGB_COLORS, &src_bits, NULL, 0 ))) goto done;
if (!(hdc = CreateCompatibleDC( 0 ))) goto done;
SelectObject( hdc, dib );
if (!(ret = GdiAlphaBlend( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
info->hdcSrc,
rect.left + (info->pptSrc ? info->pptSrc->x : 0),
rect.top + (info->pptSrc ? info->pptSrc->y : 0),
rect.right - rect.left, rect.bottom - rect.top,
(info->dwFlags & ULW_ALPHA) ? *info->pblend : blend )))
goto done;
surface->funcs->lock( surface );
memcpy( dst_bits, src_bits, bmi->bmiHeader.biSizeImage );
add_bounds_rect( surface->funcs->get_bounds( surface ), &rect );
surface->funcs->unlock( surface );
surface->funcs->flush( surface );
done:
if (hdc) DeleteDC( hdc );
if (dib) DeleteObject( dib );
return ret;
}

View File

@ -345,6 +345,7 @@ static inline size_t get_property_size( int format, unsigned long count )
}
extern XVisualInfo default_visual DECLSPEC_HIDDEN;
extern XVisualInfo argb_visual DECLSPEC_HIDDEN;
extern Colormap default_colormap DECLSPEC_HIDDEN;
extern XPixmapFormatValues **pixmap_formats DECLSPEC_HIDDEN;
extern Window root_window DECLSPEC_HIDDEN;
@ -569,6 +570,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( HWND hwnd ) 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;
extern void update_systray_balloon_position(void) DECLSPEC_HIDDEN;
extern HWND create_foreign_window( Display *display, Window window ) DECLSPEC_HIDDEN;

View File

@ -57,6 +57,7 @@ WINE_DECLARE_DEBUG_CHANNEL(synchronous);
WINE_DECLARE_DEBUG_CHANNEL(winediag);
XVisualInfo default_visual = { 0 };
XVisualInfo argb_visual = { 0 };
Colormap default_colormap = None;
XPixmapFormatValues **pixmap_formats;
unsigned int screen_width;
@ -510,8 +511,24 @@ static void init_visuals( Display *display, int screen )
default_visual.colormap_size = default_visual.visual->map_entries;
default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
}
default_colormap = XCreateColormap( gdi_display, root_window, default_visual.visual, AllocNone );
TRACE( "default visual %lx class %u\n", default_visual.visualid, default_visual.class );
default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
argb_visual.screen = screen;
argb_visual.class = TrueColor;
argb_visual.depth = 32;
argb_visual.red_mask = 0xff0000;
argb_visual.green_mask = 0x00ff00;
argb_visual.blue_mask = 0x0000ff;
if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
&argb_visual, &count )))
{
argb_visual = *info;
XFree( info );
}
TRACE( "default visual %lx class %u argb %lx\n",
default_visual.visualid, default_visual.class, argb_visual.visualid );
}
/***********************************************************************