GDK/Win32: Remove layered windows usage

In GTK4, we are now defaulting to the OpenGL renderer with the Cairo renderer
only used as a fallback, so there is no point keeping the code paths that use
layered windows as layered windows do not work well with OpenGL nor Vulkan.
This commit is contained in:
Chun-wei Fan 2020-11-05 16:24:40 +08:00
parent 6aa893e091
commit 7b47e3225b
9 changed files with 27 additions and 330 deletions

View File

@ -31,46 +31,6 @@
G_DEFINE_TYPE (GdkWin32CairoContext, gdk_win32_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
static cairo_surface_t *
create_cairo_surface_for_layered_window (GdkWin32Surface *impl,
int width,
int height,
int 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)
@ -114,22 +74,11 @@ gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
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);
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);
}
if (!self->double_buffered)
/* Non-double-buffered windows paint on the window surface directly */
self->paint_surface = cairo_surface_reference (self->window_surface);
else
{
if (width > self->db_width ||
@ -153,11 +102,10 @@ gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
}
/* 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.
* For non-double-buffered rendering we must clear it, otherwise
* semi-transparent pixels will "add up" with each repaint.
* We must also 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);
@ -184,12 +132,10 @@ gdk_win32_cairo_context_end_frame (GdkDrawContext *draw_context,
* to be here.
*/
/* Layered windows have their own, special copying section
* further down. For double-buffered windows we need to blit
/* For double-buffered windows we need to blit
* the DB buffer contents into the window itself.
*/
if (!self->layered &&
self->double_buffered)
if (self->double_buffered)
{
cairo_t *cr;
@ -207,18 +153,6 @@ gdk_win32_cairo_context_end_frame (GdkDrawContext *draw_context,
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);
}

View File

@ -44,10 +44,6 @@ struct _GdkWin32CairoContext
* 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
@ -56,12 +52,11 @@ struct _GdkWin32CairoContext
int db_width;
int db_height;
/* Surface for the window DC (in non-layered mode).
* A reference of the cache surface (in layered mode). */
/* Surface for the window DC */
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.
* When not using double-buffering this is a reference
* to window_surface.
*/
cairo_surface_t *paint_surface;
};

View File

@ -2113,7 +2113,6 @@ gdk_drag_anim_timeout (gpointer data)
(drag->start_y - drag->util_data.last_y) * t -
drag->hot_y);
gdk_win32_surface_move (drag->drag_surface, x, y);
gdk_win32_surface_set_opacity (drag->drag_surface, 1.0 - f);
return G_SOURCE_CONTINUE;
}

View File

@ -1495,15 +1495,6 @@ handle_dpi_changed (GdkSurface *window,
monitor = gdk_display_get_monitor_at_surface (display, window);
gdk_monitor_set_scale_factor (monitor, impl->surface_scale);
if (impl->layered)
{
/* We only need to set the cairo surface device scale here ourselves for layered windows */
if (impl->cache_surface != NULL)
cairo_surface_set_device_scale (impl->cache_surface,
impl->surface_scale,
impl->surface_scale);
}
}
_gdk_win32_adjust_client_rect (window, rect);

View File

@ -88,19 +88,6 @@ _gdk_win32_gl_context_dispose (GObject *gobject)
#endif
}
if (surface != NULL)
{
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
if (impl->suppress_layered > 0)
impl->suppress_layered--;
/* If we don't have any surface that forces layered windows off,
* trigger update_style_bits() to enable layered windows again
*/
if (impl->suppress_layered == 0)
_gdk_win32_surface_update_style_bits (surface);
}
G_OBJECT_CLASS (gdk_win32_gl_context_parent_class)->dispose (gobject);
}
@ -1001,17 +988,6 @@ gdk_win32_gl_context_realize (GdkGLContext *context,
/* set whether we are using GLES */
gdk_gl_context_set_use_es (context, use_es);
/* OpenGL does not work with WS_EX_LAYERED enabled, so we need to
* disable WS_EX_LAYERED when we acquire a valid HGLRC
*/
impl->suppress_layered++;
/* if this is the first time a GL context is acquired for the surface,
* disable layered windows by triggering update_style_bits()
*/
if (impl->suppress_layered == 1)
_gdk_win32_surface_update_style_bits (surface);
/* Ensure that any other context is created with a legacy bit set */
gdk_gl_context_set_is_legacy (context, legacy_bit);

View File

@ -351,7 +351,6 @@ _gdk_win32_surface_exstyle_to_string (LONG style)
BIT (CONTEXTHELP);
BIT (CONTROLPARENT);
BIT (DLGMODALFRAME);
BIT (LAYERED);
BIT (LAYOUTRTL);
BIT (LEFTSCROLLBAR);
BIT (MDICHILD);

View File

@ -275,7 +275,6 @@ _gdk_win32_adjust_client_rect (GdkSurface *window,
gboolean
_gdk_win32_surface_enable_transparency (GdkSurface *window)
{
GdkWin32Surface *impl;
DWM_BLURBEHIND blur_behind;
HRGN empty_region;
HRESULT call_result;
@ -284,12 +283,6 @@ _gdk_win32_surface_enable_transparency (GdkSurface *window)
if (window == NULL || GDK_SURFACE_HWND (window) == NULL)
return FALSE;
impl = GDK_WIN32_SURFACE (window);
/* layered windows don't need blurbehind for transparency */
if (impl->layered)
return TRUE;
if (!gdk_display_is_composited (gdk_surface_get_display (window)))
return FALSE;
@ -526,9 +519,6 @@ _gdk_win32_display_create_surface (GdkDisplay *display,
surface->width = width;
surface->height = height;
impl->layered = FALSE;
impl->layered_opacity = 1.0;
impl->surface_scale = _gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL, NULL);
impl->unscaled_width = width * impl->surface_scale;
impl->unscaled_height = height * impl->surface_scale;
@ -1761,11 +1751,6 @@ update_single_bit (LONG *style,
* Returns TRUE if window has no decorations.
* Usually it means CSD windows, because GTK
* calls gdk_surface_set_decorations (window, 0);
* This is used to decide whether a toplevel should
* be made layered, thus it
* only returns TRUE for toplevels (until GTK minimal
* system requirements are lifted to Windows 8 or newer,
* because only toplevels can be layered).
*/
gboolean
_gdk_win32_surface_lacks_wm_decorations (GdkSurface *window)
@ -1859,27 +1844,6 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window)
new_exstyle &= ~WS_EX_TOOLWINDOW;
}
/* We can get away with using layered windows
* only when no decorations are needed. It can mean
* CSD or borderless non-CSD windows (tooltips?).
*
* If this window cannot use layered windows, disable it always.
* This currently applies to windows using OpenGL, which
* does not work with layered windows.
*/
if (impl->suppress_layered == 0)
{
if (_gdk_win32_surface_lacks_wm_decorations (window))
impl->layered = g_strcmp0 (g_getenv ("GDK_WIN32_LAYERED"), "0") != 0;
}
else
impl->layered = FALSE;
if (impl->layered)
new_exstyle |= WS_EX_LAYERED;
else
new_exstyle &= ~WS_EX_LAYERED;
if (get_effective_window_decorations (window, &decorations))
{
all = (decorations & GDK_DECOR_ALL);
@ -3811,67 +3775,6 @@ gdk_win32_get_window_size_and_position_from_client_rect (GdkSurface *window,
window_size->cy = window_rect->bottom - window_rect->top;
}
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;
BLENDFUNCTION blender;
HDC hdc;
SIZE *window_size_ptr;
POINT source_point = { 0, 0 };
POINT *source_point_ptr;
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
gdk_win32_get_window_size_and_position_from_client_rect (surface,
client_rect,
&window_size,
&window_position);
blender.BlendOp = AC_SRC_OVER;
blender.BlendFlags = 0;
blender.AlphaFormat = AC_SRC_ALPHA;
blender.SourceConstantAlpha = impl->layered_opacity * 255;
/* Strictly speaking, we don't need to supply hdc, source_point and
* 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.
*/
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)))
{
if (!do_paint)
hdc = NULL;
if (!do_resize)
window_size_ptr = NULL;
if (!do_move)
source_point_ptr = NULL;
}
/* 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
gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
int x,
@ -4058,30 +3961,23 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
(rect.left != new_rect.left ||
rect.top != new_rect.top))
{
SIZE window_size;
POINT window_position;
context->native_move_resize_pending = FALSE;
gdk_surface_request_layout (window);
if (impl->layered)
{
_gdk_win32_update_layered_window_from_cache (window, &new_rect, TRUE, FALSE, FALSE);
}
else
{
SIZE window_size;
POINT window_position;
gdk_win32_get_window_size_and_position_from_client_rect (window,
&new_rect,
&window_size,
&window_position);
gdk_win32_get_window_size_and_position_from_client_rect (window,
&new_rect,
&window_size,
&window_position);
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
SWP_NOZORDER_SPECIFIED,
window_position.x, window_position.y,
0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
}
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
SWP_NOZORDER_SPECIFIED,
window_position.x, window_position.y,
0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
}
if (context->op == GDK_WIN32_DRAGOP_RESIZE ||
@ -4355,61 +4251,6 @@ gdk_win32_surface_lookup_for_display (GdkDisplay *display,
return (GdkSurface*) gdk_win32_handle_table_lookup (anid);
}
void
gdk_win32_surface_set_opacity (GdkSurface *window,
double opacity)
{
LONG exstyle;
typedef BOOL (WINAPI *PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
GdkWin32Surface *impl;
g_return_if_fail (GDK_IS_SURFACE (window));
if (GDK_SURFACE_DESTROYED (window))
return;
if (opacity < 0)
opacity = 0;
else if (opacity > 1)
opacity = 1;
impl = GDK_WIN32_SURFACE (window);
if (impl->layered)
{
if (impl->layered_opacity != opacity)
{
RECT window_rect;
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, TRUE, TRUE, TRUE);
}
return;
}
exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
if (!(exstyle & WS_EX_LAYERED))
SetWindowLong (GDK_SURFACE_HWND (window),
GWL_EXSTYLE,
exstyle | WS_EX_LAYERED);
setLayeredWindowAttributes =
(PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
if (setLayeredWindowAttributes)
{
API_CALL (setLayeredWindowAttributes, (GDK_SURFACE_HWND (window),
0,
opacity * 0xff,
LWA_ALPHA));
}
}
gboolean
gdk_win32_surface_is_win32 (GdkSurface *window)
{
@ -4489,9 +4330,6 @@ GtkShowWindow (GdkSurface *window,
if (IsWindowVisible (hwnd))
break;
if ((WS_EX_LAYERED & GetWindowLongPtr (hwnd, GWL_EXSTYLE)) != WS_EX_LAYERED)
break;
/* Window was hidden, will be shown. Erase it, GDK will repaint soon,
* but not soon enough, so it's possible to see old content before
* the next redraw, unless we erase the window first.
@ -5275,7 +5113,6 @@ gdk_win32_surface_apply_queued_move_resize (GdkSurface *surface,
RECT
gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context)
{
GdkWin32CairoContext *cairo_ctx = NULL;
GdkSurface *surface;
GdkWin32Surface *impl;
int scale;
@ -5285,23 +5122,16 @@ gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context)
impl = GDK_WIN32_SURFACE (surface);
scale = gdk_surface_get_scale_factor (surface);
if (GDK_IS_WIN32_CAIRO_CONTEXT (draw_context))
{
cairo_ctx = GDK_WIN32_CAIRO_CONTEXT (draw_context);
cairo_ctx->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
/* Apply queued resizes for non-double-buffered 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 &&
(cairo_ctx == NULL || !cairo_ctx->layered))
if (impl->drag_move_resize_context.native_move_resize_pending)
{
impl->drag_move_resize_context.native_move_resize_pending = FALSE;
gdk_win32_surface_apply_queued_move_resize (surface, queued_window_rect);

View File

@ -277,13 +277,6 @@ struct _GdkWin32Surface
guint zero_shadow : 1;
guint inhibit_configure : 1;
/* Set to TRUE if window is using true layered mode adjustments
* via UpdateLayeredWindow().
* Layered windows that get SetLayeredWindowAttributes() called
* on them are not true layered windows.
*/
guint layered : 1;
/* If TRUE, the @temp_styles is set to the styles that were temporarily
* added to this window.
*/
@ -309,12 +302,6 @@ struct _GdkWin32Surface
int dib_width;
int dib_height;
/* If the client wants uniformly-transparent window,
* we remember the opacity value here and apply it
* during UpdateLayredWindow() call, for layered windows.
*/
double layered_opacity;
HDC hdc;
int hdc_count;
HBITMAP saved_dc_bitmap; /* Original bitmap for dc */
@ -340,9 +327,6 @@ struct _GdkWin32Surface
/* Enable all decorations? */
gboolean decorate_all;
/* No. of windows to force layered windows off */
guint suppress_layered;
/* Temporary styles that this window got for the purpose of
* handling WM_SYSMENU.
* They are removed at the first opportunity (usually WM_INITMENU).
@ -382,11 +366,6 @@ int _gdk_win32_surface_get_scale_factor (GdkSurface *window);
void _gdk_win32_get_window_client_area_rect (GdkSurface *window,
int 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);
void gdk_win32_surface_move (GdkSurface *surface,
int x,

View File

@ -63,12 +63,6 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
NULL,
surface);
if (result == VK_SUCCESS)
win32_surface->suppress_layered ++;
if (win32_surface->suppress_layered == 1)
_gdk_win32_surface_update_style_bits (window);
return result;
}