Commit 7002f08c authored by LRN's avatar LRN Committed by Benjamin Otte

GDK W32: Switch to GdkCairoContext

* Remove DC refcounting (we trust GDK to always do
  begin_frame/end_frame calls in pairs)
* Now that there's no GDK-provided double-buffer up the stack,
  double-buffering is implemented here
  (though it's disabled by default - in my tests it didn't provide
   any visual improvements, but did decrease performance).
* For some reason delaying window resizes until the point where
  we need to blit the double-buffer into the window leads
  to visual glitches, so doulbe-buffered windows are resized
  in begin_frame, same as non-double-buffered ones.
* New code to clear the paint region, for all drawing modes.
  Hopefully, it isn't duplicated anywhere up the stack.
* GL has its own context now, so remove any GL-related comments.
* Layered windows are still used (because cairo actually works
  better with them)
* A bit more code re-use for layered windows
* Some functions that were local to gdksurface-win32.c are made
  usable for the whole backend
* Drag-indicator drawing is temporarily commented out to match
  a similar change in X11 backend
parent 8c5d31d1
......@@ -21,16 +21,318 @@
#include "gdkconfig.h"
#include "gdkcairocontext-win32.h"
#include "gdkprivate-win32.h"
#include "gdksurface-win32.h"
#include "gdkwin32misc.h"
#include <cairo-win32.h>
#include <Windows.h>
G_DEFINE_TYPE (GdkWin32CairoContext, gdk_win32_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
static void
gdk_win32_surface_get_queued_window_rect (GdkSurface *surface,
gint scale,
RECT *return_window_rect)
{
RECT window_rect;
GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (surface->impl);
_gdk_win32_get_window_client_area_rect (surface, scale, &window_rect);
/* Turn client area into window area */
_gdk_win32_adjust_client_rect (surface, &window_rect);
/* Convert GDK screen coordinates to W32 desktop coordinates */
window_rect.left -= _gdk_offset_x * impl->surface_scale;
window_rect.right -= _gdk_offset_x * impl->surface_scale;
window_rect.top -= _gdk_offset_y * impl->surface_scale;
window_rect.bottom -= _gdk_offset_y * impl->surface_scale;
*return_window_rect = window_rect;
}
static void
gdk_win32_surface_apply_queued_move_resize (GdkSurface *surface,
RECT window_rect)
{
if (!IsIconic (GDK_SURFACE_HWND (surface)))
{
GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (surface->impl);
GDK_NOTE (EVENTS, g_print ("Setting window position ... "));
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (surface),
SWP_NOZORDER_SPECIFIED,
window_rect.left, window_rect.top,
window_rect.right - window_rect.left,
window_rect.bottom - window_rect.top,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW));
GDK_NOTE (EVENTS, g_print (" ... set window position\n"));
return;
}
/* Don't move iconic windows */
/* TODO: use SetWindowPlacement() to change non-minimized window position */
}
static cairo_surface_t *
create_cairo_surface_for_layered_window (GdkSurfaceImplWin32 *impl,
gint width,
gint height,
gint scale)
{
if (width > impl->dib_width ||
height > impl->dib_height)
{
cairo_surface_t *new_cache;
impl->dib_width = MAX (impl->dib_width, MAX (width, 1));
impl->dib_height = MAX (impl->dib_height, MAX (height, 1));
/* Create larger cache surface, copy old cache surface over it */
new_cache = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
impl->dib_width,
impl->dib_height);
if (impl->cache_surface)
{
cairo_t *cr = cairo_create (new_cache);
cairo_set_source_surface (cr, impl->cache_surface, 0, 0);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
cairo_destroy (cr);
cairo_surface_flush (new_cache);
cairo_surface_destroy (impl->cache_surface);
}
impl->cache_surface = new_cache;
cairo_surface_set_device_scale (impl->cache_surface,
scale,
scale);
}
return cairo_surface_reference (impl->cache_surface);
}
static cairo_surface_t *
create_cairo_surface_for_surface (GdkSurface *surface,
int scale)
{
GdkDisplay *display;
cairo_surface_t *cairo_surface;
HDC hdc;
display = gdk_surface_get_display (surface);
hdc = GetDC (GDK_SURFACE_HWND (surface));
if (!hdc)
{
WIN32_GDI_FAILED ("GetDC");
return NULL;
}
cairo_surface = cairo_win32_surface_create_with_format (hdc, CAIRO_FORMAT_ARGB32);
cairo_surface_set_device_scale (cairo_surface, scale, scale);
return cairo_surface;
}
static void
gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region)
{
GdkWin32CairoContext *self = GDK_WIN32_CAIRO_CONTEXT (draw_context);
GdkRectangle clip_box;
GdkSurface *surface;
double sx, sy;
GdkSurfaceImplWin32 *impl;
int scale;
cairo_t *cr;
gint width, height;
RECT queued_window_rect;
surface = gdk_draw_context_get_surface (draw_context);
impl = GDK_SURFACE_IMPL_WIN32 (surface->impl);
scale = gdk_surface_get_scale_factor (surface);
self->layered = impl->layered;
gdk_win32_surface_get_queued_window_rect (surface, scale, &queued_window_rect);
/* Apply queued resizes for non-double-buffered and non-layered windows
* before painting them (we paint on the window DC directly,
* it must have the right size).
* Due to some poorly-undetstood issue delayed
* resizing of double-buffered windows can produce weird
* artefacts, so these are also resized before we paint.
*/
if (impl->drag_move_resize_context.native_move_resize_pending &&
!self->layered)
{
impl->drag_move_resize_context.native_move_resize_pending = FALSE;
gdk_win32_surface_apply_queued_move_resize (surface, queued_window_rect);
}
width = queued_window_rect.right - queued_window_rect.left;
height = queued_window_rect.bottom - queued_window_rect.top;
width = MAX (width, 1);
height = MAX (height, 1);
if (self->layered)
self->window_surface = create_cairo_surface_for_layered_window (impl, width, height, scale);
else
self->window_surface = create_cairo_surface_for_surface (surface, scale);
if (self->layered ||
!self->double_buffered)
{
/* Layered windows paint on the window_surface (which is itself
* an in-memory cache that the window maintains, since layered windows
* do not support incremental redraws.
* Non-double-buffered windows paint on the window surface directly
* as well.
*/
self->paint_surface = cairo_surface_reference (self->window_surface);
}
else
{
if (width > self->db_width ||
height > self->db_height)
{
self->db_width = MAX (width, self->db_width);
self->db_height = MAX (height, self->db_height);
g_clear_pointer (&self->db_surface, cairo_surface_destroy);
self->db_surface = gdk_surface_create_similar_surface (surface,
cairo_surface_get_content (self->window_surface),
self->db_width,
self->db_height);
}
/* Double-buffered windows paint on a DB surface.
* Due to performance concerns we don't recreate it unless forced to.
*/
self->paint_surface = cairo_surface_reference (self->db_surface);
}
/* Clear the paint region.
* For non-double-buffered and for layered rendering we must
* clear it, otherwise semi-transparent pixels will "add up"
* with each repaint.
* For double-buffered rendering we must clear the old pixels
* from the DB cache surface that we're going to use as a buffer.
*/
cr = cairo_create (self->paint_surface);
cairo_set_source_rgba (cr, 0, 0, 0, 00);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
gdk_cairo_region (cr, region);
cairo_clip (cr);
cairo_paint (cr);
cairo_destroy (cr);
}
static void
gdk_win32_cairo_context_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted,
cairo_region_t *damage)
{
GdkWin32CairoContext *self = GDK_WIN32_CAIRO_CONTEXT (draw_context);
GdkSurface *surface;
gint scale;
GdkSurfaceImplWin32 *impl;
surface = gdk_draw_context_get_surface (draw_context);
scale = gdk_surface_get_scale_factor (surface);
impl = GDK_SURFACE_IMPL_WIN32 (surface->impl);
/* The code to resize double-buffered windows immediately
* before blitting the buffer contents onto them used
* to be here.
*/
/* Layered windows have their own, special copying section
* further down. For double-buffered windows we need to blit
* the DB buffer contents into the window itself.
*/
if (!self->layered &&
self->double_buffered)
{
cairo_t *cr;
cr = cairo_create (self->window_surface);
cairo_set_source_surface (cr, self->paint_surface, 0, 0);
gdk_cairo_region (cr, painted);
cairo_clip (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
cairo_destroy (cr);
}
cairo_surface_flush (self->window_surface);
/* Update layered window, updating its contents, size and position
* in one call.
*/
if (self->layered)
{
RECT client_rect;
/* Get the position/size of the window that GDK wants. */
_gdk_win32_get_window_client_area_rect (surface, scale, &client_rect);
_gdk_win32_update_layered_window_from_cache (surface, &client_rect, TRUE, TRUE, TRUE);
}
g_clear_pointer (&self->paint_surface, cairo_surface_destroy);
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
}
static cairo_t *
gdk_win32_cairo_context_cairo_create (GdkCairoContext *context)
{
GdkWin32CairoContext *self = GDK_WIN32_CAIRO_CONTEXT (context);
return cairo_create (self->paint_surface);
}
static void
gdk_win32_cairo_context_finalize (GObject *object)
{
GdkWin32CairoContext *self = GDK_WIN32_CAIRO_CONTEXT (object);
g_clear_pointer (&self->db_surface, cairo_surface_destroy);
G_OBJECT_CLASS (gdk_win32_cairo_context_parent_class)->finalize (object);
}
static void
gdk_win32_cairo_context_class_init (GdkWin32CairoContextClass *klass)
{
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gdk_win32_cairo_context_finalize;
draw_context_class->begin_frame = gdk_win32_cairo_context_begin_frame;
draw_context_class->end_frame = gdk_win32_cairo_context_end_frame;
cairo_context_class->cairo_create = gdk_win32_cairo_context_cairo_create;
}
static void
gdk_win32_cairo_context_init (GdkWin32CairoContext *self)
{
self->double_buffered = g_strcmp0 (g_getenv ("GDK_WIN32_CAIRO_DB"), "1") == 0;
self->db_width = -1;
self->db_height = -1;
}
......@@ -38,6 +38,32 @@ typedef struct _GdkWin32CairoContextClass GdkWin32CairoContextClass;
struct _GdkWin32CairoContext
{
GdkCairoContext parent_instance;
/* Set to TRUE when double-buffering is used.
* Layered windows use their own, custom double-buffering
* code that is unaffected by this flag.
*/
guint double_buffered : 1;
/* Re-set to the same value as GdkSurfaceImplWin32->layered
* every frame (since layeredness can change at runtime).
*/
guint layered : 1;
/* The a surface for double-buffering. We keep it
* around between repaints, and only re-allocate it
* if it's too small. */
cairo_surface_t *db_surface;
gint db_width;
gint db_height;
/* Surface for the window DC (in non-layered mode).
* A reference of the cache surface (in layered mode). */
cairo_surface_t *window_surface;
/* A reference to db_surface (when double-buffering).
* When not using double-buffering or in layered mode
* this is a reference to window_surface.
*/
cairo_surface_t *paint_surface;
};
struct _GdkWin32CairoContextClass
......
......@@ -2405,6 +2405,7 @@ gdk_win32_drag_context_drop_done (GdkDragContext *context,
return;
}
/*
win_surface = _gdk_surface_ref_cairo_surface (win32_context->drag_surface);
surface = gdk_surface_create_similar_surface (win32_context->drag_surface,
cairo_surface_get_content (win_surface),
......@@ -2416,14 +2417,13 @@ gdk_win32_drag_context_drop_done (GdkDragContext *context,
cairo_destroy (cr);
cairo_surface_destroy (win_surface);
/*
pattern = cairo_pattern_create_for_surface (surface);
gdk_surface_set_background_pattern (win32_context->drag_surface, pattern);
cairo_pattern_destroy (pattern);
*/
cairo_surface_destroy (surface);
*/
anim = g_slice_new0 (GdkDragAnim);
g_set_object (&anim->context, win32_context);
......
......@@ -1794,11 +1794,6 @@ handle_dpi_changed (GdkSurface *window,
cairo_surface_set_device_scale (impl->cache_surface,
impl->surface_scale,
impl->surface_scale);
if (impl->cairo_surface != NULL)
cairo_surface_set_device_scale (impl->cairo_surface,
impl->surface_scale,
impl->surface_scale);
}
}
......
......@@ -128,6 +128,13 @@ GdkWin32Screen *GDK_SURFACE_SCREEN(GObject *win);
#define GDK_SURFACE_IS_WIN32(win) (GDK_IS_SURFACE_IMPL_WIN32 (win->impl))
/* Use this for hWndInsertAfter (2nd argument to SetWindowPos()) if
* SWP_NOZORDER flag is used. Otherwise it's unobvious why a particular
* argument is used. Using NULL is misleading, because
* NULL is equivalent to HWND_TOP.
*/
#define SWP_NOZORDER_SPECIFIED HWND_TOP
typedef struct _GdkWin32SingleFont GdkWin32SingleFont;
struct _GdkWin32SingleFont
......
......@@ -84,13 +84,6 @@ struct _AeroSnapEdgeRegion
typedef struct _AeroSnapEdgeRegion AeroSnapEdgeRegion;
/* Use this for hWndInsertAfter (2nd argument to SetWindowPos()) if
* SWP_NOZORDER flag is used. Otherwise it's unobvious why a particular
* argument is used. Using NULL is misleading, because
* NULL is equivalent to HWND_TOP.
*/
#define SWP_NOZORDER_SPECIFIED HWND_TOP
/* Size of the regions at the edges of the desktop where
* snapping can take place (in pixels)
*/
......@@ -261,22 +254,16 @@ gdk_surface_impl_win32_finalize (GObject *object)
surface_impl->cache_surface = NULL;
}
if (surface_impl->cairo_surface)
{
cairo_surface_destroy (surface_impl->cairo_surface);
surface_impl->cairo_surface = NULL;
}
g_assert (surface_impl->transient_owner == NULL);
g_assert (surface_impl->transient_children == NULL);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gdk_win32_get_window_client_area_rect (GdkSurface *window,
gint scale,
RECT *rect)
void
_gdk_win32_get_window_client_area_rect (GdkSurface *window,
gint scale,
RECT *rect)
{
gint x, y, width, height;
......@@ -289,195 +276,6 @@ gdk_win32_get_window_client_area_rect (GdkSurface *window,
rect->bottom = rect->top + height * scale;
}
static void
gdk_win32_surface_get_queued_window_rect (GdkSurface *window,
RECT *return_window_rect)
{
RECT window_rect;
GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
gdk_win32_get_window_client_area_rect (window, impl->surface_scale, &window_rect);
/* Turn client area into window area */
_gdk_win32_adjust_client_rect (window, &window_rect);
/* Convert GDK screen coordinates to W32 desktop coordinates */
window_rect.left -= _gdk_offset_x * impl->surface_scale;
window_rect.right -= _gdk_offset_x * impl->surface_scale;
window_rect.top -= _gdk_offset_y * impl->surface_scale;
window_rect.bottom -= _gdk_offset_y * impl->surface_scale;
*return_window_rect = window_rect;
}
static void
gdk_win32_surface_apply_queued_move_resize (GdkSurface *window,
RECT window_rect)
{
if (!IsIconic (GDK_SURFACE_HWND (window)))
{
GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
GDK_NOTE (EVENTS, g_print ("Setting window position ... "));
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
SWP_NOZORDER_SPECIFIED,
window_rect.left, window_rect.top,
window_rect.right - window_rect.left,
window_rect.bottom - window_rect.top,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW));
GDK_NOTE (EVENTS, g_print (" ... set window position\n"));
return;
}
/* Don't move iconic windows */
/* TODO: use SetWindowPlacement() to change non-minimized window position */
}
static gboolean
gdk_win32_surface_begin_paint (GdkSurface *window)
{
GdkSurfaceImplWin32 *impl;
RECT window_rect;
if (window == NULL || GDK_SURFACE_DESTROYED (window))
return TRUE;
impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
/* Layered windows are moved *after* repaint.
* We supply our own surface, return FALSE to make GDK use it.
*/
if (impl->layered)
return FALSE;
/* FIXME: Possibly remove the following lines when we transition to GL
* drawing fully. This will probably mean that we won't
* be able to use layered windows, as layered windows seem
* to support only up to OpenGL 1.1, which is not enough for our
* needs here.
*/
/* Non-GL windows are moved *after* repaint.
* We don't supply our own surface, return TRUE to make GDK create
* one by itself.
*//*
if (!window->current_paint.use_gl)
return TRUE;*/
/* GL windows are moved *before* repaint (otherwise
* repainting doesn't work), but if there's no move queued up,
* return immediately. Doesn't matter what we return, GDK
* will create a surface anyway, as if we returned TRUE.
*/
if (!impl->drag_move_resize_context.native_move_resize_pending)
return TRUE;
impl->drag_move_resize_context.native_move_resize_pending = FALSE;
/* Get the position/size of the window that GDK wants,
* apply it.
*/
gdk_win32_surface_get_queued_window_rect (window, &window_rect);
gdk_win32_surface_apply_queued_move_resize (window, window_rect);
return TRUE;
}
static void
gdk_win32_surface_end_paint (GdkSurface *window)
{
/* FIXME: Possibly make gdk_win32_surface_end_paint() a
* no-op stub, like what is done in Wayland, as
* the items here rely on layered window usage,
* when we transition to full GL drawing, as
* layered windows do not support enough GL
* for our needs here
*/
GdkSurfaceImplWin32 *impl;
RECT window_rect;
HDC hdc;
POINT window_position;
SIZE window_size;
POINT source_point;
BLENDFUNCTION blender;
cairo_t *cr;
if (window == NULL || GDK_SURFACE_DESTROYED (window))
return;
impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
/* GL windows are moved *before* repaint */
/*if (window->current_paint.use_gl)
return;*/
/* No move/resize is queued up, and we don't need to update
* the contents of a layered window, so return immediately.
*/
if (!impl->layered &&
!impl->drag_move_resize_context.native_move_resize_pending)
return;
impl->drag_move_resize_context.native_move_resize_pending = FALSE;
/* Get the position/size of the window that GDK wants. */
gdk_win32_surface_get_queued_window_rect (window, &window_rect);
if (!impl->layered)
{
gdk_win32_surface_apply_queued_move_resize (window, window_rect);
return;
}
window_position.x = window_rect.left;
window_position.y = window_rect.top;
window_size.cx = window_rect.right - window_rect.left;
window_size.cy = window_rect.bottom - window_rect.top;
cairo_surface_flush (impl->cairo_surface);
/* we always draw in the top-left corner of the surface */
source_point.x = source_point.y = 0;
blender.BlendOp = AC_SRC_OVER;
blender.BlendFlags = 0;
blender.AlphaFormat = AC_SRC_ALPHA;
blender.SourceConstantAlpha = impl->layered_opacity * 255;
/* Update cache surface contents */
cr = cairo_create (impl->cache_surface);
cairo_set_source_surface (cr, window->current_paint.surface, 0, 0);
gdk_cairo_region (cr, window->current_paint.region);
cairo_clip (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
cairo_destroy (cr);
cairo_surface_flush (impl->cache_surface);
hdc = cairo_win32_surface_get_dc (impl->cache_surface);
/* Don't use UpdateLayeredWindow on minimized windows */
if (IsIconic (GDK_SURFACE_HWND (window)))
{
gdk_win32_surface_apply_queued_move_resize (window, window_rect);
return;
}
/* Move, resize and redraw layered window in one call */
API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (window), NULL,
&window_position, &window_size,
hdc, &source_point,
0, &blender, ULW_ALPHA));
}
static void
gdk_win32_impl_frame_clock_after_paint (GdkFrameClock *clock,
GdkSurface *surface)
......@@ -4586,9 +4384,12 @@ gdk_win32_get_window_size_and_position_from_client_rect (GdkSurface *window,
window_size->cy = window_rect->bottom - window_rect->top;
}
static void
gdk_win32_update_layered_window_from_cache (GdkSurface *window,
RECT *client_rect)
void
_gdk_win32_update_layered_window_from_cache (GdkSurface *surface,
RECT *client_rect,
gboolean do_move,
gboolean do_resize,
gboolean do_paint)
{
POINT window_position;
SIZE window_size;
......@@ -4599,9 +4400,9 @@ gdk_win32_update_layered_window_from_cache (GdkSurface *window,
POINT *source_point_ptr;
GdkSurfaceImplWin32 *impl;
impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
impl = GDK_SURFACE_IMPL_WIN32 (surface->impl);
gdk_win32_get_window_size_and_position_from_client_rect (window,
gdk_win32_get_window_size_and_position_from_client_rect (surface,
client_rect,
&window_size,
&window_position);
......@@ -4611,31 +4412,39 @@ gdk_win32_update_layered_window_from_cache (GdkSurface *window,
blender.AlphaFormat = AC_SRC_ALPHA;
blender.SourceConstantAlpha = impl->layered_opacity * 255;
/* Size didn't change, so move immediately, no need to wait for redraw */
/* Strictly speaking, we don't need to supply hdc, source_point and
* window_size here. However, without these arguments
* window_size to just move the window. However, without these arguments
* the window moves but does not update its contents on Windows 7 when
* desktop composition is off. This forces us to provide hdc and
* source_point. window_size is here to avoid the function
* inexplicably failing with error 317.
*/
if (gdk_display_is_composited (gdk_surface_get_display (window)))
{
hdc = NULL;
window_size_ptr = NULL;
source_point_ptr = NULL;
}
else
hdc = cairo_win32_surface_get_dc (impl->cache_surface);
window_size_ptr = &window_size;
source_point_ptr = &source_point;
if (gdk_display_is_composited (gdk_surface_get_display (surface)))
{
hdc = cairo_win32_surface_get_dc (impl->cache_surface);
window_size_ptr = &window_size;
source_point_ptr = &source_point;
if (!do_paint)
hdc = NULL;
if (!do_resize)
window_size_ptr = NULL;
if (!do_move)
source_point_ptr = NULL;
}
API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (window), NULL,
&window_position, window_size_ptr,
hdc, source_point_ptr,
0, &blender, ULW_ALPHA));
/* Don't use UpdateLayeredWindow on minimized windows */
if (IsIconic (GDK_SURFACE_HWND (surface)))
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (surface),
SWP_NOZORDER_SPECIFIED,
window_position.x, window_position.y,
window_size.cx, window_size.cy,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW));
else
API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (surface), NULL,
&window_position, window_size_ptr,
hdc, source_point_ptr,
0, &blender, ULW_ALPHA));
}
void
......@@ -4820,7 +4629,7 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
if (impl->layered)
{
gdk_win32_update_layered_window_from_cache (window, &new_rect);
_gdk_win32_update_layered_window_from_cache (window, &new_rect, TRUE, FALSE, FALSE);
}
else
{
......@@ -5413,8 +5222,8 @@ gdk_win32_surface_set_opacity (GdkSurface *window,
impl->layered_opacity = opacity;
gdk_win32_get_window_client_area_rect (window, impl->surface_scale, &window_rect);
gdk_win32_update_layered_window_from_cache (window, &window_rect);