Bug Summary

File:themes/standard/theme.c
Warning:line 415, column 5
Access of the heap area at index 6, while it holds only 6 'struct _CdkPoint' elements

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name theme.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src/themes/standard -fcoverage-compilation-dir=/rootdir/src/themes/standard -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I ../../.. -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D _REENTRANT -D _REENTRANT -I /usr/local/include/libvnck-3.0 -I /usr/include/startup-notification-1.0 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/libxml2 -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-10-24-080024-37773-1 -x c theme.c
1/*
2 * Copyright (C) 2006-2007 Christian Hammond <chipx86@chipx86.com>
3 * Copyright (C) 2009 Red Hat, Inc.
4 * Copyright (C) 2011 Perberos <perberos@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 */
21#include "config.h"
22
23#include <glib/gi18n.h>
24#include <ctk/ctk.h>
25
26#include <libxml/xpath.h>
27
28typedef void (*ActionInvokedCb) (CtkWindow* nw, const char* key);
29typedef void (*UrlClickedCb) (CtkWindow* nw, const char* url);
30
31typedef struct {
32 CtkWidget* win;
33 CtkWidget* top_spacer;
34 CtkWidget* bottom_spacer;
35 CtkWidget* main_hbox;
36 CtkWidget* iconbox;
37 CtkWidget* icon;
38 CtkWidget* content_hbox;
39 CtkWidget* summary_label;
40 CtkWidget* close_button;
41 CtkWidget* body_label;
42 CtkWidget* actions_box;
43 CtkWidget* last_sep;
44 CtkWidget* stripe_spacer;
45 CtkWidget* pie_countdown;
46
47 gboolean has_arrow;
48 gboolean composited;
49 gboolean action_icons;
50
51 int point_x;
52 int point_y;
53
54 int drawn_arrow_begin_x;
55 int drawn_arrow_begin_y;
56 int drawn_arrow_middle_x;
57 int drawn_arrow_middle_y;
58 int drawn_arrow_end_x;
59 int drawn_arrow_end_y;
60
61 int width;
62 int height;
63
64 CdkPoint* border_points;
65 size_t num_border_points;
66
67 cairo_region_t *window_region;
68
69 guchar urgency;
70 glong timeout;
71 glong remaining;
72
73 UrlClickedCb url_clicked;
74
75} WindowData;
76
77enum {
78 URGENCY_LOW,
79 URGENCY_NORMAL,
80 URGENCY_CRITICAL
81};
82
83gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver,
84 unsigned int micro_ver);
85void get_theme_info(char **theme_name, char **theme_ver, char **author,
86 char **homepage);
87CtkWindow* create_notification(UrlClickedCb url_clicked);
88void set_notification_text(CtkWindow *nw, const char *summary,
89 const char *body);
90void set_notification_icon(CtkWindow *nw, GdkPixbuf *pixbuf);
91void set_notification_arrow(CtkWidget *nw, gboolean visible, int x, int y);
92void add_notification_action(CtkWindow *nw, const char *text, const char *key,
93 ActionInvokedCb cb);
94void clear_notification_actions(CtkWindow *nw);
95void move_notification(CtkWidget *nw, int x, int y);
96void set_notification_timeout(CtkWindow *nw, glong timeout);
97void set_notification_hints(CtkWindow *nw, GVariant *hints);
98void notification_tick(CtkWindow *nw, glong remaining);
99
100//#define ENABLE_GRADIENT_LOOK
101
102#ifdef ENABLE_GRADIENT_LOOK
103 #define STRIPE_WIDTH30 45
104#else
105 #define STRIPE_WIDTH30 30
106#endif
107
108#define WIDTH400 400
109#define IMAGE_SIZE32 32
110#define IMAGE_PADDING10 10
111#define SPACER_LEFT30 30
112#define PIE_RADIUS12 12
113#define PIE_WIDTH(2 * 12) (2 * PIE_RADIUS12)
114#define PIE_HEIGHT(2 * 12) (2 * PIE_RADIUS12)
115#define BODY_X_OFFSET(32 + 8) (IMAGE_SIZE32 + 8)
116#define DEFAULT_ARROW_OFFSET(30 + 2) (SPACER_LEFT30 + 2)
117#define DEFAULT_ARROW_HEIGHT14 14
118#define DEFAULT_ARROW_WIDTH28 28
119#define BACKGROUND_OPACITY0.92 0.92
120#define BOTTOM_GRADIENT_HEIGHT30 30
121
122static void
123get_background_color (CtkStyleContext *context,
124 CtkStateFlags state,
125 CdkRGBA *color)
126{
127 CdkRGBA *c;
128
129 g_return_if_fail (color != NULL)do { if ((color != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "color != NULL");
return; } } while (0)
;
130 g_return_if_fail (CTK_IS_STYLE_CONTEXT (context))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((context)); GType __t = ((ctk_style_context_get_type ()))
; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CTK_IS_STYLE_CONTEXT (context)"); return
; } } while (0)
;
131
132 ctk_style_context_get (context, state,
133 "background-color", &c,
134 NULL((void*)0));
135
136 *color = *c;
137 cdk_rgba_free (c);
138}
139
140static void fill_background(CtkWidget* widget, WindowData* windata, cairo_t* cr)
141{
142 CtkStyleContext *context;
143 CdkRGBA bg;
144
145 CtkAllocation allocation;
146
147 ctk_widget_get_allocation(widget, &allocation);
148
149 #ifdef ENABLE_GRADIENT_LOOK
150
151 cairo_pattern_t *gradient;
152 int gradient_y;
153
154 gradient_y = allocation.height - BOTTOM_GRADIENT_HEIGHT30;
155
156 #endif
157
158 context = ctk_widget_get_style_context (windata->win);
159
160 ctk_style_context_save (context);
161 ctk_style_context_set_state (context, CTK_STATE_FLAG_NORMAL);
162
163 get_background_color (context, CTK_STATE_FLAG_NORMAL, &bg);
164
165 ctk_style_context_restore (context);
166
167 if (windata->composited)
168 {
169 cairo_set_source_rgba(cr, bg.red, bg.green, bg.blue, BACKGROUND_OPACITY0.92);
170 }
171 else
172 {
173 cdk_cairo_set_source_rgba (cr, &bg);
174 }
175
176 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
177
178 cairo_fill(cr);
179
180 #ifdef ENABLE_GRADIENT_LOOK
181 /* Add a very subtle gradient to the bottom of the notification */
182 gradient = cairo_pattern_create_linear(0, gradient_y, 0, allocation.height);
183 cairo_pattern_add_color_stop_rgba(gradient, 0, 0, 0, 0, 0);
184 cairo_pattern_add_color_stop_rgba(gradient, 1, 0, 0, 0, 0.15);
185 cairo_rectangle(cr, 0, gradient_y, allocation.width, BOTTOM_GRADIENT_HEIGHT30);
186
187 cairo_set_source(cr, gradient);
188 cairo_fill(cr);
189 cairo_pattern_destroy(gradient);
190 #endif
191}
192
193static void draw_stripe(CtkWidget* widget, WindowData* windata, cairo_t* cr)
194{
195 CtkStyleContext* context;
196 CdkRGBA bg;
197 int stripe_x;
198 int stripe_y;
199 int stripe_height;
200 #ifdef ENABLE_GRADIENT_LOOK
201 cairo_pattern_t* gradient;
202 double r, g, b;
203 #endif
204
205 context = ctk_widget_get_style_context (widget);
206
207 ctk_style_context_save (context);
208
209 CtkAllocation alloc;
210 ctk_widget_get_allocation(windata->main_hbox, &alloc);
211
212 stripe_x = alloc.x + 1;
213
214 if (ctk_widget_get_direction(widget) == CTK_TEXT_DIR_RTL)
215 {
216 stripe_x = windata->width - STRIPE_WIDTH30 - stripe_x;
217 }
218
219 stripe_y = alloc.y + 1;
220 stripe_height = alloc.height - 2;
221
222 switch (windata->urgency)
223 {
224 case URGENCY_LOW: // LOW
225 ctk_style_context_set_state (context, CTK_STATE_FLAG_NORMAL);
226 ctk_style_context_add_class (context, CTK_STYLE_CLASS_VIEW"view");
227 get_background_color (context, CTK_STATE_FLAG_NORMAL, &bg);
228 cdk_cairo_set_source_rgba (cr, &bg);
229 break;
230
231 case URGENCY_CRITICAL: // CRITICAL
232 cdk_rgba_parse (&bg, "#CC0000");
233 break;
234
235 case URGENCY_NORMAL: // NORMAL
236 default:
237 ctk_style_context_set_state (context, CTK_STATE_FLAG_SELECTED);
238 ctk_style_context_add_class (context, CTK_STYLE_CLASS_VIEW"view");
239 get_background_color (context, CTK_STATE_FLAG_SELECTED, &bg);
240 cdk_cairo_set_source_rgba (cr, &bg);
241 break;
242 }
243
244 ctk_style_context_restore (context);
245
246 cairo_rectangle(cr, stripe_x, stripe_y, STRIPE_WIDTH30, stripe_height);
247
248 #ifdef ENABLE_GRADIENT_LOOK
249 r = color.red / 65535.0;
250 g = color.green / 65535.0;
251 b = color.blue / 65535.0;
252
253 gradient = cairo_pattern_create_linear(stripe_x, 0, STRIPE_WIDTH30, 0);
254 cairo_pattern_add_color_stop_rgba(gradient, 0, r, g, b, 1);
255 cairo_pattern_add_color_stop_rgba(gradient, 1, r, g, b, 0);
256 cairo_set_source(cr, gradient);
257 cairo_fill(cr);
258 cairo_pattern_destroy(gradient);
259 #else
260 cdk_cairo_set_source_rgba (cr, &bg);
261 cairo_fill(cr);
262 #endif
263}
264
265static CtkArrowType get_notification_arrow_type(CtkWidget* nw)
266{
267 WindowData* windata;
268 CdkScreen* screen;
269 CdkRectangle monitor_geometry;
270 CdkDisplay* display;
271 CdkMonitor* monitor;
272
273 windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
274
275 screen = cdk_window_get_screen(CDK_WINDOW( ctk_widget_get_window(nw))((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_window(nw))), ((cdk_window_get_type ())))
)))
);
276 display = cdk_screen_get_display (screen);
277 monitor = cdk_display_get_monitor_at_point (display, windata->point_x, windata->point_y);
278 cdk_monitor_get_geometry (monitor, &monitor_geometry);
279
280 if (windata->point_y - monitor_geometry.y + windata->height + DEFAULT_ARROW_HEIGHT14 > monitor_geometry.height)
281 {
282 return CTK_ARROW_DOWN;
283 }
284 else
285 {
286 return CTK_ARROW_UP;
287 }
288}
289
290#define ADD_POINT(_x, _y, shapeoffset_x, shapeoffset_y)do { windata->border_points[i].x = (_x); windata->border_points
[i].y = (_y); shape_points[i].x = (_x) + (shapeoffset_x); shape_points
[i].y = (_y) + (shapeoffset_y); i++; } while (0)
\
291 G_STMT_STARTdo { \
292 windata->border_points[i].x = (_x); \
293 windata->border_points[i].y = (_y); \
294 shape_points[i].x = (_x) + (shapeoffset_x); \
295 shape_points[i].y = (_y) + (shapeoffset_y); \
296 i++;\
297 } G_STMT_ENDwhile (0)
298
299static void create_border_with_arrow(CtkWidget* nw, WindowData* windata)
300{
301 int width;
302 int height;
303 int y;
304 int norm_point_x;
305 int norm_point_y;
306 CtkArrowType arrow_type;
307 CdkScreen* screen;
308 int arrow_side1_width = DEFAULT_ARROW_WIDTH28 / 2;
309 int arrow_side2_width = DEFAULT_ARROW_WIDTH28 / 2;
310 int arrow_offset = DEFAULT_ARROW_OFFSET(30 + 2);
311 CdkPoint* shape_points = NULL((void*)0);
312 int i = 0;
313 CdkMonitor* monitor;
314 CdkDisplay* display;
315 CdkRectangle monitor_geometry;
316
317 width = windata->width;
318 height = windata->height;
319
320 screen = cdk_window_get_screen(CDK_WINDOW(ctk_widget_get_window(nw))((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_window(nw))), ((cdk_window_get_type ())))
)))
);
321 display = cdk_screen_get_display (screen);
322 monitor = cdk_display_get_monitor_at_point (display, windata->point_x, windata->point_y);
323 cdk_monitor_get_geometry (monitor, &monitor_geometry);
324
325 windata->num_border_points = 5;
326
327 arrow_type = get_notification_arrow_type(windata->win);
328
329 norm_point_x = windata->point_x - monitor_geometry.x;
330 norm_point_y = windata->point_y - monitor_geometry.y;
331
332 /* Handle the offset and such */
333 switch (arrow_type)
1
Control jumps to 'case CTK_ARROW_UP:' at line 335
334 {
335 case CTK_ARROW_UP:
336 case CTK_ARROW_DOWN:
337
338 if (norm_point_x < arrow_side1_width)
2
Assuming 'norm_point_x' is >= 'arrow_side1_width'
3
Taking false branch
339 {
340 arrow_side1_width = 0;
341 arrow_offset = 0;
342 }
343 else if (norm_point_x > monitor_geometry.width - arrow_side2_width)
4
Assuming the condition is false
5
Taking false branch
344 {
345 arrow_side2_width = 0;
346 arrow_offset = width - arrow_side1_width;
347 }
348 else
349 {
350 if (norm_point_x - arrow_side2_width + width >= monitor_geometry.width)
6
Assuming the condition is true
7
Taking true branch
351 {
352 arrow_offset = width - monitor_geometry.width + norm_point_x;
353 }
354 else
355 {
356 arrow_offset = MIN(norm_point_x - arrow_side1_width, DEFAULT_ARROW_OFFSET)(((norm_point_x - arrow_side1_width) < ((30 + 2))) ? (norm_point_x
- arrow_side1_width) : ((30 + 2)))
;
357 }
358
359 if (arrow_offset == 0 || arrow_offset == width - arrow_side1_width)
8
Assuming 'arrow_offset' is not equal to 0
9
Assuming the condition is true
10
Taking true branch
360 {
361 windata->num_border_points++;
362 }
363 else
364 {
365 windata->num_border_points += 2;
366 }
367 }
368
369 /*
370 * Why risk this for official builds? If it's somehow off the
371 * screen, it won't horribly impact the user. Definitely less
372 * than an assertion would...
373 */
374 #if 0
375 g_assert(arrow_offset + arrow_side1_width >= 0)do { if (arrow_offset + arrow_side1_width >= 0) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 375, ((const char*) (__func__)), "arrow_offset + arrow_side1_width >= 0"
); } while (0)
;
376 g_assert(arrow_offset + arrow_side1_width + arrow_side2_width <= width)do { if (arrow_offset + arrow_side1_width + arrow_side2_width
<= width) ; else g_assertion_message_expr (((gchar*) 0), "theme.c"
, 376, ((const char*) (__func__)), "arrow_offset + arrow_side1_width + arrow_side2_width <= width"
); } while (0)
;
377 #endif
378
379 windata->border_points = g_new0(CdkPoint, windata->num_border_points)((CdkPoint *) g_malloc0_n ((windata->num_border_points), sizeof
(CdkPoint)))
;
380 shape_points = g_new0(CdkPoint, windata->num_border_points)((CdkPoint *) g_malloc0_n ((windata->num_border_points), sizeof
(CdkPoint)))
;
381
382 windata->drawn_arrow_begin_x = arrow_offset;
383 windata->drawn_arrow_middle_x = arrow_offset + arrow_side1_width;
384 windata->drawn_arrow_end_x = arrow_offset + arrow_side1_width + arrow_side2_width;
385
386 if (arrow_type
10.1
'arrow_type' is equal to CTK_ARROW_UP
== CTK_ARROW_UP)
11
Taking true branch
387 {
388 windata->drawn_arrow_begin_y = DEFAULT_ARROW_HEIGHT14;
389 windata->drawn_arrow_middle_y = 0;
390 windata->drawn_arrow_end_y = DEFAULT_ARROW_HEIGHT14;
391
392 if (arrow_side1_width
11.1
'arrow_side1_width' is not equal to 0
== 0)
12
Taking false branch
393 {
394 ADD_POINT(0, 0, 0, 0)do { windata->border_points[i].x = (0); windata->border_points
[i].y = (0); shape_points[i].x = (0) + (0); shape_points[i].y
= (0) + (0); i++; } while (0)
;
395 }
396 else
397 {
398 ADD_POINT(0, DEFAULT_ARROW_HEIGHT, 0, 0)do { windata->border_points[i].x = (0); windata->border_points
[i].y = (14); shape_points[i].x = (0) + (0); shape_points[i].
y = (14) + (0); i++; } while (0)
;
13
Loop condition is false. Exiting loop
399
400 if (arrow_offset > 0)
14
Assuming 'arrow_offset' is > 0
15
Taking true branch
401 {
402 ADD_POINT(arrow_offset - (arrow_side2_width > 0 ? 0 : 1), DEFAULT_ARROW_HEIGHT, 0, 0)do { windata->border_points[i].x = (arrow_offset - (arrow_side2_width
> 0 ? 0 : 1)); windata->border_points[i].y = (14); shape_points
[i].x = (arrow_offset - (arrow_side2_width > 0 ? 0 : 1)) +
(0); shape_points[i].y = (14) + (0); i++; } while (0)
;
16
'?' condition is true
17
'?' condition is true
18
Loop condition is false. Exiting loop
403 }
404
405 ADD_POINT(arrow_offset + arrow_side1_width - (arrow_side2_width > 0 ? 0 : 1), 0, 0, 0)do { windata->border_points[i].x = (arrow_offset + arrow_side1_width
- (arrow_side2_width > 0 ? 0 : 1)); windata->border_points
[i].y = (0); shape_points[i].x = (arrow_offset + arrow_side1_width
- (arrow_side2_width > 0 ? 0 : 1)) + (0); shape_points[i]
.y = (0) + (0); i++; } while (0)
;
19
'?' condition is true
20
'?' condition is true
21
Loop condition is false. Exiting loop
406 }
407
408 if (arrow_side2_width
21.1
'arrow_side2_width' is > 0
> 0)
22
Taking true branch
409 {
410 ADD_POINT(windata->drawn_arrow_end_x, windata->drawn_arrow_end_y, 1, 0)do { windata->border_points[i].x = (windata->drawn_arrow_end_x
); windata->border_points[i].y = (windata->drawn_arrow_end_y
); shape_points[i].x = (windata->drawn_arrow_end_x) + (1);
shape_points[i].y = (windata->drawn_arrow_end_y) + (0); i
++; } while (0)
;
23
Loop condition is false. Exiting loop
411 ADD_POINT(width - 1, DEFAULT_ARROW_HEIGHT, 1, 0)do { windata->border_points[i].x = (width - 1); windata->
border_points[i].y = (14); shape_points[i].x = (width - 1) + (
1); shape_points[i].y = (14) + (0); i++; } while (0)
;
24
Loop condition is false. Exiting loop
412 }
413
414 ADD_POINT(width - 1, height - 1, 1, 1)do { windata->border_points[i].x = (width - 1); windata->
border_points[i].y = (height - 1); shape_points[i].x = (width
- 1) + (1); shape_points[i].y = (height - 1) + (1); i++; } while
(0)
;
25
Loop condition is false. Exiting loop
415 ADD_POINT(0, height - 1, 0, 1)do { windata->border_points[i].x = (0); windata->border_points
[i].y = (height - 1); shape_points[i].x = (0) + (0); shape_points
[i].y = (height - 1) + (1); i++; } while (0)
;
26
Access of the heap area at index 6, while it holds only 6 'struct _CdkPoint' elements
416
417 y = windata->point_y;
418 }
419 else
420 {
421 windata->drawn_arrow_begin_y = height - DEFAULT_ARROW_HEIGHT14;
422 windata->drawn_arrow_middle_y = height;
423 windata->drawn_arrow_end_y = height - DEFAULT_ARROW_HEIGHT14;
424
425 ADD_POINT(0, 0, 0, 0)do { windata->border_points[i].x = (0); windata->border_points
[i].y = (0); shape_points[i].x = (0) + (0); shape_points[i].y
= (0) + (0); i++; } while (0)
;
426 ADD_POINT(width - 1, 0, 1, 0)do { windata->border_points[i].x = (width - 1); windata->
border_points[i].y = (0); shape_points[i].x = (width - 1) + (
1); shape_points[i].y = (0) + (0); i++; } while (0)
;
427
428 if (arrow_side2_width == 0)
429 {
430 ADD_POINT(width - 1, height, (arrow_side1_width > 0 ? 0 : 1), 0)do { windata->border_points[i].x = (width - 1); windata->
border_points[i].y = (height); shape_points[i].x = (width - 1
) + ((arrow_side1_width > 0 ? 0 : 1)); shape_points[i].y =
(height) + (0); i++; } while (0)
;
431 }
432 else
433 {
434 ADD_POINT(width - 1, height - DEFAULT_ARROW_HEIGHT, 1, 1)do { windata->border_points[i].x = (width - 1); windata->
border_points[i].y = (height - 14); shape_points[i].x = (width
- 1) + (1); shape_points[i].y = (height - 14) + (1); i++; } while
(0)
;
435
436 if (arrow_offset < width - arrow_side1_width)
437 {
438 ADD_POINT(arrow_offset + arrow_side1_width + arrow_side2_width, height - DEFAULT_ARROW_HEIGHT, 0, 1)do { windata->border_points[i].x = (arrow_offset + arrow_side1_width
+ arrow_side2_width); windata->border_points[i].y = (height
- 14); shape_points[i].x = (arrow_offset + arrow_side1_width
+ arrow_side2_width) + (0); shape_points[i].y = (height - 14
) + (1); i++; } while (0)
;
439 }
440
441 ADD_POINT(arrow_offset + arrow_side1_width, height, 0, 1)do { windata->border_points[i].x = (arrow_offset + arrow_side1_width
); windata->border_points[i].y = (height); shape_points[i]
.x = (arrow_offset + arrow_side1_width) + (0); shape_points[i
].y = (height) + (1); i++; } while (0)
;
442 }
443
444 if (arrow_side1_width > 0)
445 {
446 ADD_POINT(windata->drawn_arrow_begin_x - (arrow_side2_width > 0 ? 0 : 1), windata->drawn_arrow_begin_y, 0, 0)do { windata->border_points[i].x = (windata->drawn_arrow_begin_x
- (arrow_side2_width > 0 ? 0 : 1)); windata->border_points
[i].y = (windata->drawn_arrow_begin_y); shape_points[i].x =
(windata->drawn_arrow_begin_x - (arrow_side2_width > 0
? 0 : 1)) + (0); shape_points[i].y = (windata->drawn_arrow_begin_y
) + (0); i++; } while (0)
;
447 ADD_POINT(0, height - DEFAULT_ARROW_HEIGHT, 0, 1)do { windata->border_points[i].x = (0); windata->border_points
[i].y = (height - 14); shape_points[i].x = (0) + (0); shape_points
[i].y = (height - 14) + (1); i++; } while (0)
;
448 }
449
450 y = windata->point_y - height;
451 }
452
453 #if 0
454 g_assert(i == windata->num_border_points)do { if (i == windata->num_border_points) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 454, ((const char*) (__func__)), "i == windata->num_border_points"
); } while (0)
;
455 g_assert(windata->point_x - arrow_offset - arrow_side1_width >= 0)do { if (windata->point_x - arrow_offset - arrow_side1_width
>= 0) ; else g_assertion_message_expr (((gchar*) 0), "theme.c"
, 455, ((const char*) (__func__)), "windata->point_x - arrow_offset - arrow_side1_width >= 0"
); } while (0)
;
456 #endif
457
458 ctk_window_move(CTK_WINDOW(windata->win)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->win)), ((ctk_window_get_type ()))))))
, windata->point_x - arrow_offset - arrow_side1_width, y);
459
460 break;
461
462 case CTK_ARROW_LEFT:
463 case CTK_ARROW_RIGHT:
464
465 if (norm_point_y < arrow_side1_width)
466 {
467 arrow_side1_width = 0;
468 arrow_offset = norm_point_y;
469 }
470 else if (norm_point_y > monitor_geometry.height - arrow_side2_width)
471 {
472 arrow_side2_width = 0;
473 arrow_offset = norm_point_y - arrow_side1_width;
474 }
475 break;
476
477 default:
478 g_assert_not_reached()do { g_assertion_message_expr (((gchar*) 0), "theme.c", 478, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
479 }
480
481 g_assert(shape_points != NULL)do { if (shape_points != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 481, ((const char*) (__func__)), "shape_points != NULL"
); } while (0)
;
482
483 /* FIXME won't work with CTK+3, need a replacement */
484 /*windata->window_region = cdk_region_polygon(shape_points, windata->num_border_points, CDK_EVEN_ODD_RULE);*/
485 g_free(shape_points);
486}
487
488static void draw_border (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
489 WindowData *windata,
490 cairo_t *cr)
491{
492 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
493 cairo_set_line_width(cr, 1.0);
494
495 if (windata->has_arrow)
496 {
497 size_t i;
498
499 create_border_with_arrow(windata->win, windata);
500
501 cairo_move_to(cr, windata->border_points[0].x + 0.5, windata->border_points[0].y + 0.5);
502
503 for (i = 1; i < windata->num_border_points; i++)
504 {
505 cairo_line_to(cr, windata->border_points[i].x + 0.5, windata->border_points[i].y + 0.5);
506 }
507
508 cairo_close_path(cr);
509 /* FIXME window_region is not set up anyway, see previous fixme */
510 /*cdk_window_shape_combine_region (ctk_widget_get_window (windata->win), windata->window_region, 0, 0);*/
511 g_free(windata->border_points);
512 windata->border_points = NULL((void*)0);
513 }
514 else
515 {
516 cairo_rectangle(cr, 0.5, 0.5, windata->width - 0.5, windata->height - 0.5);
517 }
518
519 cairo_stroke(cr);
520}
521
522static void
523paint_window (CtkWidget *widget,
524 cairo_t *cr,
525 WindowData *windata)
526{
527 cairo_t* cr2;
528 cairo_surface_t* surface;
529 CtkAllocation allocation;
530
531 ctk_widget_get_allocation(windata->win, &allocation);
532
533 if (windata->width == 0)
534 {
535 windata->width = allocation.width;
536 windata->height = allocation.height;
537 }
538
539 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
540
541 ctk_widget_get_allocation(widget, &allocation);
542
543 surface = cairo_surface_create_similar (cairo_get_target (cr),
544 CAIRO_CONTENT_COLOR_ALPHA,
545 allocation.width,
546 allocation.height);
547
548 cr2 = cairo_create (surface);
549
550 fill_background(widget, windata, cr2);
551 draw_border(widget, windata, cr2);
552 draw_stripe(widget, windata, cr2);
553 cairo_fill (cr2);
554 cairo_destroy (cr2);
555
556 cairo_set_source_surface (cr, surface, 0, 0);
557 cairo_paint(cr);
558 cairo_surface_destroy(surface);
559}
560
561static gboolean
562on_draw (CtkWidget *widget, cairo_t *cr, WindowData *windata)
563{
564 paint_window (widget, cr, windata);
565
566 return FALSE(0);
567}
568
569static void destroy_windata(WindowData* windata)
570{
571 if (windata->window_region != NULL((void*)0))
572 {
573 cairo_region_destroy(windata->window_region);
574 }
575
576 g_free(windata);
577}
578
579static void update_spacers(CtkWidget* nw)
580{
581 WindowData* windata;
582
583 windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
584
585 if (windata->has_arrow)
586 {
587 switch (get_notification_arrow_type(CTK_WIDGET(nw)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), ((ctk_widget_get_type ()))))))
))
588 {
589 case CTK_ARROW_UP:
590 ctk_widget_show(windata->top_spacer);
591 ctk_widget_hide(windata->bottom_spacer);
592 break;
593
594 case CTK_ARROW_DOWN:
595 ctk_widget_hide(windata->top_spacer);
596 ctk_widget_show(windata->bottom_spacer);
597 break;
598
599 default:
600 g_assert_not_reached()do { g_assertion_message_expr (((gchar*) 0), "theme.c", 600, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
601 }
602 }
603 else
604 {
605 ctk_widget_hide(windata->top_spacer);
606 ctk_widget_hide(windata->bottom_spacer);
607 }
608}
609
610static void update_content_hbox_visibility(WindowData* windata)
611{
612 /*
613 * This is all a hack, but until we have a libview-style ContentBox,
614 * it'll just have to do.
615 */
616 if (ctk_widget_get_visible(windata->icon) || ctk_widget_get_visible(windata->body_label) || ctk_widget_get_visible(windata->actions_box))
617 {
618 ctk_widget_show(windata->content_hbox);
619 }
620 else
621 {
622 ctk_widget_hide(windata->content_hbox);
623 }
624}
625
626static gboolean configure_event_cb(CtkWidget* nw, CdkEventConfigure* event, WindowData* windata)
627{
628 windata->width = event->width;
629 windata->height = event->height;
630
631 update_spacers(nw);
632 ctk_widget_queue_draw(nw);
633
634 return FALSE(0);
635}
636
637static gboolean activate_link (CtkLabel *label G_GNUC_UNUSED__attribute__ ((__unused__)),
638 const char *url,
639 WindowData *windata)
640{
641 windata->url_clicked(CTK_WINDOW(windata->win)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->win)), ((ctk_window_get_type ()))))))
, url);
642
643 return TRUE(!(0));
644}
645
646CtkWindow* create_notification(UrlClickedCb url_clicked)
647{
648 CtkWidget* spacer;
649 CtkWidget* win;
650 CtkWidget* main_vbox;
651 CtkWidget* hbox;
652 CtkWidget* vbox;
653 CtkWidget* close_button;
654 CtkWidget* image;
655 AtkObject* atkobj;
656 WindowData* windata;
657
658 CdkVisual *visual;
659 CdkScreen* screen;
660
661 windata = g_new0(WindowData, 1)((WindowData *) g_malloc0_n ((1), sizeof (WindowData)));
662 windata->urgency = URGENCY_NORMAL;
663 windata->url_clicked = url_clicked;
664
665 win = ctk_window_new(CTK_WINDOW_POPUP);
666 ctk_window_set_resizable(CTK_WINDOW(win)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win)), ((ctk_window_get_type ()))))))
, FALSE(0));
667 windata->win = win;
668
669 windata->composited = FALSE(0);
670
671
672 screen = ctk_window_get_screen(CTK_WINDOW(win)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win)), ((ctk_window_get_type ()))))))
);
673
674 visual = cdk_screen_get_rgba_visual(screen);
675
676 if (visual != NULL((void*)0))
677 {
678 ctk_widget_set_visual(win, visual);
679
680 if (cdk_screen_is_composited(screen))
681 {
682 windata->composited = TRUE(!(0));
683 }
684 }
685
686 ctk_window_set_title(CTK_WINDOW(win)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win)), ((ctk_window_get_type ()))))))
, "Notification");
687 ctk_window_set_type_hint(CTK_WINDOW(win)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win)), ((ctk_window_get_type ()))))))
, CDK_WINDOW_TYPE_HINT_NOTIFICATION);
688 ctk_widget_add_events(win, CDK_BUTTON_PRESS_MASK | CDK_BUTTON_RELEASE_MASK);
689 ctk_widget_realize(win);
690 ctk_widget_set_size_request(win, WIDTH400, -1);
691
692 g_object_set_data_full(G_OBJECT(win)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win)), (((GType) ((20) << (2))))))))
, "windata", windata, (GDestroyNotify) destroy_windata);
693 atk_object_set_role(ctk_widget_get_accessible(win), ATK_ROLE_ALERT);
694
695 g_signal_connect(G_OBJECT(win), "configure_event", G_CALLBACK(configure_event_cb), windata)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((win)), (((GType) ((20) << (2))))))
))), ("configure_event"), (((GCallback) (configure_event_cb))
), (windata), ((void*)0), (GConnectFlags) 0)
;
696
697 main_vbox = ctk_box_new(CTK_ORIENTATION_VERTICAL, 0);
698 ctk_widget_show(main_vbox);
699 ctk_container_add (CTK_CONTAINER (win)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win)), ((ctk_container_get_type ()))))))
, main_vbox);
700 ctk_container_set_border_width(CTK_CONTAINER(main_vbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((main_vbox)), ((ctk_container_get_type ()))))))
, 1);
701
702 g_signal_connect (G_OBJECT (main_vbox), "draw", G_CALLBACK (on_draw), windata)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((main_vbox)), (((GType) ((20) << (2
))))))))), ("draw"), (((GCallback) (on_draw))), (windata), ((
void*)0), (GConnectFlags) 0)
;
703
704 windata->top_spacer = ctk_image_new();
705 ctk_box_pack_start(CTK_BOX(main_vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((main_vbox)), ((ctk_box_get_type ()))))))
, windata->top_spacer, FALSE(0), FALSE(0), 0);
706 ctk_widget_set_size_request(windata->top_spacer, -1, DEFAULT_ARROW_HEIGHT14);
707
708 windata->main_hbox = ctk_box_new(CTK_ORIENTATION_HORIZONTAL, 0);
709 ctk_widget_show(windata->main_hbox);
710 ctk_box_pack_start(CTK_BOX(main_vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((main_vbox)), ((ctk_box_get_type ()))))))
, windata->main_hbox, FALSE(0), FALSE(0), 0);
711
712 windata->bottom_spacer = ctk_image_new();
713 ctk_box_pack_start(CTK_BOX(main_vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((main_vbox)), ((ctk_box_get_type ()))))))
, windata->bottom_spacer, FALSE(0), FALSE(0), 0);
714 ctk_widget_set_size_request(windata->bottom_spacer, -1, DEFAULT_ARROW_HEIGHT14);
715
716 vbox = ctk_box_new(CTK_ORIENTATION_VERTICAL, 6);
717 ctk_widget_show(vbox);
718 ctk_box_pack_start(CTK_BOX(windata->main_hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->main_hbox)), ((ctk_box_get_type ()))))))
, vbox, TRUE(!(0)), TRUE(!(0)), 0);
719 ctk_container_set_border_width(CTK_CONTAINER(vbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_container_get_type ()))))))
, 10);
720
721 hbox = ctk_box_new(CTK_ORIENTATION_HORIZONTAL, 6);
722 ctk_widget_show(hbox);
723 ctk_box_pack_start(CTK_BOX(vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
, hbox, FALSE(0), FALSE(0), 0);
724
725 spacer = ctk_image_new();
726 ctk_widget_show(spacer);
727 ctk_box_pack_start(CTK_BOX(hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, spacer, FALSE(0), FALSE(0), 0);
728 ctk_widget_set_size_request(spacer, SPACER_LEFT30, -1);
729
730 windata->summary_label = ctk_label_new(NULL((void*)0));
731 ctk_widget_show(windata->summary_label);
732 ctk_box_pack_start(CTK_BOX(hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, windata->summary_label, TRUE(!(0)), TRUE(!(0)), 0);
733 ctk_label_set_xalign (CTK_LABEL (windata->summary_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->summary_label)), ((ctk_label_get_type ()))))
))
, 0.0);
734 ctk_label_set_yalign (CTK_LABEL (windata->summary_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->summary_label)), ((ctk_label_get_type ()))))
))
, 0.0);
735 ctk_label_set_line_wrap(CTK_LABEL(windata->summary_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->summary_label)), ((ctk_label_get_type ()))))
))
, TRUE(!(0)));
736 ctk_label_set_line_wrap_mode (CTK_LABEL (windata->summary_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->summary_label)), ((ctk_label_get_type ()))))
))
, PANGO_WRAP_WORD_CHAR);
737
738 atkobj = ctk_widget_get_accessible(windata->summary_label);
739 atk_object_set_description (atkobj, _("Notification summary text.")gettext ("Notification summary text."));
740
741 /* Add the close button */
742 close_button = ctk_button_new();
743 windata->close_button = close_button;
744 ctk_widget_set_halign (close_button, CTK_ALIGN_END);
745 ctk_widget_set_valign (close_button, CTK_ALIGN_START);
746 ctk_widget_show(close_button);
747 ctk_box_pack_start(CTK_BOX(hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, close_button, FALSE(0), FALSE(0), 0);
748 ctk_button_set_relief(CTK_BUTTON(close_button)((((CtkButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((close_button)), ((ctk_button_get_type ()))))))
, CTK_RELIEF_NONE);
749 ctk_container_set_border_width(CTK_CONTAINER(close_button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((close_button)), ((ctk_container_get_type ()))))))
, 0);
750 //ctk_widget_set_size_request(close_button, 20, 20);
751 g_signal_connect_swapped(G_OBJECT(close_button), "clicked", G_CALLBACK(ctk_widget_destroy), win)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((close_button)), (((GType) ((20) <<
(2))))))))), ("clicked"), (((GCallback) (ctk_widget_destroy)
)), (win), ((void*)0), G_CONNECT_SWAPPED)
;
752
753 atkobj = ctk_widget_get_accessible(close_button);
754 atk_action_set_description(ATK_ACTION(atkobj)(((AtkAction*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((atkobj)), ((atk_action_get_type ())))))
, 0,
755 _("Closes the notification.")gettext ("Closes the notification."));
756 atk_object_set_name(atkobj, "");
757 atk_object_set_description (atkobj, _("Closes the notification.")gettext ("Closes the notification."));
758
759 image = ctk_image_new_from_icon_name ("window-close", CTK_ICON_SIZE_MENU);
760 ctk_widget_show(image);
761 ctk_container_add(CTK_CONTAINER(close_button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((close_button)), ((ctk_container_get_type ()))))))
, image);
762
763 windata->content_hbox = ctk_box_new(CTK_ORIENTATION_HORIZONTAL, 6);
764 ctk_box_pack_start(CTK_BOX(vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
, windata->content_hbox, FALSE(0), FALSE(0), 0);
765
766 windata->iconbox = ctk_box_new(CTK_ORIENTATION_HORIZONTAL, 0);
767 ctk_widget_show(windata->iconbox);
768 ctk_box_pack_start(CTK_BOX(windata->content_hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->content_hbox)), ((ctk_box_get_type ()))))))
, windata->iconbox, FALSE(0), FALSE(0), 0);
769 ctk_widget_set_size_request(windata->iconbox, BODY_X_OFFSET(32 + 8), -1);
770
771 windata->icon = ctk_image_new();
772 ctk_box_pack_start(CTK_BOX(windata->iconbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->iconbox)), ((ctk_box_get_type ()))))))
, windata->icon, TRUE(!(0)), TRUE(!(0)), 0);
773 ctk_widget_set_halign (windata->icon, CTK_ALIGN_CENTER);
774 ctk_widget_set_valign (windata->icon, CTK_ALIGN_START);
775
776 vbox = ctk_box_new(CTK_ORIENTATION_VERTICAL, 6);
777 ctk_widget_show(vbox);
778 ctk_box_pack_start(CTK_BOX(windata->content_hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->content_hbox)), ((ctk_box_get_type ()))))))
, vbox, TRUE(!(0)), TRUE(!(0)), 0);
779
780 windata->body_label = ctk_label_new(NULL((void*)0));
781 ctk_widget_show(windata->body_label);
782 ctk_box_pack_start(CTK_BOX(vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
, windata->body_label, TRUE(!(0)), TRUE(!(0)), 0);
783 ctk_label_set_xalign (CTK_LABEL (windata->body_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->body_label)), ((ctk_label_get_type ()))))))
, 0.0);
784 ctk_label_set_yalign (CTK_LABEL (windata->body_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->body_label)), ((ctk_label_get_type ()))))))
, 0.0);
785 ctk_label_set_line_wrap(CTK_LABEL(windata->body_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->body_label)), ((ctk_label_get_type ()))))))
, TRUE(!(0)));
786 ctk_label_set_line_wrap_mode (CTK_LABEL (windata->body_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->body_label)), ((ctk_label_get_type ()))))))
, PANGO_WRAP_WORD_CHAR);
787 ctk_label_set_max_width_chars (CTK_LABEL (windata->body_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->body_label)), ((ctk_label_get_type ()))))))
, 50);
788 g_signal_connect(G_OBJECT(windata->body_label), "activate-link", G_CALLBACK(activate_link), windata)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((windata->body_label)), (((GType) ((20
) << (2))))))))), ("activate-link"), (((GCallback) (activate_link
))), (windata), ((void*)0), (GConnectFlags) 0)
;
789
790 atkobj = ctk_widget_get_accessible(windata->body_label);
791 atk_object_set_description (atkobj, _("Notification body text.")gettext ("Notification body text."));
792
793 windata->actions_box = ctk_box_new(CTK_ORIENTATION_HORIZONTAL, 6);
794 ctk_widget_set_halign (windata->actions_box, CTK_ALIGN_END);
795 ctk_widget_show(windata->actions_box);
796 ctk_box_pack_start(CTK_BOX(vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
, windata->actions_box, FALSE(0), TRUE(!(0)), 0);
797
798 return CTK_WINDOW(win)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win)), ((ctk_window_get_type ()))))))
;
799}
800
801void set_notification_hints(CtkWindow *nw, GVariant *hints)
802{
803 WindowData *windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
804 guint8 urgency;
805 gboolean action_icons;
806
807 g_assert(windata != NULL)do { if (windata != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 807, ((const char*) (__func__)), "windata != NULL"
); } while (0)
;
808
809 if (g_variant_lookup(hints, "urgency", "y", &urgency))
810 {
811 windata->urgency = urgency;
812
813 if (windata->urgency == URGENCY_CRITICAL) {
814 ctk_window_set_title(CTK_WINDOW(nw)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), ((ctk_window_get_type ()))))))
, "Critical Notification");
815 } else {
816 ctk_window_set_title(CTK_WINDOW(nw)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), ((ctk_window_get_type ()))))))
, "Notification");
817 }
818 }
819
820 /* Determine if action-icons have been requested */
821 if (g_variant_lookup(hints, "action-icons", "b", &action_icons))
822 {
823 windata->action_icons = action_icons;
824 }
825}
826
827void set_notification_timeout(CtkWindow* nw, glong timeout)
828{
829 WindowData* windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
830
831 g_assert(windata != NULL)do { if (windata != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 831, ((const char*) (__func__)), "windata != NULL"
); } while (0)
;
832
833 windata->timeout = timeout;
834}
835
836void notification_tick(CtkWindow* nw, glong remaining)
837{
838 WindowData* windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
839
840 windata->remaining = remaining;
841
842 if (windata->pie_countdown != NULL((void*)0))
843 {
844 ctk_widget_queue_draw_area(windata->pie_countdown, 0, 0, PIE_WIDTH(2 * 12), PIE_HEIGHT(2 * 12));
845 }
846}
847
848void set_notification_text(CtkWindow* nw, const char* summary, const char* body)
849{
850 char* str;
851 char* quoted;
852 CtkRequisition req;
853 WindowData* windata;
854
855 windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
856 g_assert(windata != NULL)do { if (windata != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 856, ((const char*) (__func__)), "windata != NULL"
); } while (0)
;
857
858 quoted = g_markup_escape_text(summary, -1);
859 str = g_strdup_printf("<b><big>%s</big></b>", quoted);
860 g_free(quoted);
861
862 ctk_label_set_markup(CTK_LABEL(windata->summary_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->summary_label)), ((ctk_label_get_type ()))))
))
, str);
863 g_free(str);
864
865 /* body */
866 xmlDocPtr doc;
867 xmlInitParser();
868 str = g_strconcat ("<markup>", body, "</markup>", NULL((void*)0));
869 /* parse notification body */
870 doc = xmlReadMemory(str, strlen (str), "noname.xml", NULL((void*)0), 0);
871 g_free (str);
872 if (doc != NULL((void*)0)) {
873 xmlXPathContextPtr xpathCtx;
874 xmlXPathObjectPtr xpathObj;
875 xmlNodeSetPtr nodes;
876 const char *body_label_text;
877 int i, size;
878
879 /* filterout img nodes */
880 xpathCtx = xmlXPathNewContext(doc);
881 xpathObj = xmlXPathEvalExpression((unsigned char *)"//img", xpathCtx);
882 nodes = xpathObj->nodesetval;
883 size = (nodes) ? nodes->nodeNr : 0;
884 for(i = size - 1; i >= 0; i--) {
885 xmlUnlinkNode (nodes->nodeTab[i]);
886 xmlFreeNode (nodes->nodeTab[i]);
887 }
888
889 /* write doc to string */
890 xmlBufferPtr buf = xmlBufferCreate();
891 (void) xmlNodeDump(buf, doc, xmlDocGetRootElement (doc), 0, 0);
892 str = (char *)buf->content;
893 ctk_label_set_markup (CTK_LABEL (windata->body_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->body_label)), ((ctk_label_get_type ()))))))
, str);
894
895 /* cleanup */
896 xmlBufferFree (buf);
897 xmlXPathFreeObject (xpathObj);
898 xmlXPathFreeContext (xpathCtx);
899 xmlFreeDoc (doc);
900
901 /* Does it render properly? */
902 body_label_text = ctk_label_get_text (CTK_LABEL (windata->body_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->body_label)), ((ctk_label_get_type ()))))))
);
903 if ((body_label_text == NULL((void*)0)) || (strlen (body_label_text) == 0)) {
904 goto render_fail;
905 }
906 goto renrer_ok;
907 }
908
909render_fail:
910 /* could not parse notification body */
911 quoted = g_markup_escape_text(body, -1);
912 ctk_label_set_markup (CTK_LABEL (windata->body_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->body_label)), ((ctk_label_get_type ()))))))
, quoted);
913 g_free (quoted);
914
915renrer_ok:
916 xmlCleanupParser ();
917
918 if (body == NULL((void*)0) || *body == '\0')
919 ctk_widget_hide(windata->body_label);
920 else
921 ctk_widget_show(windata->body_label);
922
923 update_content_hbox_visibility(windata);
924
925 if (body != NULL((void*)0) && *body != '\0')
926 {
927 ctk_widget_get_preferred_size (windata->iconbox, NULL((void*)0), &req);
928 /* -1: border width for
929 * -6: spacing for hbox */
930 ctk_widget_set_size_request(windata->body_label, WIDTH400 - (1 * 2) - (10 * 2) - req.width - 6, -1);
931 }
932
933 ctk_widget_get_preferred_size (windata->close_button, NULL((void*)0), &req);
934 /* -1: main_vbox border width
935 * -10: vbox border width
936 * -6: spacing for hbox */
937 ctk_widget_set_size_request(windata->summary_label, WIDTH400 - (1 * 2) - (10 * 2) - SPACER_LEFT30 - req.width - (6 * 2), -1);
938}
939
940void set_notification_icon(CtkWindow* nw, GdkPixbuf* pixbuf)
941{
942 WindowData* windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
943
944 g_assert(windata != NULL)do { if (windata != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 944, ((const char*) (__func__)), "windata != NULL"
); } while (0)
;
945
946 ctk_image_set_from_pixbuf(CTK_IMAGE(windata->icon)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->icon)), ((ctk_image_get_type ()))))))
, pixbuf);
947
948 if (pixbuf != NULL((void*)0))
949 {
950 int pixbuf_width = gdk_pixbuf_get_width(pixbuf);
951
952 ctk_widget_show(windata->icon);
953 ctk_widget_set_size_request(windata->iconbox, MAX(BODY_X_OFFSET, pixbuf_width)((((32 + 8)) > (pixbuf_width)) ? ((32 + 8)) : (pixbuf_width
))
, -1);
954 }
955 else
956 {
957 ctk_widget_hide(windata->icon);
958 ctk_widget_set_size_request(windata->iconbox, BODY_X_OFFSET(32 + 8), -1);
959 }
960
961 update_content_hbox_visibility(windata);
962}
963
964void set_notification_arrow(CtkWidget* nw, gboolean visible, int x, int y)
965{
966 WindowData* windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
967
968 g_assert(windata != NULL)do { if (windata != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 968, ((const char*) (__func__)), "windata != NULL"
); } while (0)
;
969
970 windata->has_arrow = visible;
971 windata->point_x = x;
972 windata->point_y = y;
973
974 update_spacers(nw);
975}
976
977static void
978paint_countdown (CtkWidget *pie,
979 cairo_t *cr,
980 WindowData *windata)
981{
982 CtkStyleContext *context;
983 CdkRGBA bg;
984 CtkAllocation alloc;
985 cairo_t* cr2;
986 cairo_surface_t* surface;
987
988 context = ctk_widget_get_style_context (windata->win);
989
990 ctk_style_context_save (context);
991 ctk_style_context_set_state (context, CTK_STATE_FLAG_SELECTED);
992
993 get_background_color (context, CTK_STATE_FLAG_SELECTED, &bg);
994
995 ctk_style_context_restore (context);
996
997 ctk_widget_get_allocation(pie, &alloc);
998 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
999 surface = cairo_surface_create_similar (cairo_get_target(cr),
1000 CAIRO_CONTENT_COLOR_ALPHA,
1001 alloc.width,
1002 alloc.height);
1003
1004 cr2 = cairo_create (surface);
1005
1006 fill_background (pie, windata, cr2);
1007
1008 if (windata->timeout > 0)
1009 {
1010 gdouble pct = (gdouble) windata->remaining / (gdouble) windata->timeout;
1011
1012 cdk_cairo_set_source_rgba (cr2, &bg);
1013
1014 cairo_move_to (cr2, PIE_RADIUS12, PIE_RADIUS12);
1015 cairo_arc_negative (cr2, PIE_RADIUS12, PIE_RADIUS12, PIE_RADIUS12, -G_PI_21.5707963267948966192313216916397514420985846996876, -(pct * G_PI3.1415926535897932384626433832795028841971693993751 * 2) - G_PI_21.5707963267948966192313216916397514420985846996876);
1016 cairo_line_to (cr2, PIE_RADIUS12, PIE_RADIUS12);
1017 cairo_fill (cr2);
1018 }
1019
1020 cairo_destroy(cr2);
1021
1022 cairo_save (cr);
1023 cairo_set_source_surface (cr, surface, 0, 0);
1024 cairo_paint (cr);
1025 cairo_restore (cr);
1026
1027 cairo_surface_destroy(surface);
1028}
1029
1030static gboolean
1031on_countdown_draw (CtkWidget *widget, cairo_t *cr, WindowData *windata)
1032{
1033 paint_countdown (widget, cr, windata);
1034
1035 return FALSE(0);
1036}
1037
1038static void action_clicked_cb (CtkWidget *w,
1039 CdkEventButton *event G_GNUC_UNUSED__attribute__ ((__unused__)),
1040 ActionInvokedCb action_cb)
1041{
1042 CtkWindow* nw;
1043 const char* key;
1044 nw = g_object_get_data(G_OBJECT(w)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), (((GType) ((20) << (2))))))))
, "_nw");
1045 key = g_object_get_data(G_OBJECT(w)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), (((GType) ((20) << (2))))))))
, "_action_key");
1046 action_cb(nw, key);
1047}
1048
1049void add_notification_action(CtkWindow* nw, const char* text, const char* key, ActionInvokedCb cb)
1050{
1051 WindowData* windata;
1052 CtkWidget* label;
1053 CtkWidget* button;
1054 CtkWidget* hbox;
1055 GdkPixbuf* pixbuf;
1056 char* buf;
1057
1058 windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
1059
1060 g_assert(windata != NULL)do { if (windata != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 1060, ((const char*) (__func__)), "windata != NULL"
); } while (0)
;
1061
1062 if (ctk_widget_get_visible(windata->actions_box))
1063 {
1064 ctk_widget_show(windata->actions_box);
1065 update_content_hbox_visibility(windata);
1066
1067 /* Don't try to re-add a pie_countdown */
1068 if (!windata->pie_countdown) {
1069 windata->pie_countdown = ctk_drawing_area_new();
1070 ctk_widget_set_halign (windata->pie_countdown, CTK_ALIGN_END);
1071 ctk_widget_show(windata->pie_countdown);
1072
1073 ctk_box_pack_end (CTK_BOX (windata->actions_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->actions_box)), ((ctk_box_get_type ()))))))
, windata->pie_countdown, FALSE(0), TRUE(!(0)), 0);
1074 ctk_widget_set_size_request(windata->pie_countdown,
1075 PIE_WIDTH(2 * 12), PIE_HEIGHT(2 * 12));
1076 g_signal_connect(G_OBJECT(windata->pie_countdown), "draw",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((windata->pie_countdown)), (((GType) (
(20) << (2))))))))), ("draw"), (((GCallback) (on_countdown_draw
))), (windata), ((void*)0), (GConnectFlags) 0)
1077 G_CALLBACK(on_countdown_draw), windata)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((windata->pie_countdown)), (((GType) (
(20) << (2))))))))), ("draw"), (((GCallback) (on_countdown_draw
))), (windata), ((void*)0), (GConnectFlags) 0)
;
1078 }
1079 }
1080
1081 if (windata->action_icons) {
1082 button = ctk_button_new_from_icon_name(key, CTK_ICON_SIZE_BUTTON);
1083 goto add_button;
1084 }
1085
1086 button = ctk_button_new();
1087 hbox = ctk_box_new(CTK_ORIENTATION_HORIZONTAL, 6);
1088 ctk_widget_show(hbox);
1089 ctk_container_add(CTK_CONTAINER(button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_container_get_type ()))))))
, hbox);
1090
1091 /* Try to be smart and find a suitable icon. */
1092 buf = g_strdup_printf("stock_%s", key);
1093 pixbuf = ctk_icon_theme_load_icon(ctk_icon_theme_get_for_screen(cdk_window_get_screen(ctk_widget_get_window(CTK_WIDGET(nw)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), ((ctk_widget_get_type ()))))))
))),
1094 buf, 16, CTK_ICON_LOOKUP_USE_BUILTIN, NULL((void*)0));
1095 g_free(buf);
1096
1097 if (pixbuf != NULL((void*)0))
1098 {
1099 CtkWidget* image = ctk_image_new_from_pixbuf(pixbuf);
1100 ctk_widget_show(image);
1101 ctk_box_pack_start(CTK_BOX(hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, image, FALSE(0), FALSE(0), 0);
1102 ctk_widget_set_halign (image, CTK_ALIGN_CENTER);
1103 ctk_widget_set_valign (image, CTK_ALIGN_CENTER);
1104 }
1105
1106 label = ctk_label_new(NULL((void*)0));
1107 ctk_widget_show(label);
1108 ctk_box_pack_start(CTK_BOX(hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, label, FALSE(0), FALSE(0), 0);
1109 ctk_label_set_xalign (CTK_LABEL (label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_label_get_type ()))))))
, 0.0);
1110 ctk_label_set_yalign (CTK_LABEL (label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_label_get_type ()))))))
, 0.5);
1111 buf = g_strdup_printf("<small>%s</small>", text);
1112 ctk_label_set_markup(CTK_LABEL(label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_label_get_type ()))))))
, buf);
1113 g_free(buf);
1114
1115add_button:
1116 ctk_widget_show(button);
1117 ctk_box_pack_start(CTK_BOX(windata->actions_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->actions_box)), ((ctk_box_get_type ()))))))
, button, FALSE(0), FALSE(0), 0);
1118
1119 g_object_set_data(G_OBJECT(button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "_nw", nw);
1120 g_object_set_data_full(G_OBJECT(button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "_action_key", g_strdup(key)g_strdup_inline (key), g_free);
1121 g_signal_connect(G_OBJECT(button), "button-release-event", G_CALLBACK(action_clicked_cb), cb)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), ("button-release-event"), (((GCallback) (action_clicked_cb
))), (cb), ((void*)0), (GConnectFlags) 0)
;
1122
1123 ctk_widget_show_all(windata->actions_box);
1124}
1125
1126void clear_notification_actions(CtkWindow* nw)
1127{
1128 WindowData* windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
1129
1130 windata->pie_countdown = NULL((void*)0);
1131
1132 ctk_widget_hide(windata->actions_box);
1133 ctk_container_foreach(CTK_CONTAINER(windata->actions_box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((windata->actions_box)), ((ctk_container_get_type ()))
))))
, (CtkCallback) ctk_widget_destroy, NULL((void*)0));
1134}
1135
1136void move_notification(CtkWidget* nw, int x, int y)
1137{
1138 WindowData* windata = g_object_get_data(G_OBJECT(nw)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), (((GType) ((20) << (2))))))))
, "windata");
1139
1140 g_assert(windata != NULL)do { if (windata != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "theme.c", 1140, ((const char*) (__func__)), "windata != NULL"
); } while (0)
;
1141
1142 if (windata->has_arrow)
1143 {
1144 ctk_widget_queue_resize(nw);
1145 }
1146 else
1147 {
1148 ctk_window_move(CTK_WINDOW(nw)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((nw)), ((ctk_window_get_type ()))))))
, x, y);
1149 }
1150}
1151
1152void get_theme_info(char** theme_name, char** theme_ver, char** author, char** homepage)
1153{
1154 *theme_name = g_strdup("Standard")g_strdup_inline ("Standard");
1155
1156 /* If they are constants, maybe we can remove printf and use G_STRINGIFY() */
1157 *theme_ver = g_strdup_printf("%d.%d.%d", NOTIFICATION_DAEMON_MAJOR_VERSION1, NOTIFICATION_DAEMON_MINOR_VERSION3, NOTIFICATION_DAEMON_MICRO_VERSION0);
1158 *author = g_strdup("Christian Hammond")g_strdup_inline ("Christian Hammond");
1159 *homepage = g_strdup("http://www.galago-project.org/")g_strdup_inline ("http://www.galago-project.org/");
1160}
1161
1162gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver, unsigned int micro_ver)
1163{
1164 return major_ver == NOTIFICATION_DAEMON_MAJOR_VERSION1 && minor_ver == NOTIFICATION_DAEMON_MINOR_VERSION3 && micro_ver == NOTIFICATION_DAEMON_MICRO_VERSION0;
1165}