forked from AuroraMiddleware/gtk
window: rework the CSD theming layer
Instead of having three different boxes and style classes, we can just get away with the regular background box, plus a window-frame, which contains the external frame, together with the window drop shadows. GtkWindow now has special code to ensure the backing actual window is allocated big enough to accomodate the shadows (using the shadow size calculations introduced in the previous commit). We also use the margin value to determine the size of the invisible borders (which can then be different than the shadow).
This commit is contained in:
parent
a44d6816d3
commit
7bbbb01ff5
269
gtk/gtkwindow.c
269
gtk/gtkwindow.c
@ -35,6 +35,7 @@
|
||||
#include "gtkwindowprivate.h"
|
||||
#include "gtkaccelgroupprivate.h"
|
||||
#include "gtkbindings.h"
|
||||
#include "gtkcssshadowsvalueprivate.h"
|
||||
#include "gtkkeyhash.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtkmnemonichash.h"
|
||||
@ -6067,68 +6068,65 @@ set_grip_position (GtkWindow *window)
|
||||
}
|
||||
|
||||
static void
|
||||
get_decoration_borders (GtkWidget *widget,
|
||||
GtkBorder *window_border,
|
||||
GtkBorder *outer_border)
|
||||
sum_borders (GtkBorder *one,
|
||||
GtkBorder *two)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GtkStateFlags state;
|
||||
GdkWindow *window;
|
||||
gboolean maximized = FALSE;
|
||||
const GtkBorder empty = { 0 };
|
||||
GtkBorder outer;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
state = gtk_style_context_get_state (context);
|
||||
window = gtk_widget_get_window (widget);
|
||||
if (window != NULL)
|
||||
maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||
|
||||
if (window_border != NULL)
|
||||
{
|
||||
if (maximized)
|
||||
{
|
||||
*window_border = empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_style_context_save (context);
|
||||
gtk_style_context_add_class (context, "window-border");
|
||||
gtk_style_context_get_border (context, state, window_border);
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
}
|
||||
|
||||
if (window_border != NULL || outer_border != NULL)
|
||||
{
|
||||
if (maximized)
|
||||
{
|
||||
outer = empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_style_context_save (context);
|
||||
gtk_style_context_add_class (context, "window-outer-border");
|
||||
gtk_style_context_get_border (context, state, &outer);
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
|
||||
if (outer_border != NULL)
|
||||
{
|
||||
*outer_border = outer;
|
||||
}
|
||||
else
|
||||
{
|
||||
window_border->left += outer.left;
|
||||
window_border->right += outer.right;
|
||||
window_border->top += outer.top;
|
||||
window_border->bottom += outer.bottom;
|
||||
}
|
||||
}
|
||||
one->top += two->top;
|
||||
one->right += two->right;
|
||||
one->bottom += two->bottom;
|
||||
one->left += two->left;
|
||||
}
|
||||
|
||||
static void
|
||||
update_border_windows (GtkWindow *window, GtkBorder *border)
|
||||
get_decoration_size (GtkWidget *widget,
|
||||
GtkBorder *decorations)
|
||||
{
|
||||
GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
|
||||
GtkBorder border = { 0 };
|
||||
GtkBorder margin;
|
||||
GtkStyleContext *context;
|
||||
GtkStateFlags state;
|
||||
GtkCssValue *shadows;
|
||||
|
||||
*decorations = border;
|
||||
|
||||
if (!priv->client_decorated)
|
||||
return;
|
||||
|
||||
if (gtk_window_get_maximized (GTK_WINDOW (widget)))
|
||||
return;
|
||||
|
||||
state = gtk_widget_get_state_flags (widget);
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_save (context);
|
||||
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
|
||||
gtk_style_context_add_class (context, "window-frame");
|
||||
|
||||
/* Always sum border + padding */
|
||||
gtk_style_context_get_border (context, state, decorations);
|
||||
gtk_style_context_get_padding (context, state, &border);
|
||||
sum_borders (decorations, &border);
|
||||
|
||||
/* Calculate the size of the drop shadows ... */
|
||||
shadows = _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BOX_SHADOW);
|
||||
_gtk_css_shadows_value_get_extents (shadows, &border);
|
||||
|
||||
/* ... and compare it to the margin size, which we use for resize grips */
|
||||
gtk_style_context_get_margin (context, state, &margin);
|
||||
|
||||
border.top = MAX (border.top, margin.top);
|
||||
border.right = MAX (border.right, margin.right);
|
||||
border.bottom = MAX (border.bottom, margin.bottom);
|
||||
border.left = MAX (border.left, margin.left);
|
||||
|
||||
sum_borders (decorations, &border);
|
||||
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
|
||||
static void
|
||||
update_border_windows (GtkWindow *window)
|
||||
{
|
||||
GtkWidget *widget = (GtkWidget *)window;
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
@ -6137,10 +6135,20 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
|
||||
cairo_region_t *region;
|
||||
cairo_rectangle_int_t rect;
|
||||
gint width, height;
|
||||
GtkBorder border;
|
||||
GtkStyleContext *context;
|
||||
|
||||
if (priv->border_window[0] == NULL)
|
||||
return;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
gtk_style_context_save (context);
|
||||
gtk_style_context_add_class (context, "window-frame");
|
||||
gtk_style_context_get_margin (context,
|
||||
gtk_widget_get_state_flags (widget),
|
||||
&border);
|
||||
gtk_style_context_restore (context);
|
||||
|
||||
if (!priv->resizable || gtk_window_get_maximized (window))
|
||||
{
|
||||
resize_h = resize_v = FALSE;
|
||||
@ -6165,31 +6173,31 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
|
||||
"decoration-resize-handle", &handle,
|
||||
NULL);
|
||||
|
||||
width = gtk_widget_get_allocated_width (widget) - (border->left + border->right);
|
||||
height = gtk_widget_get_allocated_height (widget) - (border->top + border->bottom);
|
||||
width = gtk_widget_get_allocated_width (widget) - (border.left + border.right);
|
||||
height = gtk_widget_get_allocated_height (widget) - (border.top + border.bottom);
|
||||
|
||||
if (resize_h && resize_v)
|
||||
{
|
||||
gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH_WEST],
|
||||
0, 0,
|
||||
border->left + handle, border->top + handle);
|
||||
border.left + handle, border.top + handle);
|
||||
gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH_EAST],
|
||||
border->left + width - handle, 0,
|
||||
border->right + handle, border->top + handle);
|
||||
border.left + width - handle, 0,
|
||||
border.right + handle, border.top + handle);
|
||||
gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH_WEST],
|
||||
0, border->top + height - handle,
|
||||
border->left + handle, border->bottom + handle);
|
||||
0, border.top + height - handle,
|
||||
border.left + handle, border.bottom + handle);
|
||||
gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH_EAST],
|
||||
border->left + width - handle, border->top + height - handle,
|
||||
border->right + handle, border->bottom + handle);
|
||||
border.left + width - handle, border.top + height - handle,
|
||||
border.right + handle, border.bottom + handle);
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = border->left + handle;
|
||||
rect.height = border->top + handle;
|
||||
rect.width = border.left + handle;
|
||||
rect.height = border.top + handle;
|
||||
region = cairo_region_create_rectangle (&rect);
|
||||
rect.x = border->left;
|
||||
rect.y = border->top;
|
||||
rect.x = border.left;
|
||||
rect.y = border.top;
|
||||
rect.width = handle;
|
||||
rect.height = handle;
|
||||
cairo_region_subtract_rectangle (region, &rect);
|
||||
@ -6199,11 +6207,11 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = border->right + handle;
|
||||
rect.height = border->top + handle;
|
||||
rect.width = border.right + handle;
|
||||
rect.height = border.top + handle;
|
||||
region = cairo_region_create_rectangle (&rect);
|
||||
rect.x = 0;
|
||||
rect.y = border->top;
|
||||
rect.y = border.top;
|
||||
rect.width = handle;
|
||||
rect.height = handle;
|
||||
cairo_region_subtract_rectangle (region, &rect);
|
||||
@ -6213,10 +6221,10 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = border->left + handle;
|
||||
rect.height = border->bottom + handle;
|
||||
rect.width = border.left + handle;
|
||||
rect.height = border.bottom + handle;
|
||||
region = cairo_region_create_rectangle (&rect);
|
||||
rect.x = border->left;
|
||||
rect.x = border.left;
|
||||
rect.y = 0;
|
||||
rect.width = handle;
|
||||
rect.height = handle;
|
||||
@ -6227,8 +6235,8 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = border->right + handle;
|
||||
rect.height = border->bottom + handle;
|
||||
rect.width = border.right + handle;
|
||||
rect.height = border.bottom + handle;
|
||||
region = cairo_region_create_rectangle (&rect);
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
@ -6258,21 +6266,21 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
|
||||
|
||||
if (resize_h)
|
||||
{
|
||||
x = border->left + handle;
|
||||
x = border.left + handle;
|
||||
w = width - 2 * handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0;
|
||||
w = width + border->left + border->right;
|
||||
w = width + border.left + border.right;
|
||||
}
|
||||
|
||||
gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH],
|
||||
x, 0,
|
||||
w, border->top);
|
||||
w, border.top);
|
||||
gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH],
|
||||
x, border->top + height,
|
||||
w, border->bottom);
|
||||
x, border.top + height,
|
||||
w, border.bottom);
|
||||
|
||||
gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_NORTH]);
|
||||
gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_SOUTH]);
|
||||
@ -6289,22 +6297,22 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
|
||||
|
||||
if (resize_v)
|
||||
{
|
||||
y = border->top + handle;
|
||||
y = border.top + handle;
|
||||
h = height - 2 * handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = 0;
|
||||
h = height + border->top + border->bottom;
|
||||
h = height + border.top + border.bottom;
|
||||
}
|
||||
|
||||
gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_WEST],
|
||||
0, y,
|
||||
border->left, h);
|
||||
border.left, h);
|
||||
|
||||
gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_EAST],
|
||||
border->left + width, y,
|
||||
border->right, h);
|
||||
border.left + width, y,
|
||||
border.right, h);
|
||||
|
||||
gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_WEST]);
|
||||
gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_EAST]);
|
||||
@ -6352,7 +6360,7 @@ _gtk_window_set_allocation (GtkWindow *window,
|
||||
|
||||
gtk_widget_set_allocation (widget, allocation);
|
||||
|
||||
get_decoration_borders (widget, &window_border, NULL);
|
||||
get_decoration_size (widget, &window_border);
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
|
||||
|
||||
child_allocation.x = 0;
|
||||
@ -6407,7 +6415,7 @@ _gtk_window_set_allocation (GtkWindow *window,
|
||||
{
|
||||
update_grip_visibility (window);
|
||||
set_grip_position (window);
|
||||
update_border_windows (window, &window_border);
|
||||
update_border_windows (window);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6554,6 +6562,7 @@ gtk_window_style_updated (GtkWidget *widget)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GdkRGBA transparent = { 0.0, 0.0, 0.0, 0.0 };
|
||||
GdkRectangle rect;
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
|
||||
@ -6566,6 +6575,13 @@ gtk_window_style_updated (GtkWidget *widget)
|
||||
|
||||
set_grip_shape (window);
|
||||
}
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
{
|
||||
gdk_window_set_background_rgba (gtk_widget_get_window (widget),
|
||||
&transparent);
|
||||
gtk_widget_queue_resize (widget);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -6783,12 +6799,10 @@ gtk_window_get_resize_grip_area (GtkWindow *window,
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
|
||||
|
||||
if (!window->priv->has_resize_grip)
|
||||
if (!priv->has_resize_grip)
|
||||
return FALSE;
|
||||
|
||||
if (priv->client_decorated)
|
||||
get_decoration_borders (widget, &window_border, NULL);
|
||||
|
||||
get_decoration_size (widget, &window_border);
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
gtk_widget_style_get (widget,
|
||||
@ -7449,7 +7463,7 @@ gtk_window_get_preferred_width (GtkWidget *widget,
|
||||
if (priv->decorated &&
|
||||
!priv->fullscreen)
|
||||
{
|
||||
get_decoration_borders (widget, &window_border, NULL);
|
||||
get_decoration_size (widget, &window_border);
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
gtk_widget_get_preferred_width (priv->title_box,
|
||||
@ -7498,7 +7512,7 @@ gtk_window_get_preferred_width_for_height (GtkWidget *widget,
|
||||
if (priv->decorated &&
|
||||
!priv->fullscreen)
|
||||
{
|
||||
get_decoration_borders (widget, &window_border, NULL);
|
||||
get_decoration_size (widget, &window_border);
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
gtk_widget_get_preferred_width_for_height (priv->title_box,
|
||||
@ -7551,7 +7565,7 @@ gtk_window_get_preferred_height (GtkWidget *widget,
|
||||
if (priv->decorated &&
|
||||
!priv->fullscreen)
|
||||
{
|
||||
get_decoration_borders (widget, &window_border, NULL);
|
||||
get_decoration_size (widget, &window_border);
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
gtk_widget_get_preferred_height (priv->title_box,
|
||||
@ -7602,7 +7616,7 @@ gtk_window_get_preferred_height_for_width (GtkWidget *widget,
|
||||
if (priv->decorated &&
|
||||
!priv->fullscreen)
|
||||
{
|
||||
get_decoration_borders (widget, &window_border, NULL);
|
||||
get_decoration_size (widget, &window_border);
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
gtk_widget_get_preferred_height_for_width (priv->title_box,
|
||||
@ -8827,17 +8841,14 @@ gtk_window_draw (GtkWidget *widget,
|
||||
GtkStyleContext *context;
|
||||
gboolean ret = FALSE;
|
||||
GtkAllocation allocation;
|
||||
GtkBorder inner_border = { 0 };
|
||||
GtkBorder outer_border = { 0 };
|
||||
GtkBorder window_border;
|
||||
gint title_height;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
get_decoration_size (widget, &window_border);
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (priv->client_decorated)
|
||||
get_decoration_borders (widget, &inner_border, &outer_border);
|
||||
|
||||
if (!gtk_widget_get_app_paintable (widget) &&
|
||||
gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
|
||||
{
|
||||
@ -8848,25 +8859,22 @@ gtk_window_draw (GtkWidget *widget,
|
||||
{
|
||||
gtk_style_context_save (context);
|
||||
|
||||
gtk_style_context_add_class (context, "window-border");
|
||||
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
|
||||
gtk_style_context_add_class (context, "window-frame");
|
||||
|
||||
gtk_render_background (context, cr,
|
||||
inner_border.left + outer_border.left,
|
||||
inner_border.top + outer_border.top,
|
||||
window_border.left, window_border.top,
|
||||
allocation.width -
|
||||
(inner_border.left + inner_border.right +
|
||||
outer_border.left + outer_border.right),
|
||||
(window_border.left + window_border.right),
|
||||
allocation.height -
|
||||
(inner_border.top + inner_border.bottom +
|
||||
outer_border.top + outer_border.bottom));
|
||||
(window_border.top + window_border.bottom));
|
||||
gtk_render_frame (context, cr,
|
||||
outer_border.left,
|
||||
outer_border.top,
|
||||
allocation.width - (outer_border.left + outer_border.right),
|
||||
allocation.height - (outer_border.top + outer_border.bottom));
|
||||
gtk_style_context_remove_class (context, "window-border");
|
||||
gtk_style_context_add_class (context, "window-outer-border");
|
||||
gtk_render_frame (context, cr,
|
||||
0, 0, allocation.width, allocation.height);
|
||||
window_border.left, window_border.top,
|
||||
allocation.width -
|
||||
(window_border.left + window_border.right),
|
||||
allocation.height -
|
||||
(window_border.top + window_border.bottom));
|
||||
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
|
||||
@ -8874,20 +8882,23 @@ gtk_window_draw (GtkWidget *widget,
|
||||
title_height = gtk_widget_get_allocated_height (priv->title_box);
|
||||
else
|
||||
title_height = 0;
|
||||
gtk_style_context_save (context);
|
||||
gtk_style_context_add_class (context, "window-content");
|
||||
|
||||
gtk_render_background (context, cr,
|
||||
inner_border.left + outer_border.left,
|
||||
inner_border.top + outer_border.top +
|
||||
title_height,
|
||||
window_border.left,
|
||||
window_border.top + title_height,
|
||||
allocation.width -
|
||||
(inner_border.left + inner_border.right +
|
||||
outer_border.left + outer_border.right),
|
||||
(window_border.left + window_border.right),
|
||||
allocation.height -
|
||||
(inner_border.top + inner_border.bottom +
|
||||
outer_border.top + outer_border.bottom +
|
||||
(window_border.top + window_border.bottom +
|
||||
title_height));
|
||||
gtk_style_context_restore (context);
|
||||
gtk_render_frame (context, cr,
|
||||
window_border.left,
|
||||
window_border.top + title_height,
|
||||
allocation.width -
|
||||
(window_border.left + window_border.right),
|
||||
allocation.height -
|
||||
(window_border.top + window_border.bottom +
|
||||
title_height));
|
||||
}
|
||||
|
||||
if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
|
||||
|
Loading…
Reference in New Issue
Block a user