summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorРуслан Ижбулатов <lrn1986@gmail.com>2018-04-24 15:14:23 +0000
committerРуслан Ижбулатов <lrn1986@gmail.com>2018-04-24 15:14:23 +0000
commit3ed269633ba155459b5a09ea9de0acd26270567f (patch)
tree04f943b6b0e9973b135133e74e726663f4841afc
parentf2964b0930629c9cf59d5939871a4031c55fd765 (diff)
downloadgtk+-wip/otte/cairo-context.tar.gz
GDK W32: Switch to GdkCairoContextwip/otte/cairo-context
* 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
-rw-r--r--gdk/win32/gdkcairocontext-win32.c302
-rw-r--r--gdk/win32/gdkcairocontext-win32.h26
-rw-r--r--gdk/win32/gdkdrag-win32.c4
-rw-r--r--gdk/win32/gdkevents-win32.c5
-rw-r--r--gdk/win32/gdkprivate-win32.h7
-rw-r--r--gdk/win32/gdksurface-win32.c459
-rw-r--r--gdk/win32/gdksurface-win32.h11
7 files changed, 386 insertions, 428 deletions
diff --git a/gdk/win32/gdkcairocontext-win32.c b/gdk/win32/gdkcairocontext-win32.c
index e7be8fc85c..5868a270ed 100644
--- a/gdk/win32/gdkcairocontext-win32.c
+++ b/gdk/win32/gdkcairocontext-win32.c
@@ -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;
}
diff --git a/gdk/win32/gdkcairocontext-win32.h b/gdk/win32/gdkcairocontext-win32.h
index c1a6ac53cc..69b5522ffe 100644
--- a/gdk/win32/gdkcairocontext-win32.h
+++ b/gdk/win32/gdkcairocontext-win32.h
@@ -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
diff --git a/gdk/win32/gdkdrag-win32.c b/gdk/win32/gdkdrag-win32.c
index 0d4c40aaa3..556239ae33 100644
--- a/gdk/win32/gdkdrag-win32.c
+++ b/gdk/win32/gdkdrag-win32.c
@@ -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);
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 685c5df185..102b75155e 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -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);
}
}
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index 28d410320d..57905f998e 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -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
diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c
index fc5a2fe943..f0e6def13d 100644
--- a/gdk/win32/gdksurface-win32.c
+++ b/gdk/win32/gdksurface-win32.c
@@ -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;
@@ -290,195 +277,6 @@ gdk_win32_get_window_client_area_rect (GdkSurface *window,
}
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);
+ _gdk_win32_get_window_client_area_rect (window, impl->surface_scale, &window_rect);
+ _gdk_win32_update_layered_window_from_cache (window, &window_rect, TRUE, TRUE, TRUE);
}
return;
@@ -5476,80 +5285,6 @@ gdk_win32_surface_show_window_menu (GdkSurface *window,
return TRUE;
}
-/**
- * _gdk_win32_acquire_dc
- * @impl: a Win32 #GdkSurfaceImplWin32 implementation
- *
- * Gets a DC with the given drawable selected into it.
- *
- * Returns: The DC, on success. Otherwise
- * %NULL. If this function succeeded
- * _gdk_win32_impl_release_dc() must be called
- * release the DC when you are done using it.
- **/
-static HDC
-_gdk_win32_impl_acquire_dc (GdkSurfaceImplWin32 *impl)
-{
- if (GDK_IS_SURFACE_IMPL_WIN32 (impl) &&
- GDK_SURFACE_DESTROYED (impl->wrapper))
- return NULL;
-
- /* We don't call this function for layered windows, but
- * in case we do...
- */
- if (impl->layered)
- return NULL;
-
- if (!impl->hdc)
- {
- impl->hdc = GetDC (impl->handle);
- if (!impl->hdc)
- WIN32_GDI_FAILED ("GetDC");
- }
-
- if (impl->hdc)
- {
- impl->hdc_count++;
- return impl->hdc;
- }
- else
- {
- return NULL;
- }
-}
-
-/**
- * _gdk_win32_impl_release_dc
- * @impl: a Win32 #GdkSurfaceImplWin32 implementation
- *
- * Releases the reference count for the DC
- * from _gdk_win32_impl_acquire_dc()
- **/
-static void
-_gdk_win32_impl_release_dc (GdkSurfaceImplWin32 *impl)
-{
- if (impl->layered)
- return;
-
- g_return_if_fail (impl->hdc_count > 0);
-
- impl->hdc_count--;
- if (impl->hdc_count == 0)
- {
- if (impl->saved_dc_bitmap)
- {
- GDI_CALL (SelectObject, (impl->hdc, impl->saved_dc_bitmap));
- impl->saved_dc_bitmap = NULL;
- }
-
- if (impl->hdc)
- {
- GDI_CALL (ReleaseDC, (impl->handle, impl->hdc));
- impl->hdc = NULL;
- }
- }
-}
-
HWND
gdk_win32_surface_get_impl_hwnd (GdkSurface *window)
{
@@ -5562,118 +5297,6 @@ static void
gdk_win32_cairo_surface_destroy (void *data)
{
GdkSurfaceImplWin32 *impl = data;
-
- _gdk_win32_impl_release_dc (impl);
- impl->cairo_surface = NULL;
-}
-
-static cairo_surface_t *
-gdk_win32_ref_cairo_surface_layered (GdkSurface *window,
- GdkSurfaceImplWin32 *impl)
-{
- gint width, height;
- RECT window_rect;
-
- 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);
-
- width = window_rect.right - window_rect.left;
- height = window_rect.bottom - window_rect.top;
-
- if (width > impl->dib_width ||
- height > impl->dib_height)
- {
- cairo_surface_t *new_cache;
- cairo_t *cr;
-
- /* Create larger cache surface, copy old cache surface over it */
- new_cache = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
- width,
- height);
-
- if (impl->cache_surface)
- {
- 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,
- impl->surface_scale,
- impl->surface_scale);
-
- if (impl->cairo_surface)
- cairo_surface_destroy (impl->cairo_surface);
-
- impl->cairo_surface = NULL;
- }
-
- /* This is separate, because cairo_surface gets killed
- * off frequently by outside code, whereas cache_surface
- * is only killed by us, above.
- */
- if (!impl->cairo_surface)
- {
- impl->cairo_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
- width,
- height);
- impl->dib_width = width;
- impl->dib_height = height;
-
- cairo_surface_set_device_scale (impl->cairo_surface,
- impl->surface_scale,
- impl->surface_scale);
-
- cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
- impl, gdk_win32_cairo_surface_destroy);
- }
- else
- {
- cairo_surface_reference (impl->cairo_surface);
- }
-
- return impl->cairo_surface;
-}
-
-static cairo_surface_t *
-gdk_win32_ref_cairo_surface (GdkSurface *window)
-{
- GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
- if (GDK_IS_SURFACE_IMPL_WIN32 (impl) &&
- GDK_SURFACE_DESTROYED (impl->wrapper))
- return NULL;
-
- if (impl->layered)
- return gdk_win32_ref_cairo_surface_layered (window, impl);
-
- if (!impl->cairo_surface)
- {
- HDC hdc = _gdk_win32_impl_acquire_dc (impl);
- if (!hdc)
- return NULL;
-
- impl->cairo_surface = cairo_win32_surface_create_with_format (hdc, CAIRO_FORMAT_ARGB32);
- cairo_surface_set_device_scale (impl->cairo_surface,
- impl->surface_scale,
- impl->surface_scale);
-
- cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
- impl, gdk_win32_cairo_surface_destroy);
- }
- else
- cairo_surface_reference (impl->cairo_surface);
-
- return impl->cairo_surface;
}
BOOL WINAPI
@@ -5876,8 +5499,6 @@ gdk_surface_impl_win32_class_init (GdkSurfaceImplWin32Class *klass)
object_class->dispose = gdk_surface_impl_win32_dispose;
object_class->finalize = gdk_surface_impl_win32_finalize;
- impl_class->ref_cairo_surface = gdk_win32_ref_cairo_surface;
-
impl_class->show = gdk_win32_surface_show;
impl_class->hide = gdk_win32_surface_hide;
impl_class->withdraw = gdk_win32_surface_withdraw;
@@ -5893,8 +5514,6 @@ gdk_surface_impl_win32_class_init (GdkSurfaceImplWin32Class *klass)
impl_class->input_shape_combine_region = gdk_win32_input_shape_combine_region;
impl_class->destroy = gdk_win32_surface_destroy;
- impl_class->begin_paint = gdk_win32_surface_begin_paint;
- impl_class->end_paint = gdk_win32_surface_end_paint;
//impl_class->beep = gdk_x11_surface_beep;
diff --git a/gdk/win32/gdksurface-win32.h b/gdk/win32/gdksurface-win32.h
index a4a88f6948..a0e7309eab 100644
--- a/gdk/win32/gdksurface-win32.h
+++ b/gdk/win32/gdksurface-win32.h
@@ -291,7 +291,6 @@ struct _GdkSurfaceImplWin32
* UpdateLayeredWindow() doesn't do partial redraws.
*/
cairo_surface_t *cache_surface;
- cairo_surface_t *cairo_surface;
/* Unlike window-backed surfaces, DIB-backed surface
* does not provide a way to query its size,
@@ -365,6 +364,16 @@ void _gdk_win32_surface_update_style_bits (GdkSurface *window);
gint _gdk_win32_surface_get_scale_factor (GdkSurface *window);
+void _gdk_win32_get_window_client_area_rect (GdkSurface *window,
+ gint scale,
+ RECT *rect);
+void _gdk_win32_update_layered_window_from_cache (GdkSurface *window,
+ RECT *client_rect,
+ gboolean do_move,
+ gboolean do_resize,
+ gboolean do_paint);
+
+
G_END_DECLS
#endif /* __GDK_SURFACE_WIN32_H__ */