1/* GTK - The GIMP Toolkit
2 * Copyright (C) 2014 Benjamin Otte <otte@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include "gtkcsswidgetnodeprivate.h"
21
22#include "gtkcssanimatedstyleprivate.h"
23#include "gtkprivate.h"
24#include "gtksettingsprivate.h"
25#include "gtkstylecontextprivate.h"
26#include "gtkwidgetprivate.h"
27#include "gtkwindowprivate.h"
28
29G_DEFINE_TYPE (GtkCssWidgetNode, gtk_css_widget_node, GTK_TYPE_CSS_NODE)
30
31static void
32gtk_css_widget_node_finalize (GObject *object)
33{
34 GtkCssWidgetNode *node = GTK_CSS_WIDGET_NODE (object);
35
36 g_object_unref (object: node->last_updated_style);
37
38 G_OBJECT_CLASS (gtk_css_widget_node_parent_class)->finalize (object);
39}
40
41static gboolean
42gtk_css_widget_node_queue_callback (GtkWidget *widget,
43 GdkFrameClock *frame_clock,
44 gpointer user_data)
45{
46 GtkCssNode *node = user_data;
47
48 gtk_css_node_invalidate_frame_clock (cssnode: node, TRUE);
49 gtk_root_queue_restyle (self: GTK_ROOT (ptr: widget));
50
51 return G_SOURCE_CONTINUE;
52}
53
54static void
55gtk_css_widget_node_queue_validate (GtkCssNode *node)
56{
57 GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
58
59 if (GTK_IS_ROOT (ptr: widget_node->widget))
60 widget_node->validate_cb_id = gtk_widget_add_tick_callback (widget: widget_node->widget,
61 callback: gtk_css_widget_node_queue_callback,
62 user_data: node,
63 NULL);
64}
65
66static void
67gtk_css_widget_node_dequeue_validate (GtkCssNode *node)
68{
69 GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
70
71 if (widget_node->widget && GTK_IS_ROOT (ptr: widget_node->widget))
72 gtk_widget_remove_tick_callback (widget: widget_node->widget,
73 id: widget_node->validate_cb_id);
74}
75
76static void
77gtk_css_widget_node_validate (GtkCssNode *node)
78{
79 GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
80 GtkCssStyleChange change;
81 GtkCssStyle *style;
82
83 if (widget_node->widget == NULL)
84 return;
85
86 if (node->style == widget_node->last_updated_style)
87 return;
88
89 style = gtk_css_node_get_style (cssnode: node);
90
91 gtk_css_style_change_init (change: &change, old_style: widget_node->last_updated_style, new_style: style);
92 if (gtk_css_style_change_has_change (change: &change))
93 {
94 gtk_widget_css_changed (widget: widget_node->widget, change: &change);
95 g_set_object (&widget_node->last_updated_style, style);
96 }
97 gtk_css_style_change_finish (change: &change);
98}
99
100static GtkStyleProvider *
101gtk_css_widget_node_get_style_provider (GtkCssNode *node)
102{
103 GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
104 GtkStyleContext *context;
105 GtkStyleCascade *cascade;
106
107 if (widget_node->widget == NULL)
108 return NULL;
109
110 context = _gtk_widget_peek_style_context (widget: widget_node->widget);
111 if (context)
112 return gtk_style_context_get_style_provider (context);
113
114 cascade = _gtk_settings_get_style_cascade (settings: gtk_widget_get_settings (widget: widget_node->widget),
115 scale: gtk_widget_get_scale_factor (widget: widget_node->widget));
116 return GTK_STYLE_PROVIDER (cascade);
117}
118
119static GdkFrameClock *
120gtk_css_widget_node_get_frame_clock (GtkCssNode *node)
121{
122 GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
123
124 if (widget_node->widget == NULL)
125 return NULL;
126
127 if (!gtk_settings_get_enable_animations (settings: gtk_widget_get_settings (widget: widget_node->widget)))
128 return NULL;
129
130 return gtk_widget_get_frame_clock (widget: widget_node->widget);
131}
132
133static void
134gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass)
135{
136 GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass);
137 GObjectClass *object_class = G_OBJECT_CLASS (klass);
138
139 object_class->finalize = gtk_css_widget_node_finalize;
140 node_class->validate = gtk_css_widget_node_validate;
141 node_class->queue_validate = gtk_css_widget_node_queue_validate;
142 node_class->dequeue_validate = gtk_css_widget_node_dequeue_validate;
143 node_class->get_style_provider = gtk_css_widget_node_get_style_provider;
144 node_class->get_frame_clock = gtk_css_widget_node_get_frame_clock;
145}
146
147static void
148gtk_css_widget_node_init (GtkCssWidgetNode *node)
149{
150 node->last_updated_style = g_object_ref (gtk_css_static_style_get_default ());
151}
152
153GtkCssNode *
154gtk_css_widget_node_new (GtkWidget *widget)
155{
156 GtkCssWidgetNode *result;
157
158 gtk_internal_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
159
160 result = g_object_new (GTK_TYPE_CSS_WIDGET_NODE, NULL);
161 result->widget = widget;
162 gtk_css_node_set_visible (GTK_CSS_NODE (result),
163 visible: _gtk_widget_get_visible (widget));
164
165 return GTK_CSS_NODE (result);
166}
167
168void
169gtk_css_widget_node_widget_destroyed (GtkCssWidgetNode *node)
170{
171 gtk_internal_return_if_fail (GTK_IS_CSS_WIDGET_NODE (node));
172 gtk_internal_return_if_fail (node->widget != NULL);
173
174 node->widget = NULL;
175 /* Contents of this node are now undefined.
176 * So we don't clear the style or anything.
177 */
178}
179
180GtkWidget *
181gtk_css_widget_node_get_widget (GtkCssWidgetNode *node)
182{
183 gtk_internal_return_val_if_fail (GTK_IS_CSS_WIDGET_NODE (node), NULL);
184
185 return node->widget;
186}
187
188

source code of gtk/gtk/gtkcsswidgetnode.c