Merge branch 'wip/otte/boxes' into 'master'

GtkCssBoxes

See merge request GNOME/gtk!584
This commit is contained in:
Matthias Clasen 2019-02-15 16:12:26 +00:00
commit bea1a02edd
32 changed files with 1253 additions and 581 deletions

View File

@ -751,7 +751,6 @@ GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID
gtk_container_add
gtk_container_remove
gtk_container_add_with_properties
gtk_container_check_resize
gtk_container_foreach
gtk_container_get_children
gtk_container_get_path_for_child

View File

@ -961,7 +961,7 @@ gtk_entry_accessible_get_character_extents (AtkText *text,
pango_layout_index_to_pos (gtk_entry_get_layout (entry), index, &char_rect);
pango_extents_to_pixels (&char_rect, NULL);
_gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_allocation (widget, &allocation);
surface = gtk_widget_get_surface (widget);
gdk_surface_get_origin (surface, &x_surface, &y_surface);

View File

@ -176,6 +176,7 @@
#include <gtk/gtkrecentmanager.h>
#include <gtk/gtkrender.h>
#include <gtk/gtkrevealer.h>
#include <gtk/gtkroot.h>
#include <gtk/gtkscale.h>
#include <gtk/gtkscalebutton.h>
#include <gtk/gtkscrollable.h>

View File

@ -34,12 +34,11 @@
#include "gtkpopovermenu.h"
#include "gtkprivate.h"
#include "gtkmarshalers.h"
#include "gtkshortcutssection.h"
#include "gtkshortcutswindow.h"
#include "gtksizerequest.h"
#include "gtkstylecontextprivate.h"
#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
#include "gtkwindowprivate.h"
#include "a11y/gtkcontaineraccessibleprivate.h"
@ -129,7 +128,6 @@ struct _GtkContainerPrivate
enum {
ADD,
REMOVE,
CHECK_RESIZE,
SET_FOCUS_CHILD,
LAST_SIGNAL
};
@ -148,7 +146,6 @@ static void gtk_container_add_unimplemented (GtkContainer *container
GtkWidget *widget);
static void gtk_container_remove_unimplemented (GtkContainer *container,
GtkWidget *widget);
static void gtk_container_real_check_resize (GtkContainer *container);
static void gtk_container_compute_expand (GtkWidget *widget,
gboolean *hexpand_p,
gboolean *vexpand_p);
@ -284,7 +281,6 @@ gtk_container_class_init (GtkContainerClass *class)
class->add = gtk_container_add_unimplemented;
class->remove = gtk_container_remove_unimplemented;
class->check_resize = gtk_container_real_check_resize;
class->forall = NULL;
class->set_focus_child = gtk_container_real_set_focus_child;
class->child_type = NULL;
@ -308,14 +304,6 @@ gtk_container_class_init (GtkContainerClass *class)
NULL,
G_TYPE_NONE, 1,
GTK_TYPE_WIDGET);
container_signals[CHECK_RESIZE] =
g_signal_new (I_("check-resize"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkContainerClass, check_resize),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
container_signals[SET_FOCUS_CHILD] =
g_signal_new (I_("set-focus-child"),
G_OBJECT_CLASS_TYPE (gobject_class),
@ -1397,7 +1385,10 @@ gtk_container_idle_sizer (GdkFrameClock *clock,
*/
if (gtk_widget_needs_allocate (GTK_WIDGET (container)))
{
gtk_container_check_resize (container);
if (GTK_IS_WINDOW (container))
gtk_window_check_resize (GTK_WINDOW (container));
else
g_warning ("gtk_container_idle_sizer() called on a non-window");
}
if (!gtk_container_needs_idle_sizer (container))
@ -1460,44 +1451,6 @@ _gtk_container_queue_restyle (GtkContainer *container)
gtk_container_start_idle_sizer (container);
}
void
gtk_container_check_resize (GtkContainer *container)
{
g_return_if_fail (GTK_IS_CONTAINER (container));
g_signal_emit (container, container_signals[CHECK_RESIZE], 0);
}
static void
gtk_container_real_check_resize (GtkContainer *container)
{
GtkWidget *widget = GTK_WIDGET (container);
GtkAllocation allocation;
GtkRequisition requisition;
int baseline;
if (_gtk_widget_get_alloc_needed (widget))
{
if (!_gtk_widget_is_toplevel (widget))
{
gtk_widget_get_preferred_size (widget, &requisition, NULL);
gtk_widget_get_allocated_size (widget, &allocation, &baseline);
if (allocation.width < requisition.width)
allocation.width = requisition.width;
if (allocation.height < requisition.height)
allocation.height = requisition.height;
gtk_widget_size_allocate (widget, &allocation, baseline);
}
else
gtk_widget_queue_resize (widget);
}
else
{
gtk_widget_ensure_allocate (widget);
}
}
static GtkSizeRequestMode
gtk_container_get_request_mode (GtkWidget *widget)
{

View File

@ -56,7 +56,6 @@ struct _GtkContainer
* @parent_class: The parent class.
* @add: Signal emitted when a widget is added to container.
* @remove: Signal emitted when a widget is removed from container.
* @check_resize: Signal emitted when a size recalculation is needed.
* @forall: Invokes callback on each child of container. The callback handler
* may remove the child.
* @set_focus_child: Sets the focused child of container.
@ -78,7 +77,6 @@ struct _GtkContainerClass
GtkWidget *widget);
void (*remove) (GtkContainer *container,
GtkWidget *widget);
void (*check_resize) (GtkContainer *container);
void (*forall) (GtkContainer *container,
GtkCallback callback,
gpointer callback_data);
@ -125,9 +123,6 @@ GDK_AVAILABLE_IN_ALL
void gtk_container_remove (GtkContainer *container,
GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_container_check_resize (GtkContainer *container);
GDK_AVAILABLE_IN_ALL
void gtk_container_foreach (GtkContainer *container,
GtkCallback callback,

View File

@ -0,0 +1,495 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2019 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_CSS_BOXES_IMPL_PRIVATE_H__
#define __GTK_CSS_BOXES_IMPL_PRIVATE_H__
#include "gtkcssboxesprivate.h"
#include "gtkcsscornervalueprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkwidgetprivate.h"
/* This file is included from gtkcssboxesprivate.h */
static inline void
gtk_css_boxes_init (GtkCssBoxes *boxes,
GtkWidget *widget)
{
GtkWidgetPrivate *priv = widget->priv;
gtk_css_boxes_init_content_box (boxes,
gtk_css_node_get_style (priv->cssnode),
0, 0,
priv->width,
priv->height);
}
static inline void
gtk_css_boxes_init_content_box (GtkCssBoxes *boxes,
GtkCssStyle *style,
double x,
double y,
double width,
double height)
{
memset (boxes, 0, sizeof (GtkCssBoxes));
boxes->style = style;
boxes->box[GTK_CSS_AREA_CONTENT_BOX].bounds = GRAPHENE_RECT_INIT (x, y, width, height);
boxes->has_rect[GTK_CSS_AREA_CONTENT_BOX] = TRUE;
}
static inline void
gtk_css_boxes_init_border_box (GtkCssBoxes *boxes,
GtkCssStyle *style,
double x,
double y,
double width,
double height)
{
memset (boxes, 0, sizeof (GtkCssBoxes));
boxes->style = style;
boxes->box[GTK_CSS_AREA_BORDER_BOX].bounds = GRAPHENE_RECT_INIT (x, y, width, height);
boxes->has_rect[GTK_CSS_AREA_BORDER_BOX] = TRUE;
}
static inline void
gtk_css_boxes_rect_grow (GskRoundedRect *dest,
GskRoundedRect *src,
GtkCssStyle *style,
int top_property,
int right_property,
int bottom_property,
int left_property)
{
double top = _gtk_css_number_value_get (gtk_css_style_get_value (style, top_property), 100);
double right = _gtk_css_number_value_get (gtk_css_style_get_value (style, right_property), 100);
double bottom = _gtk_css_number_value_get (gtk_css_style_get_value (style, bottom_property), 100);
double left = _gtk_css_number_value_get (gtk_css_style_get_value (style, left_property), 100);
dest->bounds.origin.x = src->bounds.origin.x - left;
dest->bounds.origin.y = src->bounds.origin.y - top;
dest->bounds.size.width = src->bounds.size.width + left + right;
dest->bounds.size.height = src->bounds.size.height + top + bottom;
}
static inline void
gtk_css_boxes_rect_shrink (GskRoundedRect *dest,
GskRoundedRect *src,
GtkCssStyle *style,
int top_property,
int right_property,
int bottom_property,
int left_property)
{
double top = _gtk_css_number_value_get (gtk_css_style_get_value (style, top_property), 100);
double right = _gtk_css_number_value_get (gtk_css_style_get_value (style, right_property), 100);
double bottom = _gtk_css_number_value_get (gtk_css_style_get_value (style, bottom_property), 100);
double left = _gtk_css_number_value_get (gtk_css_style_get_value (style, left_property), 100);
/* FIXME: Do we need underflow checks here? */
dest->bounds.origin.x = src->bounds.origin.x + left;
dest->bounds.origin.y = src->bounds.origin.y + top;
dest->bounds.size.width = src->bounds.size.width - left - right;
dest->bounds.size.height = src->bounds.size.height - top - bottom;
}
static inline void gtk_css_boxes_compute_padding_rect (GtkCssBoxes *boxes);
static inline const graphene_rect_t *
gtk_css_boxes_get_rect (GtkCssBoxes *boxes,
GtkCssArea area)
{
switch (area)
{
case GTK_CSS_AREA_BORDER_BOX:
return gtk_css_boxes_get_border_rect (boxes);
case GTK_CSS_AREA_PADDING_BOX:
return gtk_css_boxes_get_padding_rect (boxes);
case GTK_CSS_AREA_CONTENT_BOX:
return gtk_css_boxes_get_content_rect (boxes);
default:
g_assert_not_reached ();
return NULL;
}
}
static inline void
gtk_css_boxes_compute_border_rect (GtkCssBoxes *boxes)
{
if (boxes->has_rect[GTK_CSS_AREA_BORDER_BOX])
return;
gtk_css_boxes_compute_padding_rect (boxes);
gtk_css_boxes_rect_grow (&boxes->box[GTK_CSS_AREA_BORDER_BOX],
&boxes->box[GTK_CSS_AREA_PADDING_BOX],
boxes->style,
GTK_CSS_PROPERTY_BORDER_TOP_WIDTH,
GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH,
GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH);
boxes->has_rect[GTK_CSS_AREA_BORDER_BOX] = TRUE;
}
static inline void
gtk_css_boxes_compute_padding_rect (GtkCssBoxes *boxes)
{
if (boxes->has_rect[GTK_CSS_AREA_PADDING_BOX])
return;
if (boxes->has_rect[GTK_CSS_AREA_BORDER_BOX])
{
gtk_css_boxes_rect_shrink (&boxes->box[GTK_CSS_AREA_PADDING_BOX],
&boxes->box[GTK_CSS_AREA_BORDER_BOX],
boxes->style,
GTK_CSS_PROPERTY_BORDER_TOP_WIDTH,
GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH,
GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH);
}
else
{
gtk_css_boxes_rect_grow (&boxes->box[GTK_CSS_AREA_PADDING_BOX],
&boxes->box[GTK_CSS_AREA_CONTENT_BOX],
boxes->style,
GTK_CSS_PROPERTY_PADDING_TOP,
GTK_CSS_PROPERTY_PADDING_RIGHT,
GTK_CSS_PROPERTY_PADDING_BOTTOM,
GTK_CSS_PROPERTY_PADDING_LEFT);
}
boxes->has_rect[GTK_CSS_AREA_PADDING_BOX] = TRUE;
}
static inline void
gtk_css_boxes_compute_content_rect (GtkCssBoxes *boxes)
{
if (boxes->has_rect[GTK_CSS_AREA_CONTENT_BOX])
return;
gtk_css_boxes_compute_padding_rect (boxes);
gtk_css_boxes_rect_shrink (&boxes->box[GTK_CSS_AREA_CONTENT_BOX],
&boxes->box[GTK_CSS_AREA_PADDING_BOX],
boxes->style,
GTK_CSS_PROPERTY_PADDING_TOP,
GTK_CSS_PROPERTY_PADDING_RIGHT,
GTK_CSS_PROPERTY_PADDING_BOTTOM,
GTK_CSS_PROPERTY_PADDING_LEFT);
boxes->has_rect[GTK_CSS_AREA_CONTENT_BOX] = TRUE;
}
static inline void
gtk_css_boxes_compute_margin_rect (GtkCssBoxes *boxes)
{
if (boxes->has_rect[GTK_CSS_AREA_MARGIN_BOX])
return;
gtk_css_boxes_compute_border_rect (boxes);
gtk_css_boxes_rect_grow (&boxes->box[GTK_CSS_AREA_MARGIN_BOX],
&boxes->box[GTK_CSS_AREA_BORDER_BOX],
boxes->style,
GTK_CSS_PROPERTY_MARGIN_TOP,
GTK_CSS_PROPERTY_MARGIN_RIGHT,
GTK_CSS_PROPERTY_MARGIN_BOTTOM,
GTK_CSS_PROPERTY_MARGIN_LEFT);
boxes->has_rect[GTK_CSS_AREA_MARGIN_BOX] = TRUE;
}
static inline void
gtk_css_boxes_compute_outline_rect (GtkCssBoxes *boxes)
{
graphene_rect_t *dest, *src;
double d;
if (boxes->has_rect[GTK_CSS_AREA_OUTLINE_BOX])
return;
gtk_css_boxes_compute_border_rect (boxes);
dest = &boxes->box[GTK_CSS_AREA_OUTLINE_BOX].bounds;
src = &boxes->box[GTK_CSS_AREA_BORDER_BOX].bounds;
d = _gtk_css_number_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_OFFSET), 100) +
_gtk_css_number_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
dest->origin.x = src->origin.x - d;
dest->origin.y = src->origin.y - d;
dest->size.width = src->size.width + d + d;
dest->size.height = src->size.height + d + d;
boxes->has_rect[GTK_CSS_AREA_OUTLINE_BOX] = TRUE;
}
static inline const graphene_rect_t *
gtk_css_boxes_get_margin_rect (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_margin_rect (boxes);
return &boxes->box[GTK_CSS_AREA_MARGIN_BOX].bounds;
}
static inline const graphene_rect_t *
gtk_css_boxes_get_border_rect (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_border_rect (boxes);
return &boxes->box[GTK_CSS_AREA_BORDER_BOX].bounds;
}
static inline const graphene_rect_t *
gtk_css_boxes_get_padding_rect (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_padding_rect (boxes);
return &boxes->box[GTK_CSS_AREA_PADDING_BOX].bounds;
}
static inline const graphene_rect_t *
gtk_css_boxes_get_content_rect (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_content_rect (boxes);
return &boxes->box[GTK_CSS_AREA_CONTENT_BOX].bounds;
}
static inline const graphene_rect_t *
gtk_css_boxes_get_outline_rect (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_outline_rect (boxes);
return &boxes->box[GTK_CSS_AREA_OUTLINE_BOX].bounds;
}
/* clamp border radius, following CSS specs */
static inline void
gtk_css_boxes_clamp_border_radius (GskRoundedRect *box)
{
gdouble factor = 1.0;
gdouble corners;
corners = box->corner[GSK_CORNER_TOP_LEFT].width + box->corner[GSK_CORNER_TOP_RIGHT].width;
if (corners != 0)
factor = MIN (factor, box->bounds.size.width / corners);
corners = box->corner[GSK_CORNER_TOP_RIGHT].height + box->corner[GSK_CORNER_BOTTOM_RIGHT].height;
if (corners != 0)
factor = MIN (factor, box->bounds.size.height / corners);
corners = box->corner[GSK_CORNER_BOTTOM_RIGHT].width + box->corner[GSK_CORNER_BOTTOM_LEFT].width;
if (corners != 0)
factor = MIN (factor, box->bounds.size.width / corners);
corners = box->corner[GSK_CORNER_TOP_LEFT].height + box->corner[GSK_CORNER_BOTTOM_LEFT].height;
if (corners != 0)
factor = MIN (factor, box->bounds.size.height / corners);
box->corner[GSK_CORNER_TOP_LEFT].width *= factor;
box->corner[GSK_CORNER_TOP_LEFT].height *= factor;
box->corner[GSK_CORNER_TOP_RIGHT].width *= factor;
box->corner[GSK_CORNER_TOP_RIGHT].height *= factor;
box->corner[GSK_CORNER_BOTTOM_RIGHT].width *= factor;
box->corner[GSK_CORNER_BOTTOM_RIGHT].height *= factor;
box->corner[GSK_CORNER_BOTTOM_LEFT].width *= factor;
box->corner[GSK_CORNER_BOTTOM_LEFT].height *= factor;
}
static inline void
gtk_css_boxes_apply_border_radius (GskRoundedRect *box,
const GtkCssValue *top_left,
const GtkCssValue *top_right,
const GtkCssValue *bottom_right,
const GtkCssValue *bottom_left)
{
box->corner[GSK_CORNER_TOP_LEFT].width = _gtk_css_corner_value_get_x (top_left, box->bounds.size.width);
box->corner[GSK_CORNER_TOP_LEFT].height = _gtk_css_corner_value_get_y (top_left, box->bounds.size.height);
box->corner[GSK_CORNER_TOP_RIGHT].width = _gtk_css_corner_value_get_x (top_right, box->bounds.size.width);
box->corner[GSK_CORNER_TOP_RIGHT].height = _gtk_css_corner_value_get_y (top_right, box->bounds.size.height);
box->corner[GSK_CORNER_BOTTOM_RIGHT].width = _gtk_css_corner_value_get_x (bottom_right, box->bounds.size.width);
box->corner[GSK_CORNER_BOTTOM_RIGHT].height = _gtk_css_corner_value_get_y (bottom_right, box->bounds.size.height);
box->corner[GSK_CORNER_BOTTOM_LEFT].width = _gtk_css_corner_value_get_x (bottom_left, box->bounds.size.width);
box->corner[GSK_CORNER_BOTTOM_LEFT].height = _gtk_css_corner_value_get_y (bottom_left, box->bounds.size.height);
gtk_css_boxes_clamp_border_radius (box);
}
/* NB: width and height must be >= 0 */
static inline void
gtk_css_boxes_shrink_border_radius (graphene_size_t *dest,
const graphene_size_t *src,
double width,
double height)
{
dest->width = src->width - width;
dest->height = src->height - height;
if (dest->width <= 0 || dest->height <= 0)
{
dest->width = 0;
dest->height = 0;
}
}
static inline void
gtk_css_boxes_shrink_corners (GskRoundedRect *dest,
const GskRoundedRect *src)
{
double top = dest->bounds.origin.y - src->bounds.origin.y;
double right = src->bounds.origin.x + src->bounds.size.width - dest->bounds.origin.x - dest->bounds.size.width;
double bottom = src->bounds.origin.y + src->bounds.size.height - dest->bounds.origin.y - dest->bounds.size.height;
double left = dest->bounds.origin.x - src->bounds.origin.x;
gtk_css_boxes_shrink_border_radius (&dest->corner[GSK_CORNER_TOP_LEFT],
&src->corner[GSK_CORNER_TOP_LEFT],
top, left);
gtk_css_boxes_shrink_border_radius (&dest->corner[GSK_CORNER_TOP_RIGHT],
&src->corner[GSK_CORNER_TOP_RIGHT],
top, right);
gtk_css_boxes_shrink_border_radius (&dest->corner[GSK_CORNER_BOTTOM_RIGHT],
&src->corner[GSK_CORNER_BOTTOM_RIGHT],
bottom, right);
gtk_css_boxes_shrink_border_radius (&dest->corner[GSK_CORNER_BOTTOM_LEFT],
&src->corner[GSK_CORNER_BOTTOM_LEFT],
bottom, left);
}
static inline void
gtk_css_boxes_compute_border_box (GtkCssBoxes *boxes)
{
if (boxes->has_box[GTK_CSS_AREA_BORDER_BOX])
return;
gtk_css_boxes_compute_border_rect (boxes);
gtk_css_boxes_apply_border_radius (&boxes->box[GTK_CSS_AREA_BORDER_BOX],
gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS),
gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS),
gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS),
gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS));
boxes->has_box[GTK_CSS_AREA_BORDER_BOX] = TRUE;
}
static inline void
gtk_css_boxes_compute_padding_box (GtkCssBoxes *boxes)
{
if (boxes->has_box[GTK_CSS_AREA_PADDING_BOX])
return;
gtk_css_boxes_compute_border_box (boxes);
gtk_css_boxes_compute_padding_rect (boxes);
gtk_css_boxes_shrink_corners (&boxes->box[GTK_CSS_AREA_PADDING_BOX],
&boxes->box[GTK_CSS_AREA_BORDER_BOX]);
boxes->has_box[GTK_CSS_AREA_PADDING_BOX] = TRUE;
}
static inline void
gtk_css_boxes_compute_content_box (GtkCssBoxes *boxes)
{
if (boxes->has_box[GTK_CSS_AREA_CONTENT_BOX])
return;
gtk_css_boxes_compute_padding_box (boxes);
gtk_css_boxes_compute_content_rect (boxes);
gtk_css_boxes_shrink_corners (&boxes->box[GTK_CSS_AREA_CONTENT_BOX],
&boxes->box[GTK_CSS_AREA_PADDING_BOX]);
boxes->has_box[GTK_CSS_AREA_CONTENT_BOX] = TRUE;
}
static inline void
gtk_css_boxes_compute_outline_box (GtkCssBoxes *boxes)
{
if (boxes->has_box[GTK_CSS_AREA_OUTLINE_BOX])
return;
gtk_css_boxes_compute_outline_rect (boxes);
gtk_css_boxes_apply_border_radius (&boxes->box[GTK_CSS_AREA_OUTLINE_BOX],
gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_TOP_LEFT_RADIUS),
gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_TOP_RIGHT_RADIUS),
gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_BOTTOM_RIGHT_RADIUS),
gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_BOTTOM_LEFT_RADIUS));
boxes->has_box[GTK_CSS_AREA_OUTLINE_BOX] = TRUE;
}
static inline const GskRoundedRect *
gtk_css_boxes_get_box (GtkCssBoxes *boxes,
GtkCssArea area)
{
switch (area)
{
case GTK_CSS_AREA_BORDER_BOX:
return gtk_css_boxes_get_border_box (boxes);
case GTK_CSS_AREA_PADDING_BOX:
return gtk_css_boxes_get_padding_box (boxes);
case GTK_CSS_AREA_CONTENT_BOX:
return gtk_css_boxes_get_content_box (boxes);
default:
g_assert_not_reached ();
return NULL;
}
}
static inline const GskRoundedRect *
gtk_css_boxes_get_border_box (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_border_box (boxes);
return &boxes->box[GTK_CSS_AREA_BORDER_BOX];
}
static inline const GskRoundedRect *
gtk_css_boxes_get_padding_box (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_padding_box (boxes);
return &boxes->box[GTK_CSS_AREA_PADDING_BOX];
}
static inline const GskRoundedRect *
gtk_css_boxes_get_content_box (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_content_box (boxes);
return &boxes->box[GTK_CSS_AREA_CONTENT_BOX];
}
static inline const GskRoundedRect *
gtk_css_boxes_get_outline_box (GtkCssBoxes *boxes)
{
gtk_css_boxes_compute_outline_box (boxes);
return &boxes->box[GTK_CSS_AREA_OUTLINE_BOX];
}
#endif /* __GTK_CSS_BOXES_IMPL_PRIVATE_H__ */

91
gtk/gtkcssboxesprivate.h Normal file
View File

@ -0,0 +1,91 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2019 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_CSS_BOXES_PRIVATE_H__
#define __GTK_CSS_BOXES_PRIVATE_H__
#include "gtkcsstypesprivate.h"
G_BEGIN_DECLS
/*
* The idea behind this file is that it provides an on-stack representation
* for all the CSS boxes one can have to deal with in the CSS box model so that
* higher level code can use convenient and readable function calls instead of
* doing complicated math.
*
* However, because computing all those rectangles is prohibitively expensive,
* this struct does it lazily.
* And then we inline all the code, so that whenever we use this struct, the
* compiler can optimize out the parts we don't need in that particular use
* case.
*/
typedef struct _GtkCssBoxes GtkCssBoxes;
/* ahem...
* Let's extend GtkCssArea a bit here. */
#define GTK_CSS_AREA_MARGIN_BOX (3)
#define GTK_CSS_AREA_OUTLINE_BOX (4)
#define GTK_CSS_AREA_N_BOXES (5)
struct _GtkCssBoxes
{
GtkCssStyle *style;
GskRoundedRect box[GTK_CSS_AREA_N_BOXES];
gboolean has_rect[GTK_CSS_AREA_N_BOXES]; /* TRUE if we have initialized just the bounds rect */
gboolean has_box[GTK_CSS_AREA_N_BOXES]; /* TRUE if we have initialized the whole box */
};
static inline void gtk_css_boxes_init (GtkCssBoxes *boxes,
GtkWidget *widget);
static inline void gtk_css_boxes_init_content_box (GtkCssBoxes *boxes,
GtkCssStyle *style,
double x,
double y,
double width,
double height);
static inline void gtk_css_boxes_init_border_box (GtkCssBoxes *boxes,
GtkCssStyle *style,
double x,
double y,
double width,
double height);
static inline const graphene_rect_t * gtk_css_boxes_get_rect (GtkCssBoxes *boxes,
GtkCssArea area);
static inline const graphene_rect_t * gtk_css_boxes_get_margin_rect (GtkCssBoxes *boxes);
static inline const graphene_rect_t * gtk_css_boxes_get_border_rect (GtkCssBoxes *boxes);
static inline const graphene_rect_t * gtk_css_boxes_get_padding_rect (GtkCssBoxes *boxes);
static inline const graphene_rect_t * gtk_css_boxes_get_content_rect (GtkCssBoxes *boxes);
static inline const graphene_rect_t * gtk_css_boxes_get_outline_rect (GtkCssBoxes *boxes);
static inline const GskRoundedRect * gtk_css_boxes_get_box (GtkCssBoxes *boxes,
GtkCssArea area);
static inline const GskRoundedRect * gtk_css_boxes_get_border_box (GtkCssBoxes *boxes);
static inline const GskRoundedRect * gtk_css_boxes_get_padding_box (GtkCssBoxes *boxes);
static inline const GskRoundedRect * gtk_css_boxes_get_content_box (GtkCssBoxes *boxes);
static inline const GskRoundedRect * gtk_css_boxes_get_outline_box (GtkCssBoxes *boxes);
G_END_DECLS
#endif /* __GTK_CSS_BOXES_PRIVATE_H__ */
/* and finally include the actual code for the functions */
#include "gtkcssboxesimplprivate.h"

View File

@ -106,28 +106,28 @@ void gtk_css_node_insert_before (GtkCssNode *
GtkCssNode *cssnode,
GtkCssNode *next_sibling);
GtkCssNode * gtk_css_node_get_parent (GtkCssNode *cssnode);
GtkCssNode * gtk_css_node_get_first_child (GtkCssNode *cssnode);
GtkCssNode * gtk_css_node_get_last_child (GtkCssNode *cssnode);
GtkCssNode * gtk_css_node_get_previous_sibling(GtkCssNode *cssnode);
GtkCssNode * gtk_css_node_get_next_sibling (GtkCssNode *cssnode);
GtkCssNode * gtk_css_node_get_parent (GtkCssNode *cssnode) G_GNUC_PURE;
GtkCssNode * gtk_css_node_get_first_child (GtkCssNode *cssnode) G_GNUC_PURE;
GtkCssNode * gtk_css_node_get_last_child (GtkCssNode *cssnode) G_GNUC_PURE;
GtkCssNode * gtk_css_node_get_previous_sibling(GtkCssNode *cssnode) G_GNUC_PURE;
GtkCssNode * gtk_css_node_get_next_sibling (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_set_visible (GtkCssNode *cssnode,
gboolean visible);
gboolean gtk_css_node_get_visible (GtkCssNode *cssnode);
gboolean gtk_css_node_get_visible (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_set_name (GtkCssNode *cssnode,
/*interned*/const char*name);
/*interned*/const char *gtk_css_node_get_name (GtkCssNode *cssnode);
/*interned*/const char *gtk_css_node_get_name (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_set_widget_type (GtkCssNode *cssnode,
GType widget_type);
GType gtk_css_node_get_widget_type (GtkCssNode *cssnode);
GType gtk_css_node_get_widget_type (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_set_id (GtkCssNode *cssnode,
/*interned*/const char*id);
/*interned*/const char *gtk_css_node_get_id (GtkCssNode *cssnode);
/*interned*/const char *gtk_css_node_get_id (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_set_state (GtkCssNode *cssnode,
GtkStateFlags state_flags);
GtkStateFlags gtk_css_node_get_state (GtkCssNode *cssnode);
GtkStateFlags gtk_css_node_get_state (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_set_classes (GtkCssNode *cssnode,
const char **classes);
char ** gtk_css_node_get_classes (GtkCssNode *cssnode);
@ -136,13 +136,13 @@ void gtk_css_node_add_class (GtkCssNode *
void gtk_css_node_remove_class (GtkCssNode *cssnode,
GQuark style_class);
gboolean gtk_css_node_has_class (GtkCssNode *cssnode,
GQuark style_class);
GQuark style_class) G_GNUC_PURE;
const GQuark * gtk_css_node_list_classes (GtkCssNode *cssnode,
guint *n_classes);
const GtkCssNodeDeclaration *
gtk_css_node_get_declaration (GtkCssNode *cssnode);
GtkCssStyle * gtk_css_node_get_style (GtkCssNode *cssnode);
gtk_css_node_get_declaration (GtkCssNode *cssnode) G_GNUC_PURE;
GtkCssStyle * gtk_css_node_get_style (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_invalidate_style_provider
@ -157,8 +157,8 @@ void gtk_css_node_validate (GtkCssNode *
gboolean gtk_css_node_init_matcher (GtkCssNode *cssnode,
GtkCssMatcher *matcher);
GtkWidgetPath * gtk_css_node_create_widget_path (GtkCssNode *cssnode);
const GtkWidgetPath * gtk_css_node_get_widget_path (GtkCssNode *cssnode);
GtkStyleProvider * gtk_css_node_get_style_provider (GtkCssNode *cssnode);
const GtkWidgetPath * gtk_css_node_get_widget_path (GtkCssNode *cssnode) G_GNUC_PURE;
GtkStyleProvider * gtk_css_node_get_style_provider (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_print (GtkCssNode *cssnode,
GtkStyleContextPrintFlags flags,

View File

@ -61,8 +61,8 @@ gboolean gtk_css_number_value_can_parse (GtkCssParser *par
GtkCssValue * _gtk_css_number_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags);
GtkCssDimension gtk_css_number_value_get_dimension (const GtkCssValue *value);
gboolean gtk_css_number_value_has_percent (const GtkCssValue *value);
GtkCssDimension gtk_css_number_value_get_dimension (const GtkCssValue *value) G_GNUC_PURE;
gboolean gtk_css_number_value_has_percent (const GtkCssValue *value) G_GNUC_PURE;
GtkCssValue * gtk_css_number_value_multiply (const GtkCssValue *value,
double factor);
GtkCssValue * gtk_css_number_value_add (GtkCssValue *value1,
@ -72,7 +72,7 @@ GtkCssValue * gtk_css_number_value_try_add (const GtkCssValue *val
gint gtk_css_number_value_get_calc_term_order (const GtkCssValue *value);
double _gtk_css_number_value_get (const GtkCssValue *number,
double one_hundred_percent);
double one_hundred_percent) G_GNUC_PURE;
G_END_DECLS

View File

@ -28,7 +28,7 @@ G_BEGIN_DECLS
GtkCssValue * _gtk_css_rgba_value_new_from_rgba (const GdkRGBA *rgba);
const GdkRGBA * _gtk_css_rgba_value_get_rgba (const GtkCssValue *rgba);
const GdkRGBA * _gtk_css_rgba_value_get_rgba (const GtkCssValue *rgba) G_GNUC_PURE;
G_END_DECLS

View File

@ -61,13 +61,13 @@ struct _GtkCssStyleClass
GType gtk_css_style_get_type (void) G_GNUC_CONST;
GtkCssValue * gtk_css_style_get_value (GtkCssStyle *style,
guint id);
guint id) G_GNUC_PURE;
GtkCssSection * gtk_css_style_get_section (GtkCssStyle *style,
guint id);
guint id) G_GNUC_PURE;
GtkBitmask * gtk_css_style_add_difference (GtkBitmask *accumulated,
GtkCssStyle *style,
GtkCssStyle *other);
gboolean gtk_css_style_is_static (GtkCssStyle *style);
gboolean gtk_css_style_is_static (GtkCssStyle *style) G_GNUC_PURE;
char * gtk_css_style_to_string (GtkCssStyle *style);
gboolean gtk_css_style_print (GtkCssStyle *style,

View File

@ -23,11 +23,13 @@
*/
#include "config.h"
#include <gdk/gdk.h>
#include "gtkinvisibleprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkroot.h"
#include "gtkwidgetprivate.h"
/**
@ -69,7 +71,24 @@ static void gtk_invisible_get_property (GObject *object,
GParamSpec *pspec);
static void gtk_invisible_constructed (GObject *object);
G_DEFINE_TYPE_WITH_PRIVATE (GtkInvisible, gtk_invisible, GTK_TYPE_WIDGET)
static GdkDisplay *
gtk_invisible_root_get_display (GtkRoot *root)
{
GtkInvisible *invisible = GTK_INVISIBLE (root);
return invisible->priv->display;
}
static void
gtk_invisible_root_interface_init (GtkRootInterface *iface)
{
iface->get_display = gtk_invisible_root_get_display;
}
G_DEFINE_TYPE_WITH_CODE (GtkInvisible, gtk_invisible, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkInvisible)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
gtk_invisible_root_interface_init))
static void
gtk_invisible_class_init (GtkInvisibleClass *class)
@ -107,7 +126,6 @@ gtk_invisible_init (GtkInvisible *invisible)
priv = invisible->priv;
gtk_widget_set_has_surface (GTK_WIDGET (invisible), TRUE);
_gtk_widget_set_is_toplevel (GTK_WIDGET (invisible), TRUE);
g_object_ref_sink (invisible);
@ -201,22 +219,6 @@ gtk_invisible_set_display (GtkInvisible *invisible,
gtk_widget_realize (widget);
}
/**
* gtk_invisible_get_display:
* @invisible: a #GtkInvisible.
*
* Returns the #GdkDisplay object associated with @invisible
*
* Returns: (transfer none): the associated #GdkDisplay.
**/
GdkDisplay *
gtk_invisible_get_display (GtkInvisible *invisible)
{
g_return_val_if_fail (GTK_IS_INVISIBLE (invisible), NULL);
return invisible->priv->display;
}
static void
gtk_invisible_realize (GtkWidget *widget)
{

View File

@ -74,8 +74,6 @@ GtkWidget* gtk_invisible_new_for_display(GdkDisplay *display);
GDK_AVAILABLE_IN_ALL
void gtk_invisible_set_display (GtkInvisible *invisible,
GdkDisplay *display);
GDK_AVAILABLE_IN_ALL
GdkDisplay*gtk_invisible_get_display (GtkInvisible *invisible);
G_END_DECLS

View File

@ -1382,8 +1382,6 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
_gtk_widget_set_is_toplevel (plug, TRUE);
gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
op_win32->embed_widget = plug;
gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget);

View File

@ -25,6 +25,7 @@
#include "gtkcssarrayvalueprivate.h"
#include "gtkcssbgsizevalueprivate.h"
#include "gtkcssboxesprivate.h"
#include "gtkcsscornervalueprivate.h"
#include "gtkcssenumvalueprivate.h"
#include "gtkcssimagevalueprivate.h"
@ -47,49 +48,43 @@
*/
#include "fallback-c89.c"
typedef struct _GtkThemingBackground GtkThemingBackground;
#define N_BOXES (3)
struct _GtkThemingBackground {
GtkCssStyle *style;
GskRoundedRect boxes[N_BOXES];
};
static void
gtk_theming_background_snapshot_color (const GtkThemingBackground *bg,
GtkSnapshot *snapshot,
const GdkRGBA *bg_color,
const GtkCssValue *background_image)
gtk_theming_background_snapshot_color (GtkCssBoxes *boxes,
GtkSnapshot *snapshot,
const GdkRGBA *bg_color,
const GtkCssValue *background_image)
{
gint n_values = _gtk_css_array_value_get_n_values (background_image);
GtkCssArea clip = _gtk_css_area_value_get
const GskRoundedRect *box;
gint n_values;
GtkCssArea clip;
n_values = _gtk_css_array_value_get_n_values (background_image);
clip = _gtk_css_area_value_get
(_gtk_css_array_value_get_nth
(gtk_css_style_get_value (bg->style, GTK_CSS_PROPERTY_BACKGROUND_CLIP),
(gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BACKGROUND_CLIP),
n_values - 1));
box = gtk_css_boxes_get_box (boxes, clip);
if (gsk_rounded_rect_is_rectilinear (&bg->boxes[clip]))
if (gsk_rounded_rect_is_rectilinear (box))
{
gtk_snapshot_append_color (snapshot,
bg_color,
&bg->boxes[clip].bounds);
&box->bounds);
}
else
{
gtk_snapshot_push_rounded_clip (snapshot,
&bg->boxes[clip]);
gtk_snapshot_push_rounded_clip (snapshot, box);
gtk_snapshot_append_color (snapshot,
bg_color,
&bg->boxes[clip].bounds);
&box->bounds);
gtk_snapshot_pop (snapshot);
}
}
static void
gtk_theming_background_snapshot_layer (const GtkThemingBackground *bg,
guint idx,
GtkSnapshot *snapshot)
gtk_theming_background_snapshot_layer (GtkCssBoxes *bg,
guint idx,
GtkSnapshot *snapshot)
{
GtkCssRepeatStyle hrepeat, vrepeat;
const GtkCssValue *pos, *repeat;
@ -112,11 +107,11 @@ gtk_theming_background_snapshot_layer (const GtkThemingBackground *bg,
vrepeat = _gtk_css_background_repeat_value_get_y (repeat);
origin = &bg->boxes[
_gtk_css_area_value_get (
_gtk_css_array_value_get_nth (
gtk_css_style_get_value (bg->style, GTK_CSS_PROPERTY_BACKGROUND_ORIGIN),
idx))];
origin = gtk_css_boxes_get_box (bg,
_gtk_css_area_value_get (
_gtk_css_array_value_get_nth (
gtk_css_style_get_value (bg->style, GTK_CSS_PROPERTY_BACKGROUND_ORIGIN),
idx)));
width = origin->bounds.size.width;
height = origin->bounds.size.height;
@ -124,11 +119,11 @@ gtk_theming_background_snapshot_layer (const GtkThemingBackground *bg,
if (width <= 0 || height <= 0)
return;
clip = &bg->boxes[
_gtk_css_area_value_get (
_gtk_css_array_value_get_nth (
gtk_css_style_get_value (bg->style, GTK_CSS_PROPERTY_BACKGROUND_CLIP),
idx))];
clip = gtk_css_boxes_get_box (bg,
_gtk_css_area_value_get (
_gtk_css_array_value_get_nth (
gtk_css_style_get_value (bg->style, GTK_CSS_PROPERTY_BACKGROUND_CLIP),
idx)));
_gtk_css_bg_size_value_compute_size (_gtk_css_array_value_get_nth (gtk_css_style_get_value (bg->style, GTK_CSS_PROPERTY_BACKGROUND_SIZE), idx),
image,
@ -274,28 +269,10 @@ gtk_theming_background_snapshot_layer (const GtkThemingBackground *bg,
gtk_snapshot_pop (snapshot);
}
static void
gtk_theming_background_init (GtkThemingBackground *bg,
GtkCssStyle *style,
double width,
double height)
{
bg->style = style;
gtk_rounded_boxes_init_for_style (&bg->boxes[GTK_CSS_AREA_BORDER_BOX],
&bg->boxes[GTK_CSS_AREA_PADDING_BOX],
&bg->boxes[GTK_CSS_AREA_CONTENT_BOX],
style,
0, 0, width, height);
}
void
gtk_css_style_snapshot_background (GtkCssStyle *style,
GtkSnapshot *snapshot,
gdouble width,
gdouble height)
gtk_css_style_snapshot_background (GtkCssBoxes *boxes,
GtkSnapshot *snapshot)
{
GtkThemingBackground bg;
gint idx;
GtkCssValue *background_image;
GtkCssValue *box_shadow;
@ -304,9 +281,9 @@ gtk_css_style_snapshot_background (GtkCssStyle *style,
gint number_of_layers;
GskBlendMode *blend_mode_values;
background_image = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_IMAGE);
bg_color = _gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_COLOR));
box_shadow = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BOX_SHADOW);
background_image = gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BACKGROUND_IMAGE);
bg_color = _gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BACKGROUND_COLOR));
box_shadow = gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BOX_SHADOW);
/* This is the common default case of no background */
if (gdk_rgba_is_clear (bg_color) &&
@ -315,15 +292,13 @@ gtk_css_style_snapshot_background (GtkCssStyle *style,
_gtk_css_shadows_value_is_none (box_shadow))
return;
gtk_theming_background_init (&bg, style, width, height);
gtk_snapshot_push_debug (snapshot, "CSS background");
gtk_css_shadows_value_snapshot_outset (box_shadow,
snapshot,
&bg.boxes[GTK_CSS_AREA_BORDER_BOX]);
gtk_css_boxes_get_border_box (boxes));
blend_modes = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE);
blend_modes = gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE);
number_of_layers = _gtk_css_array_value_get_n_values (background_image);
blend_mode_values = g_alloca (sizeof (GskBlendMode) * number_of_layers);
@ -336,25 +311,25 @@ gtk_css_style_snapshot_background (GtkCssStyle *style,
}
if (!gdk_rgba_is_clear (bg_color))
gtk_theming_background_snapshot_color (&bg, snapshot, bg_color, background_image);
gtk_theming_background_snapshot_color (boxes, snapshot, bg_color, background_image);
for (idx = number_of_layers - 1; idx >= 0; idx--)
{
if (blend_mode_values[idx] == GSK_BLEND_MODE_DEFAULT)
{
gtk_theming_background_snapshot_layer (&bg, idx, snapshot);
gtk_theming_background_snapshot_layer (boxes, idx, snapshot);
}
else
{
gtk_snapshot_pop (snapshot);
gtk_theming_background_snapshot_layer (&bg, idx, snapshot);
gtk_theming_background_snapshot_layer (boxes, idx, snapshot);
gtk_snapshot_pop (snapshot);
}
}
gtk_css_shadows_value_snapshot_inset (box_shadow,
snapshot,
&bg.boxes[GTK_CSS_AREA_PADDING_BOX]);
gtk_css_boxes_get_padding_box (boxes));
gtk_snapshot_pop (snapshot);
}

View File

@ -24,14 +24,13 @@
#include <cairo.h>
#include "gtkcsstypesprivate.h"
#include "gtkcssboxesprivate.h"
#include "gtktypes.h"
G_BEGIN_DECLS
void gtk_css_style_snapshot_background (GtkCssStyle *style,
GtkSnapshot *snapshot,
gdouble width,
gdouble height);
void gtk_css_style_snapshot_background (GtkCssBoxes *boxes,
GtkSnapshot *snapshot);

View File

@ -251,13 +251,10 @@ gtk_border_image_compute_slice_size (GtkBorderImageSliceSize sizes[3],
}
static void
gtk_border_image_render (GtkBorderImage *image,
const double border_width[4],
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
gtk_border_image_render (GtkBorderImage *image,
const float border_width[4],
cairo_t *cr,
const graphene_rect_t *rect)
{
cairo_surface_t *surface, *slice;
GtkBorderImageSliceSize vertical_slice[3], horizontal_slice[3];
@ -267,7 +264,7 @@ gtk_border_image_render (GtkBorderImage *image,
_gtk_css_image_get_concrete_size (image->source,
0, 0,
width, height,
rect->size.width, rect->size.height,
&source_width, &source_height);
/* XXX: Optimize for (source_width == width && source_height == height) */
@ -285,15 +282,15 @@ gtk_border_image_render (GtkBorderImage *image,
_gtk_css_number_value_get (_gtk_css_border_value_get_top (image->slice), source_height),
_gtk_css_number_value_get (_gtk_css_border_value_get_bottom (image->slice), source_height));
gtk_border_image_compute_border_size (horizontal_border,
x,
width,
rect->origin.x,
rect->size.width,
border_width[GTK_CSS_LEFT],
border_width[GTK_CSS_RIGHT],
_gtk_css_border_value_get_left (image->width),
_gtk_css_border_value_get_right (image->width));
gtk_border_image_compute_border_size (vertical_border,
y,
height,
rect->origin.y,
rect->size.height,
border_width[GTK_CSS_TOP],
border_width[GTK_CSS_BOTTOM],
_gtk_css_border_value_get_top (image->width),
@ -423,12 +420,12 @@ set_stroke_style (cairo_t *cr,
}
static void
render_frame_stroke (cairo_t *cr,
GskRoundedRect *border_box,
const double border_width[4],
GdkRGBA colors[4],
guint hidden_side,
GtkBorderStyle stroke_style)
render_frame_stroke (cairo_t *cr,
const GskRoundedRect *border_box,
const double border_width[4],
GdkRGBA colors[4],
guint hidden_side,
GtkBorderStyle stroke_style)
{
gboolean different_colors, different_borders;
GskRoundedRect stroke_box;
@ -510,12 +507,12 @@ render_frame_stroke (cairo_t *cr,
}
static void
snapshot_frame_stroke (GtkSnapshot *snapshot,
GskRoundedRect *outline,
const float border_width[4],
GdkRGBA colors[4],
guint hidden_side,
GtkBorderStyle stroke_style)
snapshot_frame_stroke (GtkSnapshot *snapshot,
const GskRoundedRect *outline,
const float border_width[4],
GdkRGBA colors[4],
guint hidden_side,
GtkBorderStyle stroke_style)
{
double double_width[4] = { border_width[0], border_width[1], border_width[2], border_width[3] };
cairo_t *cr;
@ -539,11 +536,11 @@ color_shade (const GdkRGBA *color,
}
static void
snapshot_border (GtkSnapshot *snapshot,
GskRoundedRect *border_box,
const float border_width[4],
GdkRGBA colors[4],
GtkBorderStyle border_style[4])
snapshot_border (GtkSnapshot *snapshot,
const GskRoundedRect *border_box,
const float border_width[4],
GdkRGBA colors[4],
GtkBorderStyle border_style[4])
{
guint hidden_side = 0;
guint i, j;
@ -661,136 +658,86 @@ snapshot_border (GtkSnapshot *snapshot,
}
void
gtk_css_style_snapshot_border (GtkCssStyle *style,
GtkSnapshot *snapshot,
gdouble width,
gdouble height)
gtk_css_style_snapshot_border (GtkCssBoxes *boxes,
GtkSnapshot *snapshot)
{
GtkBorderImage border_image;
float border_width[4];
border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100);
border_width[1] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100);
border_width[2] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100);
border_width[3] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100);
border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100);
border_width[1] = _gtk_css_number_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100);
border_width[2] = _gtk_css_number_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100);
border_width[3] = _gtk_css_number_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100);
if (gtk_border_image_init (&border_image, style))
if (gtk_border_image_init (&border_image, boxes->style))
{
cairo_t *cr;
graphene_rect_t bounds;
double double_width[4] = { border_width[0], border_width[1], border_width[2], border_width[3] };
const graphene_rect_t *bounds;
graphene_rect_init (&bounds, 0, 0, width, height);
bounds = gtk_css_boxes_get_border_rect (boxes);
gtk_snapshot_push_debug (snapshot, "CSS border image");
cr = gtk_snapshot_append_cairo (snapshot,
&bounds);
gtk_border_image_render (&border_image, double_width, cr, 0, 0, width, height);
cr = gtk_snapshot_append_cairo (snapshot, bounds);
gtk_border_image_render (&border_image, border_width, cr, bounds);
cairo_destroy (cr);
gtk_snapshot_pop (snapshot);
}
else
{
GtkBorderStyle border_style[4];
GskRoundedRect border_box;
GdkRGBA colors[4];
graphene_simd4f_t alpha_test_vector;
/* Optimize the most common case of "This widget has no border" */
if (border_width[0] == 0 &&
border_width[1] == 0 &&
border_width[2] == 0 &&
border_width[3] == 0)
if (graphene_rect_equal (gtk_css_boxes_get_border_rect (boxes),
gtk_css_boxes_get_padding_rect (boxes)))
return;
colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_COLOR));
colors[1] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR));
colors[2] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR));
colors[3] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_COLOR));
colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_TOP_COLOR));
colors[1] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR));
colors[2] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR));
colors[3] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_LEFT_COLOR));
alpha_test_vector = graphene_simd4f_init (colors[0].alpha, colors[1].alpha, colors[2].alpha, colors[3].alpha);
if (graphene_simd4f_is_zero4 (alpha_test_vector))
return;
border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_STYLE));
border_style[1] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE));
border_style[2] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE));
border_style[3] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_STYLE));
gtk_rounded_boxes_init_for_style (&border_box, NULL, NULL, style, 0, 0, width, height);
border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_TOP_STYLE));
border_style[1] = _gtk_css_border_style_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE));
border_style[2] = _gtk_css_border_style_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE));
border_style[3] = _gtk_css_border_style_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_BORDER_LEFT_STYLE));
gtk_snapshot_push_debug (snapshot, "CSS border");
snapshot_border (snapshot, &border_box, border_width, colors, border_style);
snapshot_border (snapshot,
gtk_css_boxes_get_border_box (boxes),
border_width,
colors,
border_style);
gtk_snapshot_pop (snapshot);
}
}
static void
compute_outline_rect (GtkCssStyle *style,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
cairo_rectangle_t *out_rect)
{
double offset, owidth;
owidth = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
offset = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_OFFSET), 100);
if (width <= -2 * offset)
{
x += width / 2;
out_rect->x = x - owidth;
out_rect->width = 2 * owidth;
}
else
{
out_rect->x = x - offset - owidth;
out_rect->width = width + 2 * (offset + owidth);
}
if (height <= -2 * offset)
{
y += height / 2;
out_rect->y = y - owidth;
out_rect->height = 2 * owidth;
}
else
{
out_rect->y = y - offset - owidth;
out_rect->height = height + 2 * (offset + owidth);
}
}
void
gtk_css_style_snapshot_outline (GtkCssStyle *style,
GtkSnapshot *snapshot,
gdouble width,
gdouble height)
gtk_css_style_snapshot_outline (GtkCssBoxes *boxes,
GtkSnapshot *snapshot)
{
GtkBorderStyle border_style[4];
GskRoundedRect border_box;
float border_width[4];
GdkRGBA colors[4];
border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_STYLE));
border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_STYLE));
if (border_style[0] != GTK_BORDER_STYLE_NONE)
{
cairo_rectangle_t rect;
compute_outline_rect (style, 0, 0, width, height, &rect);
border_style[1] = border_style[2] = border_style[3] = border_style[0];
border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
border_width[3] = border_width[2] = border_width[1] = border_width[0];
colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_COLOR));
colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (boxes->style, GTK_CSS_PROPERTY_OUTLINE_COLOR));
colors[3] = colors[2] = colors[1] = colors[0];
_gtk_rounded_box_init_rect (&border_box, rect.x, rect.y, rect.width, rect.height);
_gtk_rounded_box_apply_outline_radius_for_style (&border_box, style);
snapshot_border (snapshot, &border_box, border_width, colors, border_style);
snapshot_border (snapshot,
gtk_css_boxes_get_outline_box (boxes),
border_width,
colors,
border_style);
}
}

View File

@ -23,21 +23,16 @@
#define __GTK_RENDER_BORDER_H__
#include "gtkborder.h"
#include "gtkcssimageprivate.h"
#include "gtkcssvalueprivate.h"
#include "gtkcssboxesprivate.h"
#include "gtktypes.h"
G_BEGIN_DECLS
void gtk_css_style_snapshot_border (GtkCssStyle *style,
GtkSnapshot *snapshot,
gdouble width,
gdouble height);
void gtk_css_style_snapshot_border (GtkCssBoxes *boxes,
GtkSnapshot *snapshot);
void gtk_css_style_snapshot_outline (GtkCssStyle *style,
GtkSnapshot *snapshot,
gdouble width,
gdouble height);
void gtk_css_style_snapshot_outline (GtkCssBoxes *boxes,
GtkSnapshot *snapshot);
G_END_DECLS

104
gtk/gtkroot.c Normal file
View File

@ -0,0 +1,104 @@
/*
* Copyright © 2018 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkrootprivate.h"
/**
* SECTION:root
* @Title: GtkRoot
* @Short_description: Root widgets
* @See_also: #GtkWindow
*
* #GtkRoot is the interface implemented by all widgets that can act as a toplevel
* widget to a hierarchy of widgets. The root widget takes care of providing the
* connection to the windowing system and manages layout, drawing and event delivery
* for its widget hierarchy.
*
* The obvious example of a #GtkRoot is #GtkWindow.
*/
G_DEFINE_INTERFACE (GtkRoot, gtk_root, GTK_TYPE_WIDGET)
static GdkDisplay *
gtk_root_default_get_display (GtkRoot *self)
{
return gdk_display_get_default ();
}
static GskRenderer *
gtk_root_default_get_renderer (GtkRoot *self)
{
return NULL;
}
static void
gtk_root_default_get_surface_transform (GtkRoot *self,
int *x,
int *y)
{
*x = 0;
*y = 0;
}
static void
gtk_root_default_init (GtkRootInterface *iface)
{
iface->get_display = gtk_root_default_get_display;
iface->get_renderer = gtk_root_default_get_renderer;
iface->get_surface_transform = gtk_root_default_get_surface_transform;
}
GdkDisplay *
gtk_root_get_display (GtkRoot *self)
{
GtkRootInterface *iface;
g_return_val_if_fail (GTK_IS_ROOT (self), NULL);
iface = GTK_ROOT_GET_IFACE (self);
return iface->get_display (self);
}
GskRenderer *
gtk_root_get_renderer (GtkRoot *self)
{
GtkRootInterface *iface;
g_return_val_if_fail (GTK_IS_ROOT (self), NULL);
iface = GTK_ROOT_GET_IFACE (self);
return iface->get_renderer (self);
}
void
gtk_root_get_surface_transform (GtkRoot *self,
int *x,
int *y)
{
GtkRootInterface *iface;
g_return_if_fail (GTK_IS_ROOT (self));
g_return_if_fail (x != 0);
g_return_if_fail (y != 0);
iface = GTK_ROOT_GET_IFACE (self);
return iface->get_surface_transform (self, x, y);
}

59
gtk/gtkroot.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright © 2018 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_ROOT_H__
#define __GTK_ROOT_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gdk/gdk.h>
#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
#define GTK_TYPE_ROOT (gtk_root_get_type ())
GDK_AVAILABLE_IN_ALL
G_DECLARE_INTERFACE (GtkRoot, gtk_root, GTK, ROOT, GtkWidget)
/**
* GtkRootIface:
*
* The list of functions that must be implemented for the #GtkRoot interface.
*/
struct _GtkRootInterface
{
/*< private >*/
GTypeInterface g_iface;
/*< public >*/
GdkDisplay * (* get_display) (GtkRoot *self);
GskRenderer * (* get_renderer) (GtkRoot *self);
void (* get_surface_transform) (GtkRoot *root,
int *x,
int *y);
};
G_END_DECLS
#endif /* __GTK_ROOT_H__ */

16
gtk/gtkrootprivate.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __GTK_ROOT_PRIVATE_H__
#define __GTK_ROOT_PRIVATE_H__
#include "gtkroot.h"
G_BEGIN_DECLS
GdkDisplay * gtk_root_get_display (GtkRoot *root);
GskRenderer * gtk_root_get_renderer (GtkRoot *self);
void gtk_root_get_surface_transform (GtkRoot *self,
int *x,
int *y);
G_END_DECLS
#endif /* __GTK_ROOT_PRIVATE_H__ */

View File

@ -1263,14 +1263,15 @@ gtk_snapshot_render_background (GtkSnapshot *snapshot,
gdouble width,
gdouble height)
{
GtkCssBoxes boxes;
g_return_if_fail (snapshot != NULL);
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
gtk_snapshot_offset (snapshot, x, y);
gtk_css_style_snapshot_background (gtk_style_context_lookup_style (context),
snapshot,
width, height);
gtk_snapshot_offset (snapshot, -x, -y);
gtk_css_boxes_init_border_box (&boxes,
gtk_style_context_lookup_style (context),
x, y, width, height);
gtk_css_style_snapshot_background (&boxes, snapshot);
}
/**
@ -1294,14 +1295,15 @@ gtk_snapshot_render_frame (GtkSnapshot *snapshot,
gdouble width,
gdouble height)
{
GtkCssBoxes boxes;
g_return_if_fail (snapshot != NULL);
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
gtk_snapshot_offset (snapshot, x, y);
gtk_css_style_snapshot_border (gtk_style_context_lookup_style (context),
snapshot,
width, height);
gtk_snapshot_offset (snapshot, -x, -y);
gtk_css_boxes_init_border_box (&boxes,
gtk_style_context_lookup_style (context),
x, y, width, height);
gtk_css_style_snapshot_border (&boxes, snapshot);
}
/**
@ -1325,14 +1327,15 @@ gtk_snapshot_render_focus (GtkSnapshot *snapshot,
gdouble width,
gdouble height)
{
GtkCssBoxes boxes;
g_return_if_fail (snapshot != NULL);
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
gtk_snapshot_offset (snapshot, x, y);
gtk_css_style_snapshot_outline (gtk_style_context_lookup_style (context),
snapshot,
width, height);
gtk_snapshot_offset (snapshot, -x, -y);
gtk_css_boxes_init_border_box (&boxes,
gtk_style_context_lookup_style (context),
x, y, width, height);
gtk_css_style_snapshot_outline (&boxes, snapshot);
}
/**

View File

@ -39,6 +39,7 @@ typedef struct _GtkClipboard GtkClipboard;
typedef struct _GtkEventController GtkEventController;
typedef struct _GtkGesture GtkGesture;
typedef struct _GtkRequisition GtkRequisition;
typedef struct _GtkRoot GtkRoot;
typedef struct _GtkSelectionData GtkSelectionData;
typedef struct _GtkSettings GtkSettings;
typedef GdkSnapshot GtkSnapshot;

View File

@ -34,6 +34,7 @@
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkcssboxesprivate.h"
#include "gtkcssfiltervalueprivate.h"
#include "gtkcssfontvariationsvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
@ -507,6 +508,7 @@ enum {
PROP_0,
PROP_NAME,
PROP_PARENT,
PROP_ROOT,
PROP_WIDTH_REQUEST,
PROP_HEIGHT_REQUEST,
PROP_VISIBLE,
@ -602,6 +604,8 @@ static void gtk_widget_real_move_focus (GtkWidget
GtkDirectionType direction);
static gboolean gtk_widget_real_keynav_failed (GtkWidget *widget,
GtkDirectionType direction);
static void gtk_widget_root (GtkWidget *widget);
static void gtk_widget_unroot (GtkWidget *widget);
#ifdef G_ENABLE_CONSISTENCY_CHECKS
static void gtk_widget_verify_invariants (GtkWidget *widget);
static void gtk_widget_push_verify_invariants (GtkWidget *widget);
@ -853,6 +857,18 @@ gtk_widget_real_grab_notify (GtkWidget *widget,
}
}
static void
gtk_widget_real_root (GtkWidget *widget)
{
gtk_widget_forall (widget, (GtkCallback) gtk_widget_root, NULL);
}
static void
gtk_widget_real_unroot (GtkWidget *widget)
{
gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL);
}
static void
gtk_widget_class_init (GtkWidgetClass *klass)
{
@ -899,6 +915,8 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->unmap = gtk_widget_real_unmap;
klass->realize = gtk_widget_real_realize;
klass->unrealize = gtk_widget_real_unrealize;
klass->root = gtk_widget_real_root;
klass->unroot = gtk_widget_real_unroot;
klass->size_allocate = gtk_widget_real_size_allocate;
klass->get_request_mode = gtk_widget_real_get_request_mode;
klass->measure = gtk_widget_real_measure;
@ -948,6 +966,19 @@ gtk_widget_class_init (GtkWidgetClass *klass)
GTK_TYPE_WIDGET,
GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkWidget:root:
*
* The #GtkRoot widget of the widget tree containing this widget or %NULL if
* the widget is not contained in a root widget.
*/
widget_props[PROP_ROOT] =
g_param_spec_object ("root",
P_("Root widget"),
P_("The root widget in the widget tree."),
GTK_TYPE_ROOT,
GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY);
widget_props[PROP_WIDTH_REQUEST] =
g_param_spec_int ("width-request",
P_("Width request"),
@ -2368,6 +2399,9 @@ gtk_widget_get_property (GObject *object,
case PROP_PARENT:
g_value_set_object (value, priv->parent);
break;
case PROP_ROOT:
g_value_set_object (value, priv->root);
break;
case PROP_WIDTH_REQUEST:
{
int w;
@ -2810,10 +2844,6 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
priv->visible = gtk_widget_class_get_visible_by_default (g_class);
priv->child_visible = TRUE;
priv->name = NULL;
priv->allocation.x = -1;
priv->allocation.y = -1;
priv->allocation.width = 0;
priv->allocation.height = 0;
priv->user_alpha = 255;
priv->alpha = 255;
priv->surface = NULL;
@ -2822,7 +2852,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
priv->last_child = NULL;
priv->prev_sibling = NULL;
priv->next_sibling = NULL;
priv->allocated_baseline = -1;
priv->baseline = -1;
priv->allocated_size_baseline = -1;
priv->sensitive = TRUE;
@ -2872,6 +2902,9 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
gtk_css_node_set_visible (priv->cssnode, priv->visible);
/* need to set correct type here, and only class has the correct type here */
gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_FROM_CLASS (g_class));
if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_ROOT))
priv->root = (GtkRoot *) widget;
}
@ -2999,6 +3032,46 @@ gtk_widget_new (GType type,
return widget;
}
static void
gtk_widget_root (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
/* roots are rooted by default */
if (GTK_IS_ROOT (widget))
return;
g_assert (priv->root == NULL);
g_assert (!priv->realized);
g_assert (priv->parent);
g_assert (priv->parent->priv->root);
priv->root = priv->parent->priv->root;
GTK_WIDGET_GET_CLASS (widget)->root (widget);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_ROOT]);
}
static void
gtk_widget_unroot (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
/* roots are rooted by default and cannot be unrooted */
if (GTK_IS_ROOT (widget))
return;
g_assert (priv->root);
g_assert (!priv->realized);
GTK_WIDGET_GET_CLASS (widget)->unroot (widget);
priv->root = NULL;
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_ROOT]);
}
/**
* gtk_widget_unparent:
* @widget: a #GtkWidget
@ -3044,12 +3117,15 @@ gtk_widget_unparent (GtkWidget *widget)
/* Reset the width and height here, to force reallocation if we
* get added back to a new parent.
*/
priv->allocation.width = 0;
priv->allocation.height = 0;
priv->width = 0;
priv->height = 0;
if (_gtk_widget_get_realized (widget))
gtk_widget_unrealize (widget);
if (priv->root)
gtk_widget_unroot (widget);
/* If we are unanchoring the child, we save around the toplevel
* to emit hierarchy changed
*/
@ -3107,10 +3183,9 @@ gtk_widget_unparent (GtkWidget *widget)
gtk_list_list_model_item_removed (old_parent->priv->children_observer, old_prev_sibling);
if (toplevel)
{
_gtk_widget_propagate_hierarchy_changed (widget, toplevel);
g_object_unref (toplevel);
}
_gtk_widget_propagate_hierarchy_changed (widget, toplevel);
g_clear_object (&toplevel);
/* Now that the parent pointer is nullified and the hierarchy-changed
* already passed, go ahead and unset the parent window, if we are unparenting
@ -4145,6 +4220,12 @@ gtk_widget_size_allocate (GtkWidget *widget,
real_allocation = *allocation;
baseline_changed = priv->allocated_size_baseline != baseline;
size_changed = (priv->allocated_size.width != real_allocation.width ||
priv->allocated_size.height != real_allocation.height);
position_changed = (priv->allocated_size.x != real_allocation.x ||
priv->allocated_size.y != real_allocation.y);
priv->allocated_size = *allocation;
priv->allocated_size_baseline = baseline;
@ -4233,16 +4314,6 @@ gtk_widget_size_allocate (GtkWidget *widget,
real_allocation.height = MAX (1, real_allocation.height);
}
baseline_changed = priv->allocated_baseline != baseline;
size_changed = (priv->allocation.width != real_allocation.width ||
priv->allocation.height != real_allocation.height);
position_changed = (priv->allocation.x != real_allocation.x ||
priv->allocation.y != real_allocation.y);
/* Set the widget allocation to real_allocation now, pass the smaller allocation to the vfunc */
priv->allocation = real_allocation;
priv->allocated_baseline = baseline;
if (!alloc_needed && !size_changed && !baseline_changed)
{
/* Still have to move the window... */
@ -4265,6 +4336,9 @@ gtk_widget_size_allocate (GtkWidget *widget,
get_box_border (style, &border);
get_box_padding (style, &padding);
priv->transform.x = real_allocation.x + margin.left + border.left + padding.left;
priv->transform.y = real_allocation.y + margin.top + border.top + padding.top;
/* Since gtk_widget_measure does it for us, we can be sure here that
* the given alloaction is large enough for the css margin/bordder/padding */
real_allocation.x = 0;
@ -4277,6 +4351,10 @@ gtk_widget_size_allocate (GtkWidget *widget,
if (baseline >= 0)
baseline -= margin.top + border.top + padding.top;
priv->width = real_allocation.width;
priv->height = real_allocation.height;
priv->baseline = baseline;
if (g_signal_has_handler_pending (widget, widget_signals[SIZE_ALLOCATE], 0, FALSE))
g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0,
real_allocation.width,
@ -4380,23 +4458,8 @@ gtk_widget_get_origin_relative_to_parent (GtkWidget *widget,
int *origin_x,
int *origin_y)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkBorder margin, border, padding;
GtkCssStyle *style;
style = gtk_css_node_get_style (priv->cssnode);
get_box_margin (style, &margin);
get_box_border (style, &border);
get_box_padding (style, &padding);
/* allocation is relative to the parent's origin */
*origin_x = priv->allocation.x;
*origin_y = priv->allocation.y;
/* ... but points to the upper left, excluding widget margins
* but including all the css properties */
*origin_x += margin.left + border.left + padding.left;
*origin_y += margin.top + border.top + padding.top;
*origin_x = widget->priv->transform.x;
*origin_y = widget->priv->transform.y;
}
/**
@ -5008,18 +5071,6 @@ gtk_widget_real_mnemonic_activate (GtkWidget *widget,
return TRUE;
}
static GskRenderer *
gtk_widget_get_renderer (GtkWidget *widget)
{
GtkWidget *toplevel;
toplevel = _gtk_widget_get_toplevel (widget);
if (_gtk_widget_is_toplevel (toplevel))
return gtk_window_get_renderer (GTK_WINDOW (toplevel));
return NULL;
}
#define WIDGET_REALIZED_FOR_EVENT(widget, event) \
(event->any.type == GDK_FOCUS_CHANGE || _gtk_widget_get_realized(widget))
@ -6185,10 +6236,10 @@ _gtk_widget_set_visible_flag (GtkWidget *widget,
if (!visible)
{
priv->allocation.x = -1;
priv->allocation.y = -1;
priv->allocation.width = 0;
priv->allocation.height = 0;
priv->transform.x = 0;
priv->transform.y = 0;
priv->width = 0;
priv->height = 0;
memset (&priv->allocated_size, 0, sizeof (priv->allocated_size));
priv->allocated_size_baseline = 0;
gtk_widget_update_paintables (widget);
@ -6278,8 +6329,8 @@ gtk_widget_set_has_surface (GtkWidget *widget,
priv->no_surface_set = TRUE;
/* GdkSurface has a min size of 1×1 */
priv->allocation.width = 1;
priv->allocation.height = 1;
priv->width = 1;
priv->height = 1;
}
/**
@ -6315,20 +6366,9 @@ gtk_widget_get_has_surface (GtkWidget *widget)
gboolean
gtk_widget_is_toplevel (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
return priv->toplevel;
}
void
_gtk_widget_set_is_toplevel (GtkWidget *widget,
gboolean is_toplevel)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
priv->toplevel = is_toplevel;
return GTK_IS_ROOT (widget);
}
/**
@ -6603,7 +6643,11 @@ gtk_widget_reposition_after (GtkWidget *widget,
}
if (priv->parent->priv->anchored && prev_parent == NULL)
_gtk_widget_propagate_hierarchy_changed (widget, NULL);
{
_gtk_widget_propagate_hierarchy_changed (widget, NULL);
}
if (parent->priv->root && priv->root == NULL)
gtk_widget_root (widget);
if (prev_parent == NULL)
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_PARENT]);
@ -6687,6 +6731,25 @@ gtk_widget_get_parent (GtkWidget *widget)
return priv->parent;
}
/**
* gtk_widget_get_root:
* @widget: a #GtkWidget
*
* Returns the #GtkRoot widget of @widget or %NULL if the widget is not contained
* inside a widget tree with a root widget.
*
* #GtkRoot widgets will return themselves here.
*
* Returns: (transfer none) (nullable): the root widget of @widget, or %NULL
**/
GtkRoot *
gtk_widget_get_root (GtkWidget *widget)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
return _gtk_widget_get_root (widget);
}
static void
gtk_widget_real_direction_changed (GtkWidget *widget,
GtkTextDirection previous_direction)
@ -6899,7 +6962,7 @@ gtk_widget_verify_invariants (GtkWidget *widget)
g_warning ("%s %p is mapped but not visible",
G_OBJECT_TYPE_NAME (widget), widget);
if (!priv->toplevel)
if (!GTK_IS_ROOT (widget))
{
if (!priv->child_visible)
g_warning ("%s %p is mapped but not child_visible",
@ -6947,7 +7010,7 @@ gtk_widget_verify_invariants (GtkWidget *widget)
G_OBJECT_TYPE_NAME (widget), widget);
#endif
}
else if (!priv->toplevel)
else if (!GTK_IS_ROOT (widget))
{
/* No parent or parent not realized on non-toplevel implies... */
@ -6969,7 +7032,7 @@ gtk_widget_verify_invariants (GtkWidget *widget)
G_OBJECT_TYPE_NAME (parent), parent,
G_OBJECT_TYPE_NAME (widget), widget);
}
else if (!widget->priv->toplevel)
else if (!GTK_IS_ROOT (widget))
{
/* No parent or parent not mapped on non-toplevel implies... */
@ -11130,11 +11193,19 @@ gtk_widget_get_allocation (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
const graphene_rect_t *margin_rect;
GtkCssBoxes boxes;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (allocation != NULL);
*allocation = priv->allocation;
gtk_css_boxes_init (&boxes, widget);
margin_rect = gtk_css_boxes_get_margin_rect (&boxes);
allocation->x = priv->transform.x + ceil (margin_rect->origin.x);
allocation->y = priv->transform.y + ceil (margin_rect->origin.y);
allocation->width = ceil (margin_rect->size.width);
allocation->height = ceil (margin_rect->size.height);
}
/**
@ -11216,18 +11287,12 @@ gtk_widget_pick (GtkWidget *widget,
case GTK_OVERFLOW_HIDDEN:
{
GtkBorder margin, border, padding;
GtkCssStyle *style;
GtkCssBoxes boxes;
style = gtk_css_node_get_style (priv->cssnode);
get_box_margin (style, &margin);
get_box_border (style, &border);
get_box_padding (style, &padding);
gtk_css_boxes_init (&boxes, widget);
if (x < -padding.left ||
y < -padding.top ||
x >= priv->allocation.width - margin.left - margin.right - border.left - border.right - padding.left ||
y >= priv->allocation.height - margin.top - margin.bottom - border.top - border.bottom - padding.top)
if (!graphene_rect_contains_point (gtk_css_boxes_get_padding_rect (&boxes),
&GRAPHENE_POINT_INIT (x, y)))
return NULL;
}
break;
@ -11259,39 +11324,26 @@ gtk_widget_compute_bounds (GtkWidget *widget,
GtkWidget *target,
graphene_rect_t *out_bounds)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkBorder margin, border, padding;
GtkCssStyle *style;
GtkAllocation alloc;
GtkCssBoxes boxes;
int x, y;
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
g_return_val_if_fail (GTK_IS_WIDGET (target), FALSE);
g_return_val_if_fail (out_bounds != NULL, FALSE);
style = gtk_css_node_get_style (priv->cssnode);
get_box_margin (style, &margin);
get_box_border (style, &border);
get_box_padding (style, &padding);
alloc.x = - (padding.left + border.left);
alloc.y = - (padding.top + border.top);
alloc.width = priv->allocation.width - margin.left - margin.right;
alloc.height = priv->allocation.height -margin.top - margin.bottom;
if (!gtk_widget_translate_coordinates (widget,
target,
alloc.x, alloc.y,
&alloc.x, &alloc.y))
0, 0,
&x, &y))
{
graphene_rect_init_from_rect (out_bounds, graphene_rect_zero ());
return FALSE;
}
graphene_rect_init (out_bounds,
alloc.x,
alloc.y,
alloc.width,
alloc.height);
gtk_css_boxes_init (&boxes, widget);
graphene_rect_offset_r (gtk_css_boxes_get_border_rect (&boxes),
x, y,
out_bounds);
return TRUE;
}
@ -11307,11 +11359,13 @@ gtk_widget_compute_bounds (GtkWidget *widget,
int
gtk_widget_get_allocated_width (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkCssBoxes boxes;
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
return priv->allocation.width;
gtk_css_boxes_init (&boxes, widget);
return gtk_css_boxes_get_margin_rect (&boxes)->size.width;
}
/**
@ -11325,11 +11379,13 @@ gtk_widget_get_allocated_width (GtkWidget *widget)
int
gtk_widget_get_allocated_height (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkCssBoxes boxes;
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
return priv->allocation.height;
gtk_css_boxes_init (&boxes, widget);
return gtk_css_boxes_get_margin_rect (&boxes)->size.height;
}
/**
@ -11352,7 +11408,7 @@ gtk_widget_get_allocated_baseline (GtkWidget *widget)
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
if (priv->allocated_baseline == -1)
if (priv->baseline == -1)
return -1;
style = gtk_css_node_get_style (priv->cssnode);
@ -11360,7 +11416,7 @@ gtk_widget_get_allocated_baseline (GtkWidget *widget)
get_box_border (style, &border);
get_box_padding (style, &padding);
return priv->allocated_baseline - margin.top - border.top - padding.top;
return priv->baseline - margin.top - border.top - padding.top;
}
/**
@ -12948,36 +13004,24 @@ gtk_widget_reset_controllers (GtkWidget *widget)
}
static inline void
gtk_widget_maybe_add_debug_render_nodes (GtkWidget *widget,
GtkSnapshot *snapshot)
gtk_widget_maybe_add_debug_render_nodes (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GdkDisplay *display = _gtk_widget_get_display (widget);
GtkCssStyle *style;
GtkBorder margin, border, padding;
/* We should be offset to priv->allocation at this point */
if (GTK_DISPLAY_DEBUG_CHECK (display, BASELINES))
{
int baseline = gtk_widget_get_allocated_baseline (widget);
if (baseline != -1)
if (priv->baseline != -1)
{
GdkRGBA red = {1, 0, 0, 1};
graphene_rect_t bounds;
style = gtk_css_node_get_style (priv->cssnode);
get_box_margin (style, &margin);
get_box_border (style, &border);
get_box_padding (style, &padding);
/* Baselines are relative to the widget's origin,
* and we are offset to the widget's allocation here */
graphene_rect_init (&bounds,
0,
margin.top + border.top + padding.top + baseline,
priv->allocation.width, 1);
0, priv->baseline,
priv->width, 1);
gtk_snapshot_append_color (snapshot,
&red,
&bounds);
@ -12992,7 +13036,7 @@ gtk_widget_maybe_add_debug_render_nodes (GtkWidget *widget,
graphene_rect_init (&bounds,
0, 0,
priv->allocation.width, priv->allocation.height);
priv->width, priv->height);
gtk_snapshot_append_color (snapshot,
&blue,
@ -13009,74 +13053,43 @@ gtk_widget_create_render_node (GtkWidget *widget,
{
GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS (widget);
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkCssBoxes boxes;
GtkCssValue *filter_value;
double opacity;
GtkCssStyle *style;
GtkAllocation allocation;
GtkBorder margin, border, padding;
GtkSnapshot *snapshot;
opacity = priv->alpha / 255.0;
if (opacity <= 0.0)
return NULL;
gtk_css_boxes_init (&boxes, widget);
snapshot = gtk_snapshot_new_with_parent (parent_snapshot);
_gtk_widget_get_allocation (widget, &allocation);
gtk_snapshot_push_debug (snapshot,
"RenderNode for %s %p @ %d x %d",
G_OBJECT_TYPE_NAME (widget), widget,
allocation.width, allocation.height);
"RenderNode for %s %p",
G_OBJECT_TYPE_NAME (widget), widget);
filter_value = _gtk_style_context_peek_property (_gtk_widget_get_style_context (widget), GTK_CSS_PROPERTY_FILTER);
gtk_css_filter_value_push_snapshot (filter_value, snapshot);
style = gtk_css_node_get_style (priv->cssnode);
get_box_margin (style, &margin);
get_box_border (style, &border);
get_box_padding (style, &padding);
if (opacity < 1.0)
gtk_snapshot_push_opacity (snapshot, opacity);
if (!GTK_IS_WINDOW (widget))
{
gtk_snapshot_offset (snapshot, margin.left, margin.top);
gtk_css_style_snapshot_background (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_css_style_snapshot_border (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_snapshot_offset (snapshot, - margin.left, - margin.top);
gtk_css_style_snapshot_background (&boxes, snapshot);
gtk_css_style_snapshot_border (&boxes, snapshot);
}
/* Offset to content allocation */
gtk_snapshot_offset (snapshot, margin.left + padding.left + border.left, margin.top + border.top + padding.top);
if (priv->overflow == GTK_OVERFLOW_HIDDEN)
{
gtk_snapshot_push_clip (snapshot,
&GRAPHENE_RECT_INIT (- padding.left,
- padding.top,
allocation.width - margin.left - margin.right - border.left - border.right,
allocation.height - margin.top - margin.bottom - border.top - border.bottom));
}
gtk_snapshot_push_clip (snapshot, gtk_css_boxes_get_padding_rect (&boxes));
klass->snapshot (widget, snapshot);
if (priv->overflow == GTK_OVERFLOW_HIDDEN)
gtk_snapshot_pop (snapshot);
gtk_snapshot_offset (snapshot, - (padding.left + border.left), -(border.top + padding.top));
gtk_css_style_snapshot_outline (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_snapshot_offset (snapshot, - margin.left, - margin.top);
gtk_css_style_snapshot_outline (&boxes, snapshot);
if (opacity < 1.0)
gtk_snapshot_pop (snapshot);
@ -13137,17 +13150,24 @@ gtk_widget_render (GtkWidget *widget,
GtkSnapshot *snapshot;
GskRenderer *renderer;
GskRenderNode *root;
int x, y;
if (!GTK_IS_ROOT (widget))
return;
/* We only render double buffered on native windows */
if (!gdk_surface_has_native (surface))
return;
renderer = gtk_widget_get_renderer (widget);
renderer = gtk_root_get_renderer (GTK_ROOT (widget));
if (renderer == NULL)
return;
snapshot = gtk_snapshot_new ();
gtk_root_get_surface_transform (GTK_ROOT (widget), &x, &y);
gtk_snapshot_offset (snapshot, x, y);
gtk_widget_snapshot (widget, snapshot);
gtk_snapshot_offset (snapshot, -x, -y);
root = gtk_snapshot_free_to_node (snapshot);
if (root != NULL)
@ -13459,14 +13479,12 @@ gtk_widget_snapshot_child (GtkWidget *widget,
GtkWidget *child,
GtkSnapshot *snapshot)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (child);
int x, y;
g_return_if_fail (_gtk_widget_get_parent (child) == widget);
g_return_if_fail (snapshot != NULL);
x = priv->allocation.x;
y = priv->allocation.y;
gtk_widget_get_origin_relative_to_parent (child, &x, &y);
gtk_snapshot_offset (snapshot, x, y);
gtk_widget_snapshot (child, snapshot);
@ -13658,20 +13676,10 @@ int
gtk_widget_get_width (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkBorder margin, border, padding;
GtkCssStyle *style;
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
style = gtk_css_node_get_style (priv->cssnode);
get_box_margin (style, &margin);
get_box_border (style, &border);
get_box_padding (style, &padding);
return priv->allocation.width -
margin.left - margin.right -
border.left - border.right -
padding.left - padding.right;
return priv->width;
}
/**
@ -13688,18 +13696,8 @@ int
gtk_widget_get_height (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkBorder margin, border, padding;
GtkCssStyle *style;
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
style = gtk_css_node_get_style (priv->cssnode);
get_box_margin (style, &margin);
get_box_border (style, &border);
get_box_padding (style, &padding);
return priv->allocation.height -
margin.top - margin.bottom -
border.top - border.bottom -
padding.top - padding.bottom;
return priv->height;
}

View File

@ -152,6 +152,9 @@ struct _GtkWidget
* widget is destroyed, which means that gtk_widget_unrealize() has
* been called or the widget has been unmapped (that is, it is going
* to be hidden).
* @root: Called when the widget gets added to a #GtkRoot widget.
* @unroot: Called when the widget is about to be removed from its
* #GtkRoot widget.
* @size_allocate: Signal emitted to get the widget allocation.
* @state_flags_changed: Signal emitted when the widget state changes,
* see gtk_widget_get_state_flags().
@ -247,6 +250,8 @@ struct _GtkWidgetClass
void (* unmap) (GtkWidget *widget);
void (* realize) (GtkWidget *widget);
void (* unrealize) (GtkWidget *widget);
void (* root) (GtkWidget *widget);
void (* unroot) (GtkWidget *widget);
void (* size_allocate) (GtkWidget *widget,
int width,
int height,
@ -559,13 +564,16 @@ GDK_AVAILABLE_IN_ALL
void gtk_widget_set_parent (GtkWidget *widget,
GtkWidget *parent);
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_widget_get_parent (GtkWidget *widget);
GtkWidget * gtk_widget_get_parent (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
GtkRoot * gtk_widget_get_root (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_set_parent_surface (GtkWidget *widget,
GdkSurface *parent_surface);
GDK_AVAILABLE_IN_ALL
GdkSurface * gtk_widget_get_parent_surface (GtkWidget *widget);
GdkSurface * gtk_widget_get_parent_surface (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_set_child_visible (GtkWidget *widget,

View File

@ -92,13 +92,15 @@ gtk_widget_paintable_paintable_snapshot (GdkPaintable *paintable,
else if (self->snapshot_count > 0)
{
graphene_matrix_t transform;
graphene_rect_t bounds;
gtk_snapshot_push_clip (snapshot,
&GRAPHENE_RECT_INIT(0, 0, width, height));
graphene_matrix_init_scale (&transform,
width / gtk_widget_get_allocated_width (self->widget),
height / gtk_widget_get_allocated_height (self->widget),
1.0);
gtk_widget_compute_bounds (self->widget, self->widget, &bounds);
graphene_matrix_init_from_2d (&transform,
width / bounds.size.width, 0.0,
0.0, height / bounds.size.height,
bounds.origin.x, bounds.origin.y);
gtk_snapshot_push_transform (snapshot, &transform);
gtk_widget_snapshot (self->widget, snapshot);

View File

@ -32,6 +32,7 @@
#include "gtkcsstypesprivate.h"
#include "gtkeventcontroller.h"
#include "gtklistlistmodelprivate.h"
#include "gtkrootprivate.h"
#include "gtksizerequestcacheprivate.h"
#include "gtkwindowprivate.h"
#include "gtkinvisibleprivate.h"
@ -55,7 +56,6 @@ struct _GtkWidgetPrivate
#endif
guint in_destruction : 1;
guint toplevel : 1;
guint anchored : 1;
guint no_surface : 1;
guint no_surface_set : 1;
@ -124,6 +124,11 @@ struct _GtkWidgetPrivate
*/
gchar *name;
/* The root this widget belongs to or %NULL if widget is not
* rooted or is a #GtkRoot itself.
*/
GtkRoot *root;
/* The list of attached windows to this widget.
* We keep a list in order to call reset_style to all of them,
* recursively.
@ -141,8 +146,13 @@ struct _GtkWidgetPrivate
/* The widget's allocated size */
GtkAllocation allocated_size;
gint allocated_size_baseline;
GtkAllocation allocation;
gint allocated_baseline;
struct {
int x;
int y;
} transform;
int width;
int height;
int baseline;
/* The widget's requested sizes */
SizeRequestCache requests;
@ -221,8 +231,6 @@ void _gtk_widget_set_has_default (GtkWidget *widget,
gboolean has_default);
void _gtk_widget_set_has_grab (GtkWidget *widget,
gboolean has_grab);
void _gtk_widget_set_is_toplevel (GtkWidget *widget,
gboolean is_toplevel);
void _gtk_widget_grab_notify (GtkWidget *widget,
gboolean was_grabbed);
@ -385,7 +393,7 @@ _gtk_widget_get_realized (GtkWidget *widget)
static inline gboolean
_gtk_widget_is_toplevel (GtkWidget *widget)
{
return widget->priv->toplevel;
return GTK_IS_ROOT (widget);
}
static inline GtkStateFlags
@ -414,20 +422,21 @@ _gtk_widget_get_toplevel (GtkWidget *widget)
return widget;
}
static inline GtkRoot *
_gtk_widget_get_root (GtkWidget *widget)
{
return widget->priv->root;
}
static inline GdkDisplay *
_gtk_widget_get_display (GtkWidget *widget)
{
GtkWidget *toplevel = _gtk_widget_get_toplevel (widget);
GtkRoot *root = _gtk_widget_get_root (widget);
if (_gtk_widget_is_toplevel (toplevel))
{
if (GTK_IS_WINDOW (toplevel))
return gtk_window_get_display (GTK_WINDOW (toplevel));
else if (GTK_IS_INVISIBLE (toplevel))
return gtk_invisible_get_display (GTK_INVISIBLE (widget));
}
if (root == NULL)
return gdk_display_get_default ();
return gdk_display_get_default ();
return gtk_root_get_display (root);
}
static inline GtkStyleContext *
@ -451,13 +460,6 @@ _gtk_widget_get_surface (GtkWidget *widget)
return widget->priv->surface;
}
static inline void
_gtk_widget_get_allocation (GtkWidget *widget,
GtkAllocation *allocation)
{
*allocation = widget->priv->allocation;
}
static inline GtkWidget *
_gtk_widget_get_prev_sibling (GtkWidget *widget)
{

View File

@ -61,6 +61,7 @@
#include "gtkpointerfocusprivate.h"
#include "gtkpopoverprivate.h"
#include "gtkprivate.h"
#include "gtkroot.h"
#include "gtkseparatormenuitem.h"
#include "gtksettings.h"
#include "gtksnapshot.h"
@ -432,7 +433,6 @@ static void gtk_window_focus_out (GtkWidget *widget);
static void surface_state_changed (GtkWidget *widget);
static void gtk_window_remove (GtkContainer *container,
GtkWidget *widget);
static void gtk_window_check_resize (GtkContainer *container);
static void gtk_window_forall (GtkContainer *container,
GtkCallback callback,
gpointer callback_data);
@ -562,6 +562,9 @@ static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
const gchar *tagname,
gpointer user_data);
/* GtkRoot */
static void gtk_window_root_interface_init (GtkRootInterface *iface);
static void ensure_state_flag_backdrop (GtkWidget *widget);
static void unset_titlebar (GtkWindow *window);
static void on_titlebar_title_notify (GtkHeaderBar *titlebar,
@ -576,7 +579,9 @@ static void gtk_window_update_debugging (void);
G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
G_ADD_PRIVATE (GtkWindow)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_window_buildable_interface_init))
gtk_window_buildable_interface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
gtk_window_root_interface_init))
static void
add_tab_bindings (GtkBindingSet *binding_set,
@ -809,7 +814,6 @@ gtk_window_class_init (GtkWindowClass *klass)
container_class->add = gtk_window_add;
container_class->remove = gtk_window_remove;
container_class->check_resize = gtk_window_check_resize;
container_class->forall = gtk_window_forall;
klass->set_focus = gtk_window_real_set_focus;
@ -1724,7 +1728,7 @@ edge_under_coordinates (GtkWindow *window,
(priv->edge_constraints & constraints) != constraints)
return FALSE;
_gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
context = _gtk_widget_get_style_context (GTK_WIDGET (window));
gtk_style_context_save_to_node (context, priv->decoration_node);
@ -1862,7 +1866,6 @@ gtk_window_init (GtkWindow *window)
widget = GTK_WIDGET (window);
gtk_widget_set_has_surface (widget, TRUE);
_gtk_widget_set_is_toplevel (widget, TRUE);
_gtk_widget_set_anchored (widget, TRUE);
priv->title = NULL;
@ -2495,6 +2498,50 @@ gtk_window_buildable_custom_finished (GtkBuildable *buildable,
}
}
static GdkDisplay *
gtk_window_root_get_display (GtkRoot *root)
{
GtkWindow *window = GTK_WINDOW (root);
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
return priv->display;
}
static GskRenderer *
gtk_window_root_get_renderer (GtkRoot *root)
{
GtkWindow *self = GTK_WINDOW (root);
GtkWindowPrivate *priv = gtk_window_get_instance_private (self);
return priv->renderer;
}
static void
gtk_window_root_get_surface_transform (GtkRoot *root,
int *x,
int *y)
{
GtkWindow *self = GTK_WINDOW (root);
GtkStyleContext *context;
GtkBorder margin, border, padding;
context = gtk_widget_get_style_context (GTK_WIDGET (self));
gtk_style_context_get_margin (context, &margin);
gtk_style_context_get_border (context, &border);
gtk_style_context_get_padding (context, &padding);
*x = margin.left + border.left + padding.left;
*y = margin.top + border.top + padding.top;
}
static void
gtk_window_root_interface_init (GtkRootInterface *iface)
{
iface->get_display = gtk_window_root_get_display;
iface->get_renderer = gtk_window_root_get_renderer;
iface->get_surface_transform = gtk_window_root_get_surface_transform;
}
/**
* gtk_window_new:
* @type: type of window
@ -5224,7 +5271,7 @@ gtk_window_move (GtkWindow *window,
{
GtkAllocation allocation;
_gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_allocation (widget, &allocation);
/* we have now sent a request with this position
* with currently-active constraints, so toggle flag.
@ -5704,7 +5751,6 @@ gtk_window_show (GtkWidget *widget)
{
GtkWindow *window = GTK_WINDOW (widget);
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
GtkContainer *container = GTK_CONTAINER (window);
if (!_gtk_widget_is_toplevel (GTK_WIDGET (widget)))
{
@ -5718,7 +5764,7 @@ gtk_window_show (GtkWidget *widget)
gtk_widget_realize (widget);
gtk_container_check_resize (container);
gtk_window_check_resize (window);
gtk_widget_map (widget);
@ -6017,7 +6063,7 @@ popover_get_rect (GtkWindowPopover *popover,
gdouble min, max;
gtk_widget_get_preferred_size (popover->widget, NULL, &req);
_gtk_widget_get_allocation (GTK_WIDGET (window), &win_alloc);
gtk_widget_get_allocation (GTK_WIDGET (window), &win_alloc);
get_shadow_width (window, &win_border);
win_alloc.x += win_border.left;
@ -6403,7 +6449,7 @@ gtk_window_realize (GtkWidget *widget)
g_return_if_fail (!_gtk_widget_get_realized (widget));
}
_gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_allocation (widget, &allocation);
if (priv->hardcoded_surface)
{
@ -6781,7 +6827,7 @@ gtk_window_configure (GtkWindow *window,
* have been a queued resize from child widgets, and so we
* need to reallocate our children in case *they* changed.
*/
_gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_allocation (widget, &allocation);
if (priv->configure_request_count == 0 &&
(allocation.width == width && allocation.height == height))
{
@ -7002,7 +7048,7 @@ get_active_region_type (GtkWindow *window, gint x, gint y)
gtk_widget_get_visible (priv->title_box) &&
gtk_widget_get_child_visible (priv->title_box))
{
_gtk_widget_get_allocation (priv->title_box, &allocation);
gtk_widget_get_allocation (priv->title_box, &allocation);
if (allocation.x <= x && allocation.x + allocation.width > x &&
allocation.y <= y && allocation.y + allocation.height > y)
return GTK_WINDOW_REGION_TITLE;
@ -7157,13 +7203,15 @@ gtk_window_remove (GtkContainer *container,
GTK_CONTAINER_CLASS (gtk_window_parent_class)->remove (container, widget);
}
static void
gtk_window_check_resize (GtkContainer *container)
void
gtk_window_check_resize (GtkWindow *self)
{
if (!_gtk_widget_get_alloc_needed (GTK_WIDGET (container)))
GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
else if (gtk_widget_get_visible (GTK_WIDGET (container)))
gtk_window_move_resize (GTK_WINDOW (container));
GtkWidget *widget = GTK_WIDGET (self);
if (!_gtk_widget_get_alloc_needed (widget))
gtk_widget_ensure_allocate (widget);
else if (gtk_widget_get_visible (widget))
gtk_window_move_resize (self);
}
static void
@ -7380,7 +7428,7 @@ gtk_window_style_updated (GtkWidget *widget)
GtkAllocation allocation;
GtkBorder window_border;
_gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_allocation (widget, &allocation);
get_shadow_width (window, &window_border);
update_opaque_region (window, &window_border, &allocation);
@ -7926,7 +7974,7 @@ gtk_window_compute_configure_request (GtkWindow *window,
gdk_surface_get_origin (surface, &ox, &oy);
_gtk_widget_get_allocation (parent_widget, &allocation);
gtk_widget_get_allocation (parent_widget, &allocation);
x = ox + (allocation.width - w) / 2;
y = oy + (allocation.height - h) / 2;
@ -9427,14 +9475,6 @@ gtk_window_on_theme_variant_changed (GtkSettings *settings,
}
#endif
GdkDisplay *
gtk_window_get_display (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
return priv->display;
}
/**
* gtk_window_is_active:
* @window: a #GtkWindow
@ -10557,14 +10597,6 @@ gtk_window_unexport_handle (GtkWindow *window)
#endif
}
GskRenderer *
gtk_window_get_renderer (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
return priv->renderer;
}
static void
gtk_window_add_pointer_focus (GtkWindow *window,
GtkPointerFocus *focus)

View File

@ -54,6 +54,7 @@ void _gtk_window_set_allocation (GtkWindow *window,
int width,
int height,
GtkAllocation *allocation_out);
void gtk_window_check_resize (GtkWindow *self);
typedef void (*GtkWindowKeysForeachFunc) (GtkWindow *window,
guint keyval,
@ -120,8 +121,6 @@ GdkTexture * gtk_window_get_icon_for_size (GtkWindow *window,
void gtk_window_set_hardcoded_surface (GtkWindow *window,
GdkSurface *surface);
GdkDisplay *gtk_window_get_display (GtkWindow *window);
/* Exported handles */
typedef void (*GtkWindowHandleExported) (GtkWindow *window,
@ -133,8 +132,6 @@ gboolean gtk_window_export_handle (GtkWindow *window,
gpointer user_data);
void gtk_window_unexport_handle (GtkWindow *window);
GskRenderer *gtk_window_get_renderer (GtkWindow *window);
GtkWidget * gtk_window_lookup_pointer_focus_widget (GtkWindow *window,
GdkDevice *device,
GdkEventSequence *sequence);

View File

@ -35,7 +35,7 @@
#include "gtkprivate.h"
#include "gtkdebug.h"
#include "gdkinternals.h"
#include "gtkwindowprivate.h"
#include "gtkrootprivate.h"
#include "gskdebugprivate.h"
#include "gskrendererprivate.h"
@ -146,7 +146,7 @@ flag_toggled (GtkWidget *button,
if (toplevel == gtk_widget_get_toplevel (button)) /* skip the inspector */
continue;
renderer = gtk_window_get_renderer (GTK_WINDOW (toplevel));
renderer = gtk_root_get_renderer (GTK_ROOT (toplevel));
if (!renderer)
continue;

View File

@ -51,10 +51,10 @@
#include "gtklabel.h"
#include "gtkmodulesprivate.h"
#include "gtkprivate.h"
#include "gtkrootprivate.h"
#include "gtkstack.h"
#include "gtktreeviewcolumn.h"
#include "gtkwindowgroup.h"
#include "gtkwindowprivate.h"
G_DEFINE_TYPE (GtkInspectorWindow, gtk_inspector_window, GTK_TYPE_WINDOW)
@ -273,7 +273,7 @@ gtk_inspector_window_realize (GtkWidget *widget)
GTK_WIDGET_CLASS (gtk_inspector_window_parent_class)->realize (widget);
renderer = gtk_window_get_renderer (GTK_WINDOW (widget));
renderer = gtk_root_get_renderer (GTK_ROOT (widget));
gsk_renderer_set_debug_flags (renderer, 0);
}

View File

@ -314,6 +314,7 @@ gtk_public_sources = files([
'gtkrendericon.c',
'gtkrendernodepaintable.c',
'gtkrevealer.c',
'gtkroot.c',
'gtkroundedbox.c',
'gtkscale.c',
'gtkscalebutton.c',
@ -551,6 +552,7 @@ gtk_public_headers = files([
'gtkrecentmanager.h',
'gtkrender.h',
'gtkrevealer.h',
'gtkroot.h',
'gtkscale.h',
'gtkscalebutton.h',
'gtkscrollable.h',