GCC Code Coverage Report


Directory: ./
File: panels/wacom/calibrator/cc-clock.c
Date: 2024-05-03 09:46:52
Exec Total Coverage
Lines: 0 106 0.0%
Functions: 0 18 0.0%
Branches: 0 25 0.0%

Line Branch Exec Source
1 /*
2 * Copyright © 2018 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program 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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Joaquim Rocha <jrocha@redhat.com>
18 * Carlos Garnacho <carlosg@gnome.org>
19 */
20 #include "config.h"
21 #include "cc-clock.h"
22
23 #include <math.h>
24
25 #define CLOCK_RADIUS 50
26 #define CLOCK_LINE_WIDTH 10
27 #define CLOCK_LINE_PADDING 10
28 #define EXTRA_SPACE 2
29
30 typedef struct _CcClock CcClock;
31
32 struct _CcClock
33 {
34 GtkWidget parent_instance;
35 guint duration;
36 gint64 start_time;
37 gboolean running;
38 };
39
40 enum
41 {
42 PROP_DURATION = 1,
43 N_PROPS
44 };
45
46 static GParamSpec *props[N_PROPS] = { 0, };
47
48 enum {
49 FINISHED,
50 N_SIGNALS
51 };
52
53 static guint signals[N_SIGNALS] = { 0, };
54
55 G_DEFINE_TYPE (CcClock, cc_clock, GTK_TYPE_WIDGET)
56
57 static gint64
58 cc_clock_get_time_diff (CcClock *clock)
59 {
60 GdkFrameClock *frame_clock;
61 gint64 current_time;
62
63 frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
64 current_time = gdk_frame_clock_get_frame_time (frame_clock);
65
66 return current_time - clock->start_time;
67 }
68
69 static gdouble
70 cc_clock_get_angle (CcClock *clock)
71 {
72 gint64 time_diff;
73
74 time_diff = cc_clock_get_time_diff (clock);
75
76 if (time_diff > clock->duration * 1000)
77 return 360;
78
79 return ((gdouble) time_diff / (clock->duration * 1000)) * 360;
80 }
81
82 static void
83 cc_clock_snapshot (GtkWidget *widget,
84 GtkSnapshot *snapshot)
85 {
86 GtkAllocation allocation;
87 cairo_t *cr;
88 gdouble angle;
89
90 gtk_widget_get_allocation (widget, &allocation);
91 angle = cc_clock_get_angle (CC_CLOCK (widget));
92
93 cr = gtk_snapshot_append_cairo (snapshot,
94 &GRAPHENE_RECT_INIT (0, 0, allocation.width, allocation.height));
95
96 /* Draw the clock background */
97 cairo_arc (cr, allocation.width / 2, allocation.height / 2, CLOCK_RADIUS / 2, 0.0, 2.0 * M_PI);
98 cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
99 cairo_fill_preserve (cr);
100 cairo_stroke (cr);
101
102 cairo_set_line_width (cr, CLOCK_LINE_WIDTH);
103
104 cairo_arc (cr,
105 allocation.width / 2,
106 allocation.height / 2,
107 (CLOCK_RADIUS - CLOCK_LINE_WIDTH - CLOCK_LINE_PADDING) / 2,
108 3 * M_PI_2,
109 3 * M_PI_2 + angle * M_PI / 180.0);
110 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
111 cairo_stroke (cr);
112 }
113
114 static void
115 cc_clock_stop (CcClock *clock)
116 {
117 GdkFrameClock *frame_clock;
118
119 if (!clock->running)
120 return;
121
122 frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
123
124 gdk_frame_clock_end_updating (frame_clock);
125 clock->running = FALSE;
126 }
127
128 static void
129 on_frame_clock_update (CcClock *clock)
130 {
131 gint64 time_diff;
132
133 if (!clock->running)
134 return;
135
136 time_diff = cc_clock_get_time_diff (clock);
137
138 if (time_diff > clock->duration * 1000)
139 {
140 g_signal_emit (clock, signals[FINISHED], 0);
141 cc_clock_stop (clock);
142 }
143
144 gtk_widget_queue_draw (GTK_WIDGET (clock));
145 }
146
147 static void
148 cc_clock_map (GtkWidget *widget)
149 {
150 GdkFrameClock *frame_clock;
151
152 GTK_WIDGET_CLASS (cc_clock_parent_class)->map (widget);
153
154 frame_clock = gtk_widget_get_frame_clock (widget);
155 g_signal_connect_object (frame_clock, "update",
156 G_CALLBACK (on_frame_clock_update),
157 widget, G_CONNECT_SWAPPED);
158 cc_clock_reset (CC_CLOCK (widget));
159 }
160
161 static void
162 cc_clock_set_property (GObject *object,
163 guint prop_id,
164 const GValue *value,
165 GParamSpec *pspec)
166 {
167 CcClock *clock = CC_CLOCK (object);
168
169 switch (prop_id)
170 {
171 case PROP_DURATION:
172 clock->duration = g_value_get_uint (value);
173 break;
174 default:
175 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
176 break;
177 }
178 }
179
180 static void
181 cc_clock_get_property (GObject *object,
182 guint prop_id,
183 GValue *value,
184 GParamSpec *pspec)
185 {
186 CcClock *clock = CC_CLOCK (object);
187
188 switch (prop_id)
189 {
190 case PROP_DURATION:
191 g_value_set_uint (value, clock->duration);
192 break;
193 default:
194 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
195 break;
196 }
197 }
198
199 static void
200 cc_clock_measure (GtkWidget *widget,
201 GtkOrientation orientation,
202 gint for_size,
203 gint *minimum,
204 gint *natural,
205 gint *minimum_baseline,
206 gint *natural_baseline)
207 {
208 if (minimum)
209 *minimum = CLOCK_RADIUS + EXTRA_SPACE;
210 if (natural)
211 *natural = CLOCK_RADIUS + EXTRA_SPACE;
212 }
213
214 static void
215 cc_clock_class_init (CcClockClass *klass)
216 {
217 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
218 GObjectClass *object_class = G_OBJECT_CLASS (klass);
219
220 object_class->set_property = cc_clock_set_property;
221 object_class->get_property = cc_clock_get_property;
222
223 widget_class->map = cc_clock_map;
224 widget_class->snapshot = cc_clock_snapshot;
225 widget_class->measure = cc_clock_measure;
226
227 signals[FINISHED] =
228 g_signal_new ("finished",
229 CC_TYPE_CLOCK,
230 G_SIGNAL_RUN_LAST,
231 0, NULL, NULL, NULL,
232 G_TYPE_NONE, 0);
233
234 props[PROP_DURATION] =
235 g_param_spec_uint ("duration",
236 "Duration",
237 "Duration",
238 0, G_MAXUINT, 0,
239 G_PARAM_READWRITE |
240 G_PARAM_STATIC_STRINGS |
241 G_PARAM_CONSTRUCT_ONLY);
242
243 g_object_class_install_properties (object_class, N_PROPS, props);
244 }
245
246 static void
247 cc_clock_init (CcClock *clock)
248 {
249 }
250
251 GtkWidget *
252 cc_clock_new (guint duration)
253 {
254 return g_object_new (CC_TYPE_CLOCK,
255 "duration", duration,
256 NULL);
257 }
258
259 void
260 cc_clock_reset (CcClock *clock)
261 {
262 GdkFrameClock *frame_clock;
263
264 if (!gtk_widget_get_mapped (GTK_WIDGET (clock)))
265 return;
266
267 frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
268
269 cc_clock_stop (clock);
270
271 clock->running = TRUE;
272 clock->start_time = g_get_monotonic_time ();
273 gdk_frame_clock_begin_updating (frame_clock);
274 }
275
276 void
277 cc_clock_set_duration (CcClock *clock,
278 guint duration)
279 {
280 clock->duration = duration;
281 g_object_notify (G_OBJECT (clock), "duration");
282 cc_clock_reset (clock);
283 }
284
285 guint
286 cc_clock_get_duration (CcClock *clock)
287 {
288 return clock->duration;
289 }
290