Commit f12c1c66 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 8dcbeff7
...@@ -833,6 +833,8 @@ static void X11DRV_Expose( HWND hwnd, XEvent *xev ) ...@@ -833,6 +833,8 @@ static void X11DRV_Expose( HWND hwnd, XEvent *xev )
data->surface->funcs->lock( data->surface ); data->surface->funcs->lock( data->surface );
add_bounds_rect( data->surface->funcs->get_bounds( data->surface ), &rect ); add_bounds_rect( data->surface->funcs->get_bounds( data->surface ), &rect );
data->surface->funcs->unlock( data->surface ); data->surface->funcs->unlock( data->surface );
if (data->vis.visualid != default_visual.visualid)
data->surface->funcs->flush( data->surface );
} }
if (event->window != root_window) if (event->window != root_window)
......
...@@ -1083,6 +1083,8 @@ static void map_window( HWND hwnd, DWORD new_style ) ...@@ -1083,6 +1083,8 @@ static void map_window( HWND hwnd, DWORD new_style )
sync_window_style( data ); sync_window_style( data );
XMapWindow( data->display, data->whole_window ); XMapWindow( data->display, data->whole_window );
XFlush( data->display ); 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 ); else set_xembed_flags( data, XEMBED_MAPPED );
...@@ -1457,6 +1459,22 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des ...@@ -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.@) * SetWindowText (X11DRV.@)
*/ */
...@@ -1490,6 +1508,7 @@ void CDECL X11DRV_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ) ...@@ -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 */ 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 ); sync_window_opacity( data->display, data->whole_window, 0, 0, 0 );
if (data->surface) set_surface_color_key( data->surface, CLR_INVALID ); 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 ...@@ -2096,9 +2115,12 @@ void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags
data->window_rect = *rectWindow; data->window_rect = *rectWindow;
data->whole_rect = *visible_rect; data->whole_rect = *visible_rect;
data->client_rect = *rectClient; data->client_rect = *rectClient;
if (data->vis.visualid == default_visual.visualid)
{
if (surface) window_surface_add_ref( surface ); if (surface) window_surface_add_ref( surface );
if (data->surface) window_surface_release( data->surface ); if (data->surface) window_surface_release( data->surface );
data->surface = surface; data->surface = surface;
}
TRACE( "win %p window %s client %s style %08x flags %08x\n", 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 ); 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 ...@@ -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 */ 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: done:
release_win_data( data ); release_win_data( data );
} }
...@@ -2337,40 +2362,64 @@ void CDECL X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alph ...@@ -2337,40 +2362,64 @@ void CDECL X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alph
BOOL CDECL X11DRV_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, BOOL CDECL X11DRV_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
const RECT *window_rect ) 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;
{
HDC hdc = GetWindowDC( hwnd );
if (hdc) set_window_visual( data, &argb_visual );
{
int x = 0, y = 0;
RECT rect;
GetWindowRect( hwnd, &rect ); rect = *window_rect;
OffsetRect( &rect, -rect.left, -rect.top); OffsetRect( &rect, -window_rect->left, -window_rect->top );
if (info->pptSrc)
{
x = info->pptSrc->x;
y = info->pptSrc->y;
}
if (!info->prcDirty || (info->prcDirty && IntersectRect(&rect, &rect, info->prcDirty))) surface = data->surface;
if (!surface || memcmp( &surface->rect, &rect, sizeof(RECT) ))
{ {
TRACE( "copying window %p pos %d,%d\n", hwnd, x, y ); data->surface = create_surface( data->whole_window, &data->vis, &rect, color_key );
BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom, if (surface) window_surface_release( surface );
info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY ); surface = data->surface;
}
ReleaseDC( hwnd, hdc );
}
} }
else set_surface_color_key( surface, color_key );
if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha; release_win_data( data );
TRACE( "setting window %p alpha %u\n", hwnd, alpha );
X11DRV_SetLayeredWindowAttributes( hwnd, info->crKey, alpha, if (!surface) return FALSE;
info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) ); if (!info->hdcSrc) return TRUE;
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;
} }
......
...@@ -345,6 +345,7 @@ static inline size_t get_property_size( int format, unsigned long count ) ...@@ -345,6 +345,7 @@ static inline size_t get_property_size( int format, unsigned long count )
} }
extern XVisualInfo default_visual DECLSPEC_HIDDEN; extern XVisualInfo default_visual DECLSPEC_HIDDEN;
extern XVisualInfo argb_visual DECLSPEC_HIDDEN;
extern Colormap default_colormap DECLSPEC_HIDDEN; extern Colormap default_colormap DECLSPEC_HIDDEN;
extern XPixmapFormatValues **pixmap_formats DECLSPEC_HIDDEN; extern XPixmapFormatValues **pixmap_formats DECLSPEC_HIDDEN;
extern Window root_window DECLSPEC_HIDDEN; extern Window root_window DECLSPEC_HIDDEN;
...@@ -569,6 +570,7 @@ extern Window init_clip_window(void) 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_user_time( Time time ) DECLSPEC_HIDDEN;
extern void update_net_wm_states( struct x11drv_win_data *data ) 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 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 change_systray_owner( Display *display, Window systray_window ) DECLSPEC_HIDDEN;
extern void update_systray_balloon_position(void) DECLSPEC_HIDDEN; extern void update_systray_balloon_position(void) DECLSPEC_HIDDEN;
extern HWND create_foreign_window( Display *display, Window window ) DECLSPEC_HIDDEN; extern HWND create_foreign_window( Display *display, Window window ) DECLSPEC_HIDDEN;
......
...@@ -57,6 +57,7 @@ WINE_DECLARE_DEBUG_CHANNEL(synchronous); ...@@ -57,6 +57,7 @@ WINE_DECLARE_DEBUG_CHANNEL(synchronous);
WINE_DECLARE_DEBUG_CHANNEL(winediag); WINE_DECLARE_DEBUG_CHANNEL(winediag);
XVisualInfo default_visual = { 0 }; XVisualInfo default_visual = { 0 };
XVisualInfo argb_visual = { 0 };
Colormap default_colormap = None; Colormap default_colormap = None;
XPixmapFormatValues **pixmap_formats; XPixmapFormatValues **pixmap_formats;
unsigned int screen_width; unsigned int screen_width;
...@@ -510,8 +511,24 @@ static void init_visuals( Display *display, int screen ) ...@@ -510,8 +511,24 @@ static void init_visuals( Display *display, int screen )
default_visual.colormap_size = default_visual.visual->map_entries; default_visual.colormap_size = default_visual.visual->map_entries;
default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb; default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
} }
default_colormap = XCreateColormap( gdi_display, root_window, default_visual.visual, AllocNone ); default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
TRACE( "default visual %lx class %u\n", default_visual.visualid, default_visual.class );
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 );
} }
/*********************************************************************** /***********************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment