Bug Summary

File:libcafe-panel-applet/cafe-panel-applet.c
Warning:line 1611, column 34
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

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 cafe-panel-applet.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 -fcoverage-compilation-dir=/rootdir/libcafe-panel-applet -resource-dir /usr/lib/llvm-16/lib/clang/16 -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 -I ../libcafe-panel-applet -D CAFELOCALEDIR="/usr/share/locale" -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/libcafe-panel-applet -ferror-limit 19 -fgnuc-version=4.2.1 -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.core.SizeofPtr -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/2024-07-14-140356-56036-1 -x c cafe-panel-applet.c
1/*
2 * cafe-panel-applet.c: panel applet writing library.
3 *
4 * Copyright (c) 2010 Carlos Garcia Campos <carlosgc@gnome.org>
5 * Copyright (C) 2001 Sun Microsystems, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 * Authors:
23 * Mark McLoughlin <mark@skynet.ie>
24 */
25
26#ifdef HAVE_CONFIG_H1
27#include <config.h>
28#endif
29
30#include <unistd.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include <glib/gi18n-lib.h>
35#include <cairo.h>
36#include <cdk/cdk.h>
37#include <cdk/cdkkeysyms.h>
38#include <ctk/ctk.h>
39
40#ifdef HAVE_X111
41#include <cairo-xlib.h>
42#include <cdk/cdkx.h>
43#include <ctk/ctkx.h>
44#include <X11/Xatom.h>
45#include "panel-plug-private.h"
46#endif
47
48#include "cafe-panel-applet.h"
49#include "panel-applet-private.h"
50#include "cafe-panel-applet-factory.h"
51#include "cafe-panel-applet-marshal.h"
52#include "cafe-panel-applet-enums.h"
53
54struct _CafePanelAppletPrivate {
55 CtkWidget *plug;
56 GDBusConnection *connection;
57
58 gboolean out_of_process;
59
60 char *id;
61 GClosure *closure;
62 char *object_path;
63 guint object_id;
64 char *prefs_path;
65
66 CtkUIManager *ui_manager;
67 CtkActionGroup *applet_action_group;
68 CtkActionGroup *panel_action_group;
69
70 CafePanelAppletFlags flags;
71 CafePanelAppletOrient orient;
72 guint size;
73 char *background;
74
75 int previous_width;
76 int previous_height;
77
78 int *size_hints;
79 int size_hints_len;
80
81 gboolean moving_focus_out;
82
83 gboolean locked;
84 gboolean locked_down;
85};
86
87enum {
88 CHANGE_ORIENT,
89 CHANGE_SIZE,
90 CHANGE_BACKGROUND,
91 MOVE_FOCUS_OUT_OF_APPLET,
92 LAST_SIGNAL
93};
94
95static guint cafe_panel_applet_signals[LAST_SIGNAL] = { 0 };
96
97enum {
98 PROP_0,
99 PROP_OUT_OF_PROCESS,
100 PROP_ID,
101 PROP_CLOSURE,
102 PROP_CONNECTION,
103 PROP_PREFS_PATH,
104 PROP_ORIENT,
105 PROP_SIZE,
106 PROP_BACKGROUND,
107 PROP_FLAGS,
108 PROP_SIZE_HINTS,
109 PROP_LOCKED,
110 PROP_LOCKED_DOWN
111};
112
113static void cafe_panel_applet_handle_background (CafePanelApplet *applet);
114static CtkAction *cafe_panel_applet_menu_get_action (CafePanelApplet *applet,
115 const gchar *action);
116static void cafe_panel_applet_menu_update_actions (CafePanelApplet *applet);
117static void cafe_panel_applet_menu_cmd_remove (CtkAction *action,
118 CafePanelApplet *applet);
119static void cafe_panel_applet_menu_cmd_move (CtkAction *action,
120 CafePanelApplet *applet);
121static void cafe_panel_applet_menu_cmd_lock (CtkAction *action,
122 CafePanelApplet *applet);
123static void cafe_panel_applet_register_object (CafePanelApplet *applet);
124void _cafe_panel_applet_apply_css (CtkWidget* widget, CafePanelAppletBackgroundType type);
125
126static const gchar panel_menu_ui[] =
127 "<ui>\n"
128 " <popup name=\"CafePanelAppletPopup\" action=\"PopupAction\">\n"
129 " <placeholder name=\"AppletItems\"/>\n"
130 " <separator/>\n"
131 " <menuitem name=\"RemoveItem\" action=\"Remove\"/>\n"
132 " <menuitem name=\"MoveItem\" action=\"Move\"/>\n"
133 " <separator/>\n"
134 " <menuitem name=\"LockItem\" action=\"Lock\"/>\n"
135 " </popup>\n"
136 "</ui>\n";
137
138static const CtkActionEntry menu_entries[] = {
139 { "Remove", "list-remove", N_("_Remove From Panel")("_Remove From Panel"),
140 NULL((void*)0), NULL((void*)0),
141 G_CALLBACK (cafe_panel_applet_menu_cmd_remove)((GCallback) (cafe_panel_applet_menu_cmd_remove)) },
142 { "Move", NULL((void*)0), N_("_Move")("_Move"),
143 NULL((void*)0), NULL((void*)0),
144 G_CALLBACK (cafe_panel_applet_menu_cmd_move)((GCallback) (cafe_panel_applet_menu_cmd_move)) }
145};
146
147static const CtkToggleActionEntry menu_toggle_entries[] = {
148 { "Lock", NULL((void*)0), N_("Loc_k To Panel")("Loc_k To Panel"),
149 NULL((void*)0), NULL((void*)0),
150 G_CALLBACK (cafe_panel_applet_menu_cmd_lock)((GCallback) (cafe_panel_applet_menu_cmd_lock)) }
151};
152
153G_DEFINE_TYPE_WITH_PRIVATE (CafePanelApplet, cafe_panel_applet, CTK_TYPE_EVENT_BOX)static void cafe_panel_applet_init (CafePanelApplet *self); static
void cafe_panel_applet_class_init (CafePanelAppletClass *klass
); static GType cafe_panel_applet_get_type_once (void); static
gpointer cafe_panel_applet_parent_class = ((void*)0); static
gint CafePanelApplet_private_offset; static void cafe_panel_applet_class_intern_init
(gpointer klass) { cafe_panel_applet_parent_class = g_type_class_peek_parent
(klass); if (CafePanelApplet_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CafePanelApplet_private_offset); cafe_panel_applet_class_init
((CafePanelAppletClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer cafe_panel_applet_get_instance_private
(CafePanelApplet *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CafePanelApplet_private_offset)))); } GType cafe_panel_applet_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= cafe_panel_applet_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType cafe_panel_applet_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((ctk_event_box_get_type ()), g_intern_static_string ("CafePanelApplet"
), sizeof (CafePanelAppletClass), (GClassInitFunc)(void (*)(void
)) cafe_panel_applet_class_intern_init, sizeof (CafePanelApplet
), (GInstanceInitFunc)(void (*)(void)) cafe_panel_applet_init
, (GTypeFlags) 0); { {{ CafePanelApplet_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CafePanelAppletPrivate)); };} } return
g_define_type_id; }
154
155#define CAFE_PANEL_APPLET_INTERFACE"org.cafe.panel.applet.Applet" "org.cafe.panel.applet.Applet"
156#define CAFE_PANEL_APPLET_OBJECT_PATH"/org/cafe/panel/applet/%s/%d" "/org/cafe/panel/applet/%s/%d"
157
158char *
159cafe_panel_applet_get_preferences_path (CafePanelApplet *applet)
160{
161 g_return_val_if_fail (PANEL_IS_APPLET (applet), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return (((void
*)0)); } } while (0)
;
162
163 if (!applet->priv->prefs_path)
164 return NULL((void*)0);
165
166 return g_strdup (applet->priv->prefs_path)g_strdup_inline (applet->priv->prefs_path);
167}
168
169static void
170cafe_panel_applet_set_preferences_path (CafePanelApplet *applet,
171 const char *prefs_path)
172{
173 if (applet->priv->prefs_path == prefs_path)
174 return;
175
176 if (g_strcmp0 (applet->priv->prefs_path, prefs_path) == 0)
177 return;
178
179 if (prefs_path) {
180 applet->priv->prefs_path = g_strdup (prefs_path)g_strdup_inline (prefs_path);
181
182 }
183
184 g_object_notify (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
, "prefs-path");
185}
186
187CafePanelAppletFlags
188cafe_panel_applet_get_flags (CafePanelApplet *applet)
189{
190 g_return_val_if_fail (PANEL_IS_APPLET (applet), CAFE_PANEL_APPLET_FLAGS_NONE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return (CAFE_PANEL_APPLET_FLAGS_NONE
); } } while (0)
;
191
192 return applet->priv->flags;
193}
194
195void
196cafe_panel_applet_set_flags (CafePanelApplet *applet,
197 CafePanelAppletFlags flags)
198{
199 g_return_if_fail (PANEL_IS_APPLET (applet))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return; } }
while (0)
;
200
201 if (applet->priv->flags == flags)
202 return;
203
204 applet->priv->flags = flags;
205
206 g_object_notify (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
, "flags");
207
208 if (applet->priv->connection) {
209 GVariantBuilder builder;
210 GVariantBuilder invalidated_builder;
211 GError *error = NULL((void*)0);
212
213 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY((const GVariantType *) "a*"));
214 g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")(g_variant_type_checked_ (("as"))));
215
216 g_variant_builder_add (&builder, "{sv}", "Flags",
217 g_variant_new_uint32 (applet->priv->flags));
218
219 g_dbus_connection_emit_signal (applet->priv->connection,
220 NULL((void*)0),
221 applet->priv->object_path,
222 "org.freedesktop.DBus.Properties",
223 "PropertiesChanged",
224 g_variant_new ("(sa{sv}as)",
225 CAFE_PANEL_APPLET_INTERFACE"org.cafe.panel.applet.Applet",
226 &builder,
227 &invalidated_builder),
228 &error);
229 if (error) {
230 g_printerr ("Failed to send signal PropertiesChanged::Flags: %s\n",
231 error->message);
232 g_error_free (error);
233 }
234 g_variant_builder_clear (&builder);
235 g_variant_builder_clear (&invalidated_builder);
236 }
237}
238
239static void
240cafe_panel_applet_size_hints_ensure (CafePanelApplet *applet,
241 int new_size)
242{
243 if (applet->priv->size_hints && applet->priv->size_hints_len < new_size) {
244 g_free (applet->priv->size_hints);
245 applet->priv->size_hints = g_new (gint, new_size)((gint *) g_malloc_n ((new_size), sizeof (gint)));
246 } else if (!applet->priv->size_hints) {
247 applet->priv->size_hints = g_new (gint, new_size)((gint *) g_malloc_n ((new_size), sizeof (gint)));
248 }
249 applet->priv->size_hints_len = new_size;
250}
251
252static gboolean
253cafe_panel_applet_size_hints_changed (CafePanelApplet *applet,
254 const int *size_hints,
255 int n_elements,
256 int base_size)
257{
258 gint i;
259
260 if (!applet->priv->size_hints)
261 return TRUE(!(0));
262
263 if (applet->priv->size_hints_len != n_elements)
264 return TRUE(!(0));
265
266 for (i = 0; i < n_elements; i++) {
267 if (size_hints[i] + base_size != applet->priv->size_hints[i])
268 return TRUE(!(0));
269 }
270
271 return FALSE(0);
272}
273
274/**
275 * cafe_panel_applet_set_size_hints:
276 * @applet: applet
277 * @size_hints: (array length=n_elements): List of integers
278 * @n_elements: Length of @size_hints
279 * @base_size: base_size
280 */
281void
282cafe_panel_applet_set_size_hints (CafePanelApplet *applet,
283 const int *size_hints,
284 int n_elements,
285 int base_size)
286{
287 gint i;
288
289 /* Make sure property has really changed to avoid bus traffic */
290 if (!cafe_panel_applet_size_hints_changed (applet, size_hints, n_elements, base_size))
291 return;
292
293 cafe_panel_applet_size_hints_ensure (applet, n_elements);
294 for (i = 0; i < n_elements; i++)
295 applet->priv->size_hints[i] = size_hints[i] + base_size;
296
297 g_object_notify (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
, "size-hints");
298
299 if (applet->priv->connection) {
300 GVariantBuilder builder;
301 GVariantBuilder invalidated_builder;
302 GVariant **children;
303 GError *error = NULL((void*)0);
304
305 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY((const GVariantType *) "a*"));
306 g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")(g_variant_type_checked_ (("as"))));
307
308 children = g_new (GVariant *, applet->priv->size_hints_len)((GVariant * *) g_malloc_n ((applet->priv->size_hints_len
), sizeof (GVariant *)))
;
309 for (i = 0; i < n_elements; i++)
310 children[i] = g_variant_new_int32 (applet->priv->size_hints[i]);
311 g_variant_builder_add (&builder, "{sv}", "SizeHints",
312 g_variant_new_array (G_VARIANT_TYPE_INT32((const GVariantType *) "i"),
313 children, applet->priv->size_hints_len));
314 g_free (children);
315
316 g_dbus_connection_emit_signal (applet->priv->connection,
317 NULL((void*)0),
318 applet->priv->object_path,
319 "org.freedesktop.DBus.Properties",
320 "PropertiesChanged",
321 g_variant_new ("(sa{sv}as)",
322 CAFE_PANEL_APPLET_INTERFACE"org.cafe.panel.applet.Applet",
323 &builder,
324 &invalidated_builder),
325 &error);
326 if (error) {
327 g_printerr ("Failed to send signal PropertiesChanged::SizeHints: %s\n",
328 error->message);
329 g_error_free (error);
330 }
331 g_variant_builder_clear (&builder);
332 g_variant_builder_clear (&invalidated_builder);
333 }
334}
335
336guint
337cafe_panel_applet_get_size (CafePanelApplet *applet)
338{
339 g_return_val_if_fail (PANEL_IS_APPLET (applet), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return (0);
} } while (0)
;
340
341 return applet->priv->size;
342}
343
344/* Applets cannot set their size, so API is not public. */
345static void
346cafe_panel_applet_set_size (CafePanelApplet *applet,
347 guint size)
348{
349 g_return_if_fail (PANEL_IS_APPLET (applet))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return; } }
while (0)
;
350
351 if (applet->priv->size == size)
352 return;
353
354 applet->priv->size = size;
355 g_signal_emit (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
,
356 cafe_panel_applet_signals [CHANGE_SIZE],
357 0, size);
358
359 g_object_notify (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
, "size");
360}
361
362CafePanelAppletOrient
363cafe_panel_applet_get_orient (CafePanelApplet *applet)
364{
365 g_return_val_if_fail (PANEL_IS_APPLET (applet), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return (0);
} } while (0)
;
366
367 return applet->priv->orient;
368}
369
370/* Applets cannot set their orientation, so API is not public. */
371static void
372cafe_panel_applet_set_orient (CafePanelApplet *applet,
373 CafePanelAppletOrient orient)
374{
375 g_return_if_fail (PANEL_IS_APPLET (applet))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return; } }
while (0)
;
376
377 if (applet->priv->orient == orient)
378 return;
379
380 applet->priv->orient = orient;
381 g_signal_emit (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
,
382 cafe_panel_applet_signals [CHANGE_ORIENT],
383 0, orient);
384
385 g_object_notify (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
, "orient");
386}
387
388static void
389cafe_panel_applet_set_locked (CafePanelApplet *applet,
390 gboolean locked)
391{
392 CtkAction *action;
393
394 g_return_if_fail (PANEL_IS_APPLET (applet))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return; } }
while (0)
;
395
396 if (applet->priv->locked == locked)
397 return;
398
399 applet->priv->locked = locked;
400
401 action = cafe_panel_applet_menu_get_action (applet, "Lock");
402 g_signal_handlers_block_by_func (action,g_signal_handlers_block_matched ((action), (GSignalMatchType)
(G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0
), (cafe_panel_applet_menu_cmd_lock), (applet))
403 cafe_panel_applet_menu_cmd_lock,g_signal_handlers_block_matched ((action), (GSignalMatchType)
(G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0
), (cafe_panel_applet_menu_cmd_lock), (applet))
404 applet)g_signal_handlers_block_matched ((action), (GSignalMatchType)
(G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0
), (cafe_panel_applet_menu_cmd_lock), (applet))
;
405 ctk_toggle_action_set_active (CTK_TOGGLE_ACTION (action)((((CtkToggleAction*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((action)), ((ctk_toggle_action_get_type ()))))))
, locked);
406 g_signal_handlers_unblock_by_func (action,g_signal_handlers_unblock_matched ((action), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (cafe_panel_applet_menu_cmd_lock), (applet))
407 cafe_panel_applet_menu_cmd_lock,g_signal_handlers_unblock_matched ((action), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (cafe_panel_applet_menu_cmd_lock), (applet))
408 applet)g_signal_handlers_unblock_matched ((action), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (cafe_panel_applet_menu_cmd_lock), (applet))
;
409
410 cafe_panel_applet_menu_update_actions (applet);
411
412 g_object_notify (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
, "locked");
413
414 if (applet->priv->connection) {
415 GError *error = NULL((void*)0);
416
417 g_dbus_connection_emit_signal (applet->priv->connection,
418 NULL((void*)0),
419 applet->priv->object_path,
420 CAFE_PANEL_APPLET_INTERFACE"org.cafe.panel.applet.Applet",
421 locked ? "Lock" : "Unlock",
422 NULL((void*)0), &error);
423 if (error) {
424 g_printerr ("Failed to send signal %s: %s\n",
425 locked ? "Lock" : "Unlock",
426 error->message);
427 g_error_free (error);
428 }
429 }
430}
431
432gboolean
433cafe_panel_applet_get_locked_down (CafePanelApplet *applet)
434{
435 g_return_val_if_fail (PANEL_IS_APPLET (applet), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return ((0)
); } } while (0)
;
436
437 return applet->priv->locked_down;
438}
439
440/* Applets cannot set the lockdown state, so API is not public. */
441static void
442cafe_panel_applet_set_locked_down (CafePanelApplet *applet,
443 gboolean locked_down)
444{
445 g_return_if_fail (PANEL_IS_APPLET (applet))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return; } }
while (0)
;
446
447 if (applet->priv->locked_down == locked_down)
448 return;
449
450 applet->priv->locked_down = locked_down;
451 cafe_panel_applet_menu_update_actions (applet);
452
453 g_object_notify (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
, "locked-down");
454}
455
456#ifdef HAVE_X111
457
458static Atom _net_wm_window_type = None0L;
459static Atom _net_wm_window_type_dock = None0L;
460static Atom _net_active_window = None0L;
461
462static void
463cafe_panel_applet_init_atoms (Display *xdisplay)
464{
465 if (_net_wm_window_type == None0L)
466 _net_wm_window_type = XInternAtom (xdisplay,
467 "_NET_WM_WINDOW_TYPE",
468 False0);
469
470 if (_net_wm_window_type_dock == None0L)
471 _net_wm_window_type_dock = XInternAtom (xdisplay,
472 "_NET_WM_WINDOW_TYPE_DOCK",
473 False0);
474
475 if (_net_active_window == None0L)
476 _net_active_window = XInternAtom (xdisplay,
477 "_NET_ACTIVE_WINDOW",
478 False0);
479}
480
481static Window
482cafe_panel_applet_find_toplevel_dock_window (CafePanelApplet *applet,
483 Display *xdisplay)
484{
485 CtkWidget *toplevel;
486 Window xwin;
487 Window root, parent, *child;
488 int num_children;
489
490 toplevel = ctk_widget_get_toplevel (CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
);
491 if (!ctk_widget_get_realized (toplevel))
492 return None0L;
493
494 xwin = CDK_WINDOW_XID (ctk_widget_get_window (toplevel))(cdk_x11_window_get_xid (ctk_widget_get_window (toplevel)));
495
496 child = NULL((void*)0);
497 parent = root = None0L;
498 do {
499 Atom type_return;
500 Atom window_type;
501 int format_return;
502 gulong number_return, bytes_after_return;
503 guchar *data_return;
504
505 XGetWindowProperty (xdisplay,
506 xwin,
507 _net_wm_window_type,
508 0, 1, False0,
509 XA_ATOM((Atom) 4),
510 &type_return, &format_return,
511 &number_return,
512 &bytes_after_return,
513 &data_return);
514
515 if (type_return == XA_ATOM((Atom) 4)) {
516 window_type = *(Atom *) data_return;
517
518 XFree (data_return);
519 data_return = NULL((void*)0);
520
521 if (window_type == _net_wm_window_type_dock)
522 return xwin;
523 }
524
525 if (!XQueryTree (xdisplay,
526 xwin,
527 &root, &parent, &child,
528 (guint *) &num_children)) {
529 return None0L;
530 }
531
532 if (child && num_children > 0)
533 XFree (child);
534
535 xwin = parent;
536
537 } while (xwin != None0L && xwin != root);
538
539 return None0L;
540}
541
542#endif // HAVE_X11
543
544/* This function
545 * 1) Gets the window id of the panel that contains the applet
546 * using XQueryTree and XGetWindowProperty to find an ancestor
547 * window with the _NET_WM_WINDOW_TYPE_DOCK window type.
548 * 2) Sends a _NET_ACTIVE_WINDOW message to get that panel focused
549 */
550void
551cafe_panel_applet_request_focus (CafePanelApplet *applet,
552 guint32 timestamp)
553{
554#ifdef HAVE_X111
555 CdkScreen *screen;
556 CdkWindow *root;
557 CdkDisplay *display;
558 Display *xdisplay;
559 Window dock_xwindow;
560 Window xroot;
561 XEvent xev;
562
563 if (!CDK_IS_X11_DISPLAY (cdk_display_get_default ())(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(cdk_display_get_default ())); GType __t = ((cdk_x11_display_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; }))))
)
564 return;
565
566 g_return_if_fail (PANEL_IS_APPLET (applet))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return; } }
while (0)
;
567
568 screen = ctk_window_get_screen (CTK_WINDOW (applet->priv->plug)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_window_get_type ()))))
))
);
569 root = cdk_screen_get_root_window (screen);
570 display = cdk_screen_get_display (screen);
571
572 xdisplay = CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display));
573 xroot = CDK_WINDOW_XID (root)(cdk_x11_window_get_xid (root));
574
575 cafe_panel_applet_init_atoms (xdisplay);
576
577 dock_xwindow = cafe_panel_applet_find_toplevel_dock_window (applet, xdisplay);
578 if (dock_xwindow == None0L)
579 return;
580
581 xev.xclient.type = ClientMessage33;
582 xev.xclient.serial = 0;
583 xev.xclient.send_event = True1;
584 xev.xclient.window = dock_xwindow;
585 xev.xclient.message_type = _net_active_window;
586 xev.xclient.format = 32;
587 xev.xclient.data.l[0] = 1; /* requestor type; we're an app, I guess */
588 xev.xclient.data.l[1] = timestamp;
589 xev.xclient.data.l[2] = None0L; /* "currently active window", supposedly */
590 xev.xclient.data.l[3] = 0;
591 xev.xclient.data.l[4] = 0;
592
593 XSendEvent (xdisplay,
594 xroot, False0,
595 SubstructureRedirectMask(1L<<20) | SubstructureNotifyMask(1L<<19),
596 &xev);
597#endif
598}
599
600static CtkAction *
601cafe_panel_applet_menu_get_action (CafePanelApplet *applet,
602 const gchar *action)
603{
604 return ctk_action_group_get_action (applet->priv->panel_action_group, action);
605}
606
607static void
608cafe_panel_applet_menu_update_actions (CafePanelApplet *applet)
609{
610 gboolean locked = applet->priv->locked;
611 gboolean locked_down = applet->priv->locked_down;
612
613 g_object_set (cafe_panel_applet_menu_get_action (applet, "Lock"),
614 "visible", !locked_down, NULL((void*)0));
615 g_object_set (cafe_panel_applet_menu_get_action (applet, "Move"),
616 "sensitive", !locked,
617 "visible", !locked_down,
618 NULL((void*)0));
619 g_object_set (cafe_panel_applet_menu_get_action (applet, "Remove"),
620 "sensitive", !locked,
621 "visible", !locked_down,
622 NULL((void*)0));
623}
624
625static void
626cafe_panel_applet_menu_cmd_remove (CtkAction *action,
627 CafePanelApplet *applet)
628{
629 GError *error = NULL((void*)0);
630
631 if (!applet->priv->connection)
632 return;
633
634 g_dbus_connection_emit_signal (applet->priv->connection,
635 NULL((void*)0),
636 applet->priv->object_path,
637 CAFE_PANEL_APPLET_INTERFACE"org.cafe.panel.applet.Applet",
638 "RemoveFromPanel",
639 NULL((void*)0), &error);
640 if (error) {
641 g_printerr ("Failed to send signal RemoveFromPanel: %s\n",
642 error->message);
643 g_error_free (error);
644 }
645}
646
647static void
648cafe_panel_applet_menu_cmd_move (CtkAction *action,
649 CafePanelApplet *applet)
650{
651 GError *error = NULL((void*)0);
652
653 if (!applet->priv->connection)
654 return;
655
656 g_dbus_connection_emit_signal (applet->priv->connection,
657 NULL((void*)0),
658 applet->priv->object_path,
659 CAFE_PANEL_APPLET_INTERFACE"org.cafe.panel.applet.Applet",
660 "Move",
661 NULL((void*)0), &error);
662 if (error) {
663 g_printerr ("Failed to send signal RemoveFromPanel: %s\n",
664 error->message);
665 g_error_free (error);
666 }
667}
668
669static void
670cafe_panel_applet_menu_cmd_lock (CtkAction *action,
671 CafePanelApplet *applet)
672{
673 gboolean locked;
674
675 locked = ctk_toggle_action_get_active (CTK_TOGGLE_ACTION (action)((((CtkToggleAction*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((action)), ((ctk_toggle_action_get_type ()))))))
);
676 cafe_panel_applet_set_locked (applet, locked);
677}
678
679void
680cafe_panel_applet_setup_menu (CafePanelApplet *applet,
681 const gchar *xml,
682 CtkActionGroup *applet_action_group)
683{
684 gchar *new_xml;
685 GError *error = NULL((void*)0);
686
687 g_return_if_fail (PANEL_IS_APPLET (applet))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return; } }
while (0)
;
688 g_return_if_fail (xml != NULL)do { if ((xml != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "xml != NULL"); return
; } } while (0)
;
689
690 if (applet->priv->applet_action_group)
691 return;
692
693 applet->priv->applet_action_group = g_object_ref (applet_action_group)((__typeof__ (applet_action_group)) (g_object_ref) (applet_action_group
))
;
694 ctk_ui_manager_insert_action_group (applet->priv->ui_manager,
695 applet_action_group, 0);
696
697 new_xml = g_strdup_printf ("<ui><popup name=\"CafePanelAppletPopup\" action=\"AppletItems\">"
698 "<placeholder name=\"AppletItems\">%s\n</placeholder>\n"
699 "</popup></ui>\n", xml);
700 ctk_ui_manager_add_ui_from_string (applet->priv->ui_manager, new_xml, -1, &error);
701 g_free (new_xml);
702 ctk_ui_manager_ensure_update (applet->priv->ui_manager);
703 if (error) {
704 g_warning ("Error merging menus: %s\n", error->message);
705 g_error_free (error);
706 }
707}
708
709void
710cafe_panel_applet_setup_menu_from_file (CafePanelApplet *applet,
711 const gchar *filename,
712 CtkActionGroup *applet_action_group)
713{
714 gchar *xml = NULL((void*)0);
715 GError *error = NULL((void*)0);
716
717 if (g_file_get_contents (filename, &xml, NULL((void*)0), &error)) {
718 cafe_panel_applet_setup_menu (applet, xml, applet_action_group);
719 } else {
720 g_warning ("%s", error->message);
721 g_error_free (error);
722 }
723
724 g_free (xml);
725}
726
727/**
728 * cafe_panel_applet_setup_menu_from_resource:
729 * @applet: a #CafePanelApplet.
730 * @resource_path: a resource path
731 * @action_group: a #CtkActionGroup.
732 *
733 * Sets up the context menu of @applet. @filename is a resource path to a menu
734 * XML file, containing a #CtkUIManager UI definition that describes how to
735 * display the menu items. @action_group contains the various #CtkAction that
736 * are referenced in @xml.
737 *
738 * See also the <link linkend="getting-started.context-menu">Context
739 * Menu</link> section.
740 *
741 * Since: 1.20.1
742 **/
743void
744cafe_panel_applet_setup_menu_from_resource (CafePanelApplet *applet,
745 const gchar *resource_path,
746 CtkActionGroup *action_group)
747{
748 GBytes *bytes;
749 GError *error = NULL((void*)0);
750
751 bytes = g_resources_lookup_data (resource_path,
752 G_RESOURCE_LOOKUP_FLAGS_NONE,
753 &error);
754
755 if (bytes) {
756 cafe_panel_applet_setup_menu (applet,
757 g_bytes_get_data (bytes, NULL((void*)0)),
758 action_group);
759 } else {
760 g_warning ("%s", error->message);
761 g_error_free (error);
762 }
763
764 g_bytes_unref (bytes);
765}
766
767static void
768cafe_panel_applet_finalize (GObject *object)
769{
770 CafePanelApplet *applet = CAFE_PANEL_APPLET (object)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((cafe_panel_applet_get_type ()))))))
;
771
772 if (applet->priv->connection) {
773 if (applet->priv->object_id)
774 g_dbus_connection_unregister_object (applet->priv->connection,
775 applet->priv->object_id);
776 applet->priv->object_id = 0;
777 g_object_unref (applet->priv->connection);
778 applet->priv->connection = NULL((void*)0);
779 }
780
781 if (applet->priv->object_path) {
782 g_free (applet->priv->object_path);
783 applet->priv->object_path = NULL((void*)0);
784 }
785
786 cafe_panel_applet_set_preferences_path (applet, NULL((void*)0));
787
788 if (applet->priv->applet_action_group) {
789 g_object_unref (applet->priv->applet_action_group);
790 applet->priv->applet_action_group = NULL((void*)0);
791 }
792
793 if (applet->priv->panel_action_group) {
794 g_object_unref (applet->priv->panel_action_group);
795 applet->priv->panel_action_group = NULL((void*)0);
796 }
797
798 if (applet->priv->ui_manager) {
799 g_object_unref (applet->priv->ui_manager);
800 applet->priv->ui_manager = NULL((void*)0);
801 }
802
803 g_free (applet->priv->size_hints);
804 g_free (applet->priv->prefs_path);
805 g_free (applet->priv->background);
806 g_free (applet->priv->id);
807
808 /* closure is owned by the factory */
809 applet->priv->closure = NULL((void*)0);
810
811 G_OBJECT_CLASS (cafe_panel_applet_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cafe_panel_applet_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
812}
813
814static gboolean
815container_has_focusable_child (CtkContainer *container)
816{
817 CtkWidget *child;
818 GList *list;
819 GList *t;
820 gboolean retval = FALSE(0);
821
822 list = ctk_container_get_children (container);
823
824 for (t = list; t; t = t->next) {
825 child = CTK_WIDGET (t->data)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((t->data)), ((ctk_widget_get_type ()))))))
;
826 if (ctk_widget_get_can_focus (child)) {
827 retval = TRUE(!(0));
828 break;
829 } else if (CTK_IS_CONTAINER (child)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(child)); GType __t = ((ctk_container_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; }))))
) {
830 retval = container_has_focusable_child (CTK_CONTAINER (child)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_container_get_type ()))))))
);
831 if (retval)
832 break;
833 }
834 }
835 g_list_free (list);
836 return retval;
837}
838
839static void
840cafe_panel_applet_menu_popup (CafePanelApplet *applet,
841 CdkEvent *event)
842{
843 CtkWidget *menu;
844
845 menu = ctk_ui_manager_get_widget (applet->priv->ui_manager,
846 "/CafePanelAppletPopup");
847
848/* Set up theme and transparency support */
849 CtkWidget *toplevel = ctk_widget_get_toplevel (menu);
850/* Fix any failures of compiz/other wm's to communicate with ctk for transparency */
851 CdkScreen *screen = ctk_widget_get_screen(CTK_WIDGET(toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_widget_get_type ()))))))
);
852 CdkVisual *visual = cdk_screen_get_rgba_visual(screen);
853 ctk_widget_set_visual(CTK_WIDGET(toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_widget_get_type ()))))))
, visual);
854/* Set menu and it's toplevel window to follow panel theme */
855 CtkStyleContext *context;
856 context = ctk_widget_get_style_context (CTK_WIDGET(toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_widget_get_type ()))))))
);
857 ctk_style_context_add_class(context,"gnome-panel-menu-bar");
858 ctk_style_context_add_class(context,"cafe-panel-menu-bar");
859 CdkGravity widget_anchor = CDK_GRAVITY_NORTH_WEST;
860 CdkGravity menu_anchor = CDK_GRAVITY_NORTH_WEST;
861 switch (applet->priv->orient) {
862 case CAFE_PANEL_APPLET_ORIENT_UP:
863 menu_anchor = CDK_GRAVITY_SOUTH_WEST;
864 break;
865 case CAFE_PANEL_APPLET_ORIENT_DOWN:
866 widget_anchor = CDK_GRAVITY_SOUTH_WEST;
867 break;
868 case CAFE_PANEL_APPLET_ORIENT_LEFT:
869 menu_anchor = CDK_GRAVITY_NORTH_EAST;
870 break;
871 case CAFE_PANEL_APPLET_ORIENT_RIGHT:
872 widget_anchor = CDK_GRAVITY_NORTH_EAST;
873 break;
874 }
875 ctk_menu_popup_at_widget (CTK_MENU (menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_get_type ()))))))
,
876 CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
,
877 widget_anchor,
878 menu_anchor,
879 event);
880}
881
882static gboolean
883cafe_panel_applet_can_focus (CtkWidget *widget)
884{
885 /*
886 * A CafePanelApplet widget can focus if it has a tooltip or it does
887 * not have any focusable children.
888 */
889 if (ctk_widget_get_has_tooltip (widget))
890 return TRUE(!(0));
891
892 if (!PANEL_IS_APPLET (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((cafe_panel_applet_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; }))))
)
893 return FALSE(0);
894
895 return !container_has_focusable_child (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
);
896}
897
898/* Taken from libcafecomponentui/cafecomponent/cafecomponent-plug.c */
899static gboolean
900cafe_panel_applet_button_event (CafePanelApplet *applet,
901 CdkEventButton *event)
902{
903#ifdef HAVE_X111
904 CtkWidget *widget;
905 CdkWindow *window;
906 CdkWindow *socket_window;
907 XEvent xevent;
908 CdkDisplay *display;
909
910 if (!applet->priv->out_of_process)
911 return FALSE(0);
912
913 widget = applet->priv->plug;
914
915 if (!ctk_widget_is_toplevel (widget))
916 return FALSE(0);
917
918 window = ctk_widget_get_window (widget);
919 socket_window = ctk_plug_get_socket_window (CTK_PLUG (widget)((((CtkPlug*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_plug_get_type ()))))))
);
920
921 display = cdk_display_get_default ();
922
923 if (!CDK_IS_X11_DISPLAY (display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(display)); GType __t = ((cdk_x11_display_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; }))))
)
924 return FALSE(0);
925
926 if (event->type == CDK_BUTTON_PRESS) {
927 CdkSeat *seat;
928
929 xevent.xbutton.type = ButtonPress4;
930
931 seat = cdk_display_get_default_seat (display);
932
933 /* X does an automatic pointer grab on button press
934 * if we have both button press and release events
935 * selected.
936 * We don't want to hog the pointer on our parent.
937 */
938 cdk_seat_ungrab (seat);
939 } else {
940 xevent.xbutton.type = ButtonRelease5;
941 }
942
943 xevent.xbutton.display = CDK_WINDOW_XDISPLAY (window)((cdk_x11_display_get_xdisplay (cdk_window_get_display (window
))))
;
944 xevent.xbutton.window = CDK_WINDOW_XID (socket_window)(cdk_x11_window_get_xid (socket_window));
945 xevent.xbutton.root = CDK_WINDOW_XID (cdk_screen_get_root_window(cdk_x11_window_get_xid (cdk_screen_get_root_window (cdk_window_get_screen
(window))))
946 (cdk_window_get_screen (window)))(cdk_x11_window_get_xid (cdk_screen_get_root_window (cdk_window_get_screen
(window))))
;
947 /*
948 * FIXME: the following might cause
949 * big problems for non-CTK apps
950 */
951 xevent.xbutton.x = 0;
952 xevent.xbutton.y = 0;
953 xevent.xbutton.x_root = 0;
954 xevent.xbutton.y_root = 0;
955 xevent.xbutton.state = event->state;
956 xevent.xbutton.button = event->button;
957 xevent.xbutton.same_screen = TRUE(!(0)); /* FIXME ? */
958
959 cdk_x11_display_error_trap_push (display);
960
961 XSendEvent (CDK_WINDOW_XDISPLAY (window)((cdk_x11_display_get_xdisplay (cdk_window_get_display (window
))))
,
962 CDK_WINDOW_XID (socket_window)(cdk_x11_window_get_xid (socket_window)),
963 False0, NoEventMask0L, &xevent);
964
965 cdk_display_flush (display);
966 cdk_x11_display_error_trap_pop_ignored (display);
967
968 return TRUE(!(0));
969#else
970 return FALSE(0);
971#endif
972}
973
974static gboolean
975cafe_panel_applet_button_press (CtkWidget *widget,
976 CdkEventButton *event)
977{
978 CafePanelApplet *applet = CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
;
979
980 if (!container_has_focusable_child (CTK_CONTAINER (applet)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_container_get_type ()))))))
)) {
981 if (!ctk_widget_has_focus (widget)) {
982 ctk_widget_set_can_focus (widget, TRUE(!(0)));
983 ctk_widget_grab_focus (widget);
984 }
985 }
986
987 if (event->button == 3) {
988 cafe_panel_applet_menu_popup (applet, (CdkEvent *) event);
989
990 return TRUE(!(0));
991 }
992
993 return cafe_panel_applet_button_event (applet, event);
994}
995
996static gboolean
997cafe_panel_applet_button_release (CtkWidget *widget,
998 CdkEventButton *event)
999{
1000 CafePanelApplet *applet = CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
;
1001
1002 return cafe_panel_applet_button_event (applet, event);
1003}
1004
1005/*Open the applet context menu only on Menu key
1006 *Do not open it on Return or some applets won't work
1007 */
1008static gboolean
1009cafe_panel_applet_key_press_event (CtkWidget *widget,
1010 CdkEventKey *event)
1011{
1012 if (event->keyval == CDK_KEY_Menu0xff67) {
1013 cafe_panel_applet_menu_popup (CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
, (CdkEvent *) event);
1014 return TRUE(!(0));
1015 }
1016 else
1017 return FALSE(0);
1018}
1019
1020static void
1021cafe_panel_applet_get_preferred_width (CtkWidget *widget,
1022 int *minimum_width,
1023 int *natural_width)
1024{
1025 CTK_WIDGET_CLASS (cafe_panel_applet_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cafe_panel_applet_parent_class)), ((ctk_widget_get_type (
)))))))
->get_preferred_width (widget,
1026 minimum_width,
1027 natural_width);
1028
1029#if !CTK_CHECK_VERSION (3, 23, 0)((3) > (3) || ((3) == (3) && (25) > (23)) || ((
3) == (3) && (25) == (23) && (5) >= (0)))
1030 CafePanelApplet *applet = CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
;
1031 if (applet->priv->out_of_process) {
1032 /* Out-of-process applets end up scaled up doubly with CTK 3.22.
1033 * For these builds divide by the scale factor to ensure
1034 * they are back at their own intended size.
1035 */
1036 gint scale;
1037 scale = ctk_widget_get_scale_factor (widget);
1038 *minimum_width /= scale;
1039 *natural_width /= scale;
1040 }
1041#endif
1042}
1043
1044static void
1045cafe_panel_applet_get_preferred_height (CtkWidget *widget,
1046 int *minimum_height,
1047 int *natural_height)
1048{
1049 CTK_WIDGET_CLASS (cafe_panel_applet_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cafe_panel_applet_parent_class)), ((ctk_widget_get_type (
)))))))
->get_preferred_height (widget,
1050 minimum_height,
1051 natural_height);
1052
1053#if !CTK_CHECK_VERSION (3, 23, 0)((3) > (3) || ((3) == (3) && (25) > (23)) || ((
3) == (3) && (25) == (23) && (5) >= (0)))
1054 CafePanelApplet *applet = CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
;
1055 if (applet->priv->out_of_process) {
1056 gint scale;
1057 /* Out-of-process applets end up scaled up doubly with CTK 3.22.
1058 * For these builds divide by the scale factor to ensure
1059 * they are back at their own intended size.
1060 */
1061 scale = ctk_widget_get_scale_factor (widget);
1062 *minimum_height /= scale;
1063 *natural_height /= scale;
1064 }
1065#endif
1066}
1067
1068static CtkSizeRequestMode
1069cafe_panel_applet_get_request_mode (CtkWidget *widget)
1070{
1071 /*Do not use CTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH
1072 *or CTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT
1073 *to avoid problems with in-process applets
1074 *when the panel is not expanded
1075 *See https://github.com/cafe-desktop/cafe-panel/issues/797
1076 *and https://github.com/cafe-desktop/cafe-panel/issues/799
1077 *Out of process applets already use CTK_SIZE_REQUEST_CONSTANT_SIZE
1078 */
1079 return CTK_SIZE_REQUEST_CONSTANT_SIZE;
1080}
1081
1082static void
1083cafe_panel_applet_size_allocate (CtkWidget *widget,
1084 CtkAllocation *allocation)
1085{
1086 CtkAllocation child_allocation;
1087 CtkBin *bin;
1088 CtkWidget *child;
1089 int border_width;
1090 CafePanelApplet *applet;
1091
1092 if (!cafe_panel_applet_can_focus (widget)) {
1093 CTK_WIDGET_CLASS (cafe_panel_applet_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cafe_panel_applet_parent_class)), ((ctk_widget_get_type (
)))))))
->size_allocate (widget, allocation);
1094 } else {
1095
1096 border_width = ctk_container_get_border_width (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
);
1097
1098 ctk_widget_set_allocation (widget, allocation);
1099 bin = CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
;
1100
1101 child_allocation.x = 0;
1102 child_allocation.y = 0;
1103
1104 child_allocation.width = MAX (allocation->width - border_width * 2, 0)(((allocation->width - border_width * 2) > (0)) ? (allocation
->width - border_width * 2) : (0))
;
1105 child_allocation.height = MAX (allocation->height - border_width * 2, 0)(((allocation->height - border_width * 2) > (0)) ? (allocation
->height - border_width * 2) : (0))
;
1106
1107 if (ctk_widget_get_realized (widget))
1108 cdk_window_move_resize (ctk_widget_get_window (widget),
1109 allocation->x + border_width,
1110 allocation->y + border_width,
1111 child_allocation.width,
1112 child_allocation.height);
1113
1114 child = ctk_bin_get_child (bin);
1115 if (child)
1116 ctk_widget_size_allocate (child, &child_allocation);
1117 }
1118
1119 applet = CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
;
1120
1121 if (applet->priv->previous_height != allocation->height ||
1122 applet->priv->previous_width != allocation->width) {
1123 applet->priv->previous_height = allocation->height;
1124 applet->priv->previous_width = allocation->width;
1125
1126 cafe_panel_applet_handle_background (applet);
1127 }
1128}
1129
1130static gboolean cafe_panel_applet_draw(CtkWidget* widget, cairo_t* cr)
1131{
1132 CtkStyleContext *context;
1133 int border_width;
1134 gdouble x, y, width, height;
1135
1136 CTK_WIDGET_CLASS (cafe_panel_applet_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cafe_panel_applet_parent_class)), ((ctk_widget_get_type (
)))))))
->draw(widget, cr);
1137
1138 if (!ctk_widget_has_focus (widget))
1139 return FALSE(0);
1140
1141 width = ctk_widget_get_allocated_width (widget);
1142 height = ctk_widget_get_allocated_height (widget);
1143
1144 border_width = ctk_container_get_border_width (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
);
1145
1146 x = 0;
1147 y = 0;
1148
1149 width -= 2 * border_width;
1150 height -= 2 * border_width;
1151
1152 context = ctk_widget_get_style_context (widget);
1153 ctk_style_context_save (context);
1154
1155 cairo_save (cr);
1156 ctk_render_focus (context, cr, x, y, width, height);
1157 cairo_restore (cr);
1158
1159 ctk_style_context_restore (context);
1160
1161 return FALSE(0);
1162}
1163
1164static gboolean
1165cafe_panel_applet_focus (CtkWidget *widget,
1166 CtkDirectionType dir)
1167{
1168 gboolean ret;
1169 CtkWidget *previous_focus_child;
1170 CafePanelApplet *applet;
1171
1172 g_return_val_if_fail (PANEL_IS_APPLET (widget), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (widget)"); return ((0)
); } } while (0)
;
1173
1174 applet = CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
;
1175 if (applet->priv->moving_focus_out) {
1176 /*
1177 * Applet will retain focus if there is nothing else on the
1178 * panel to get focus
1179 */
1180 applet->priv->moving_focus_out = FALSE(0);
1181 return FALSE(0);
1182 }
1183
1184 previous_focus_child = ctk_container_get_focus_child (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
);
1185 if (!previous_focus_child && !ctk_widget_has_focus (widget)) {
1186 if (ctk_widget_get_has_tooltip (widget)) {
1187 ctk_widget_set_can_focus (widget, TRUE(!(0)));
1188 ctk_widget_grab_focus (widget);
1189 ctk_widget_set_can_focus (widget, FALSE(0));
1190 return TRUE(!(0));
1191 }
1192 }
1193 ret = CTK_WIDGET_CLASS (cafe_panel_applet_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cafe_panel_applet_parent_class)), ((ctk_widget_get_type (
)))))))
->focus (widget, dir);
1194
1195 if (!ret && !previous_focus_child) {
1196 if (!ctk_widget_has_focus (widget)) {
1197 /*
1198 * Applet does not have a widget which can focus so set
1199 * the focus on the applet unless it already had focus
1200 * because it had a tooltip.
1201 */
1202 ctk_widget_set_can_focus (widget, TRUE(!(0)));
1203 ctk_widget_grab_focus (widget);
1204 ctk_widget_set_can_focus (widget, FALSE(0));
1205 ret = TRUE(!(0));
1206 }
1207 }
1208
1209 return ret;
1210}
1211
1212static gboolean
1213cafe_panel_applet_parse_color (const gchar *color_str,
1214 CdkRGBA *color)
1215{
1216 g_assert (color_str && color)do { if (color_str && color) ; else g_assertion_message_expr
(((gchar*) 0), "cafe-panel-applet.c", 1216, ((const char*) (
__func__)), "color_str && color"); } while (0)
;
1217
1218 return cdk_rgba_parse (color, color_str);
1219}
1220
1221#ifdef HAVE_X111
1222static gboolean
1223cafe_panel_applet_parse_pixmap_str (const char *str,
1224 Window *xid,
1225 int *x,
1226 int *y)
1227{
1228 char **elements;
1229 char *tmp;
1230
1231 g_return_val_if_fail (str != NULL, FALSE)do { if ((str != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "str != NULL"); return
((0)); } } while (0)
;
1232 g_return_val_if_fail (xid != NULL, FALSE)do { if ((xid != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "xid != NULL"); return
((0)); } } while (0)
;
1233 g_return_val_if_fail (x != NULL, FALSE)do { if ((x != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "x != NULL"); return
((0)); } } while (0)
;
1234 g_return_val_if_fail (y != NULL, FALSE)do { if ((y != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "y != NULL"); return
((0)); } } while (0)
;
1235
1236 elements = g_strsplit (str, ",", -1);
1237
1238 if (!elements)
1239 return FALSE(0);
1240
1241 if (!elements [0] || !*elements [0] ||
1242 !elements [1] || !*elements [1] ||
1243 !elements [2] || !*elements [2])
1244 goto ERROR_AND_FREE;
1245
1246 *xid = strtol (elements [0], &tmp, 10);
1247 if (tmp == elements [0])
1248 goto ERROR_AND_FREE;
1249
1250 *x = strtol (elements [1], &tmp, 10);
1251 if (tmp == elements [1])
1252 goto ERROR_AND_FREE;
1253
1254 *y = strtol (elements [2], &tmp, 10);
1255 if (tmp == elements [2])
1256 goto ERROR_AND_FREE;
1257
1258 g_strfreev (elements);
1259 return TRUE(!(0));
1260
1261ERROR_AND_FREE:
1262 g_strfreev (elements);
1263 return FALSE(0);
1264}
1265
1266static cairo_surface_t *
1267cafe_panel_applet_create_foreign_surface_for_display (CdkDisplay *display,
1268 CdkVisual *visual,
1269 Window xid)
1270{
1271 Statusint result = 0;
1272 Window window;
1273 gint x, y;
1274 guint width, height, border, depth;
1275
1276 cdk_x11_display_error_trap_push (display);
1277 result = XGetGeometry (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), xid, &window,
1278 &x, &y, &width, &height, &border, &depth);
1279 cdk_x11_display_error_trap_pop_ignored (display);
1280
1281 if (result == 0)
1282 return NULL((void*)0);
1283
1284 return cairo_xlib_surface_create (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)),
1285 xid, cdk_x11_visual_get_xvisual (visual),
1286 width, height);
1287}
1288
1289static cairo_pattern_t *
1290cafe_panel_applet_get_pattern_from_pixmap (CafePanelApplet *applet,
1291 Window xid,
1292 int x,
1293 int y)
1294{
1295 cairo_surface_t *background;
1296 cairo_surface_t *surface;
1297 CdkWindow *window;
1298 int width;
1299 int height;
1300 CdkDisplay *display;
1301 cairo_t *cr;
1302 cairo_pattern_t *pattern;
1303
1304 g_return_val_if_fail (PANEL_IS_APPLET (applet), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return (((void
*)0)); } } while (0)
;
1305
1306 if (!ctk_widget_get_realized (CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
))
1307 return NULL((void*)0);
1308
1309 window = ctk_widget_get_window (CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
);
1310 display = cdk_window_get_display (window);
1311
1312 background = cafe_panel_applet_create_foreign_surface_for_display (display,
1313 cdk_window_get_visual (window),
1314 xid);
1315
1316 /* background can be NULL if the user changes the background very fast.
1317 * We'll get the next update, so it's not a big deal. */
1318 if (!background || cairo_surface_status (background) != CAIRO_STATUS_SUCCESS) {
1319 if (background)
1320 cairo_surface_destroy (background);
1321 return NULL((void*)0);
1322 }
1323
1324 width = cdk_window_get_width(window);
1325 height = cdk_window_get_height(window);
1326 surface = cdk_window_create_similar_surface (window,
1327 CAIRO_CONTENT_COLOR_ALPHA,
1328 width,
1329 height);
1330 cdk_x11_display_error_trap_push (display);
1331 cr = cairo_create (surface);
1332 cairo_set_source_surface (cr, background, -x, -y);
1333 cairo_rectangle (cr, 0, 0, width, height);
1334 cairo_fill (cr);
1335 cdk_x11_display_error_trap_pop_ignored (display);
1336
1337 cairo_surface_destroy (background);
1338 pattern = NULL((void*)0);
1339
1340 if (cairo_status (cr) == CAIRO_STATUS_SUCCESS) {
1341 pattern = cairo_pattern_create_for_surface (surface);
1342 }
1343
1344 cairo_destroy (cr);
1345 cairo_surface_destroy (surface);
1346
1347 return pattern;
1348}
1349#endif
1350
1351static CafePanelAppletBackgroundType
1352cafe_panel_applet_handle_background_string (CafePanelApplet *applet,
1353 CdkRGBA *color,
1354 cairo_pattern_t **pattern)
1355{
1356 CafePanelAppletBackgroundType retval;
1357 char **elements;
1358
1359 retval = PANEL_NO_BACKGROUND;
1360
1361 if (!ctk_widget_get_realized (CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
) || !applet->priv->background)
1362 return retval;
1363
1364 elements = g_strsplit (applet->priv->background, ":", -1);
1365
1366 if (elements [0] && !strcmp (elements [0], "none" )) {
1367 retval = PANEL_NO_BACKGROUND;
1368
1369 } else if (elements [0] && !strcmp (elements [0], "color")) {
1370 g_return_val_if_fail (color != NULL, PANEL_NO_BACKGROUND)do { if ((color != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "color != NULL");
return (PANEL_NO_BACKGROUND); } } while (0)
;
1371
1372 if (!elements [1] || !cafe_panel_applet_parse_color (elements [1], color)) {
1373
1374 g_warning ("Incomplete '%s' background type received", elements [0]);
1375 g_strfreev (elements);
1376 return PANEL_NO_BACKGROUND;
1377 }
1378
1379 retval = PANEL_COLOR_BACKGROUND;
1380
1381 } else if (elements [0] && !strcmp (elements [0], "pixmap")) {
1382#ifdef HAVE_X111
1383 if (CDK_IS_X11_DISPLAY (cdk_display_get_default ())(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(cdk_display_get_default ())); GType __t = ((cdk_x11_display_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; }))))
) {
1384 Window pixmap_id;
1385 int x, y;
1386
1387 g_return_val_if_fail (pattern != NULL, PANEL_NO_BACKGROUND)do { if ((pattern != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "pattern != NULL"
); return (PANEL_NO_BACKGROUND); } } while (0)
;
1388
1389 if (!cafe_panel_applet_parse_pixmap_str (elements [1], &pixmap_id, &x, &y)) {
1390 g_warning ("Incomplete '%s' background type received: %s",
1391 elements [0], elements [1]);
1392
1393 g_strfreev (elements);
1394 return PANEL_NO_BACKGROUND;
1395 }
1396
1397 *pattern = cafe_panel_applet_get_pattern_from_pixmap (applet, pixmap_id, x, y);
1398 if (!*pattern) {
1399 g_warning ("Failed to get pattern %s", elements [1]);
1400 g_strfreev (elements);
1401 return PANEL_NO_BACKGROUND;
1402 }
1403
1404 retval = PANEL_PIXMAP_BACKGROUND;
1405 } else
1406#endif
1407 { // not using X11
1408 g_warning("Received pixmap background type, which is only supported on X11");
1409 }
1410 } else
1411 g_warning ("Unknown background type received");
1412
1413 g_strfreev (elements);
1414
1415 return retval;
1416}
1417
1418CafePanelAppletBackgroundType
1419cafe_panel_applet_get_background (CafePanelApplet *applet,
1420 CdkRGBA *color,
1421 cairo_pattern_t **pattern)
1422{
1423 g_return_val_if_fail (PANEL_IS_APPLET (applet), PANEL_NO_BACKGROUND)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((applet)); GType __t = ((cafe_panel_applet_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__)), "PANEL_IS_APPLET (applet)"); return (PANEL_NO_BACKGROUND
); } } while (0)
;
1424
1425 /* initial sanity */
1426 if (pattern != NULL((void*)0))
1427 *pattern = NULL((void*)0);
1428 if (color != NULL((void*)0))
1429 memset (color, 0, sizeof (CdkRGBA));
1430
1431 return cafe_panel_applet_handle_background_string (applet, color, pattern);
1432}
1433
1434static void
1435cafe_panel_applet_set_background_string (CafePanelApplet *applet,
1436 const gchar *background)
1437{
1438 if (applet->priv->background == background)
1439 return;
1440
1441 if (g_strcmp0 (applet->priv->background, background) == 0)
1442 return;
1443
1444 if (applet->priv->background)
1445 g_free (applet->priv->background);
1446 applet->priv->background = background ? g_strdup (background)g_strdup_inline (background) : NULL((void*)0);
1447 cafe_panel_applet_handle_background (applet);
1448
1449 g_object_notify (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
, "background");
1450}
1451
1452static void
1453cafe_panel_applet_handle_background (CafePanelApplet *applet)
1454{
1455 CafePanelAppletBackgroundType type;
1456
1457 CdkRGBA color;
1458 cairo_pattern_t *pattern;
1459
1460 type = cafe_panel_applet_get_background (applet, &color, &pattern);
1461
1462 switch (type) {
1463 case PANEL_NO_BACKGROUND:
1464 g_signal_emit (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
,
1465 cafe_panel_applet_signals [CHANGE_BACKGROUND],
1466 0, PANEL_NO_BACKGROUND, NULL((void*)0), NULL((void*)0));
1467 break;
1468 case PANEL_COLOR_BACKGROUND:
1469 g_signal_emit (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
,
1470 cafe_panel_applet_signals [CHANGE_BACKGROUND],
1471 0, PANEL_COLOR_BACKGROUND, &color, NULL((void*)0));
1472 break;
1473 case PANEL_PIXMAP_BACKGROUND:
1474 g_signal_emit (G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
,
1475 cafe_panel_applet_signals [CHANGE_BACKGROUND],
1476
1477 0, PANEL_PIXMAP_BACKGROUND, NULL((void*)0), pattern);
1478
1479
1480 cairo_pattern_destroy (pattern);
1481
1482 break;
1483 default:
1484 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "cafe-panel-applet.c"
, 1484, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1485 break;
1486 }
1487}
1488
1489static void
1490cafe_panel_applet_realize (CtkWidget *widget)
1491{
1492 CTK_WIDGET_CLASS (cafe_panel_applet_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cafe_panel_applet_parent_class)), ((ctk_widget_get_type (
)))))))
->realize (widget);
1493
1494 if (CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
->priv->background)
1495 cafe_panel_applet_handle_background (CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
);
1496}
1497
1498static void
1499cafe_panel_applet_move_focus_out_of_applet (CafePanelApplet *applet,
1500 CtkDirectionType dir)
1501{
1502 CtkWidget *toplevel;
1503
1504 applet->priv->moving_focus_out = TRUE(!(0));
1505 toplevel = ctk_widget_get_toplevel (CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
);
1506 g_return_if_fail (toplevel)do { if ((toplevel)) { } else { g_return_if_fail_warning (((gchar
*) 0), ((const char*) (__func__)), "toplevel"); return; } } while
(0)
;
1507
1508 ctk_widget_child_focus (toplevel, dir);
1509 applet->priv->moving_focus_out = FALSE(0);
1510}
1511
1512static void
1513cafe_panel_applet_change_background(CafePanelApplet *applet,
1514 CafePanelAppletBackgroundType type,
1515 CdkRGBA* color,
1516 cairo_pattern_t *pattern)
1517{
1518 CtkStyleContext* context;
1519 CdkWindow* window;
1520
1521 if (applet->priv->out_of_process)
1522 window = ctk_widget_get_window (CTK_WIDGET (applet->priv->plug)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_widget_get_type ()))))
))
);
1523 else
1524 window = ctk_widget_get_window (CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
);
1525
1526 ctk_widget_set_app_paintable(CTK_WIDGET(applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
,TRUE(!(0)));
1527
1528 if (applet->priv->out_of_process)
1529 _cafe_panel_applet_apply_css(CTK_WIDGET(applet->priv->plug)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_widget_get_type ()))))
))
,type);
1530
1531 switch (type) {
1532 case PANEL_NO_BACKGROUND:
1533 if (applet->priv->out_of_process){
1534 pattern = cairo_pattern_create_rgba (0,0,0,0); /* Using NULL here breaks transparent */
1535 cdk_window_set_background_pattern(window,pattern); /* backgrounds set by CTK theme */
1536 }
1537 break;
1538 case PANEL_COLOR_BACKGROUND:
1539 if (applet->priv->out_of_process){
1540 cdk_window_set_background_rgba(window,color);
1541 ctk_widget_queue_draw (applet->priv->plug); /*change the bg right away always */
1542 }
1543 break;
1544 case PANEL_PIXMAP_BACKGROUND:
1545 if (applet->priv->out_of_process){
1546 cdk_window_set_background_pattern(window,pattern);
1547 ctk_widget_queue_draw (applet->priv->plug); /*change the bg right away always */
1548 }
1549 break;
1550 default:
1551 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "cafe-panel-applet.c"
, 1551, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1552 break;
1553 }
1554
1555 if (applet->priv->out_of_process){
1556 context = ctk_widget_get_style_context (CTK_WIDGET(applet->priv->plug)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_widget_get_type ()))))
))
);
1557 if (applet->priv->orient == CAFE_PANEL_APPLET_ORIENT_UP ||
1558 applet->priv->orient == CAFE_PANEL_APPLET_ORIENT_DOWN){
1559 ctk_style_context_add_class(context,"horizontal");
1560 }
1561 else {
1562 ctk_style_context_add_class(context,"vertical");
1563 }
1564 }
1565}
1566
1567static void
1568cafe_panel_applet_get_property (GObject *object,
1569 guint prop_id,
1570 GValue *value,
1571 GParamSpec *pspec)
1572{
1573 CafePanelApplet *applet = CAFE_PANEL_APPLET (object)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((cafe_panel_applet_get_type ()))))))
;
1574
1575 switch (prop_id) {
1576 case PROP_OUT_OF_PROCESS:
1577 g_value_set_boolean (value, applet->priv->out_of_process);
1578 break;
1579 case PROP_ID:
1580 g_value_set_string (value, applet->priv->id);
1581 break;
1582 case PROP_CLOSURE:
1583 g_value_set_pointer (value, applet->priv->closure);
1584 break;
1585 case PROP_CONNECTION:
1586 g_value_set_object (value, applet->priv->connection);
1587 break;
1588 case PROP_PREFS_PATH:
1589 g_value_set_string (value, applet->priv->prefs_path);
1590 break;
1591 case PROP_ORIENT:
1592 g_value_set_uint (value, applet->priv->orient);
1593 break;
1594 case PROP_SIZE:
1595 g_value_set_uint (value, applet->priv->size);
1596 break;
1597 case PROP_BACKGROUND:
1598 g_value_set_string (value, applet->priv->background);
1599 break;
1600 case PROP_FLAGS:
1601 g_value_set_uint (value, applet->priv->flags);
1602 break;
1603 case PROP_SIZE_HINTS: {
1604 GVariant **children;
1605 GVariant *variant;
1606 gint i;
1607
1608 children = g_new (GVariant *, applet->priv->size_hints_len)((GVariant * *) g_malloc_n ((applet->priv->size_hints_len
), sizeof (GVariant *)))
;
1609 for (i = 0; i < applet->priv->size_hints_len; i++)
1610 children[i] = g_variant_new_int32 (applet->priv->size_hints[i]);
1611 variant = g_variant_new_array (G_VARIANT_TYPE_INT32((const GVariantType *) "i"),
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
1612 children, applet->priv->size_hints_len);
1613 g_free (children);
1614 g_value_set_pointer (value, variant);
1615 }
1616 break;
1617 case PROP_LOCKED:
1618 g_value_set_boolean (value, applet->priv->locked);
1619 break;
1620 case PROP_LOCKED_DOWN:
1621 g_value_set_boolean (value, applet->priv->locked_down);
1622 break;
1623 default:
1624 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "cafe-panel-applet.c", 1624, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1625 }
1626}
1627
1628static void
1629cafe_panel_applet_set_property (GObject *object,
1630 guint prop_id,
1631 const GValue *value,
1632 GParamSpec *pspec)
1633{
1634 CafePanelApplet *applet = CAFE_PANEL_APPLET (object)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((cafe_panel_applet_get_type ()))))))
;
1635
1636 switch (prop_id) {
1637 case PROP_OUT_OF_PROCESS:
1638 applet->priv->out_of_process = g_value_get_boolean (value);
1639 break;
1640 case PROP_ID:
1641 applet->priv->id = g_value_dup_string (value);
1642 break;
1643 case PROP_CLOSURE:
1644 applet->priv->closure = g_value_get_pointer (value);
1645 g_closure_set_marshal (applet->priv->closure,
1646 cafe_panel_applet_marshal_BOOLEAN__STRING);
1647 break;
1648 case PROP_CONNECTION:
1649 applet->priv->connection = g_value_dup_object (value);
1650 break;
1651 case PROP_PREFS_PATH:
1652 cafe_panel_applet_set_preferences_path (applet, g_value_get_string (value));
1653 break;
1654 case PROP_ORIENT:
1655 cafe_panel_applet_set_orient (applet, g_value_get_uint (value));
1656 break;
1657 case PROP_SIZE:
1658 cafe_panel_applet_set_size (applet, g_value_get_uint (value));
1659 break;
1660 case PROP_BACKGROUND:
1661 cafe_panel_applet_set_background_string (applet, g_value_get_string (value));
1662 break;
1663 case PROP_FLAGS:
1664 cafe_panel_applet_set_flags (applet, g_value_get_uint (value));
1665 break;
1666 case PROP_SIZE_HINTS: {
1667 const int *size_hints;
1668 gsize n_elements;
1669
1670 size_hints = g_variant_get_fixed_array (g_value_get_pointer (value),
1671 &n_elements, sizeof (gint32));
1672 cafe_panel_applet_set_size_hints (applet, size_hints, n_elements, 0);
1673 }
1674 break;
1675 case PROP_LOCKED:
1676 cafe_panel_applet_set_locked (applet, g_value_get_boolean (value));
1677 break;
1678 case PROP_LOCKED_DOWN:
1679 cafe_panel_applet_set_locked_down (applet, g_value_get_boolean (value));
1680 break;
1681 default:
1682 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "cafe-panel-applet.c", 1682, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1683 }
1684}
1685
1686static void
1687add_tab_bindings (CtkBindingSet *binding_set,
1688 CdkModifierType modifiers,
1689 CtkDirectionType direction)
1690{
1691 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Tab0xff09, modifiers,
1692 "move_focus_out_of_applet", 1,
1693 CTK_TYPE_DIRECTION_TYPE(ctk_direction_type_get_type ()), direction);
1694 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Tab0xff89, modifiers,
1695 "move_focus_out_of_applet", 1,
1696 CTK_TYPE_DIRECTION_TYPE(ctk_direction_type_get_type ()), direction);
1697}
1698
1699static void
1700cafe_panel_applet_setup (CafePanelApplet *applet)
1701{
1702 GValue value = {0, };
1703 GArray *params;
1704 gint i;
1705 gboolean ret;
1706
1707 g_assert (applet->priv->id != NULL &&do { if (applet->priv->id != ((void*)0) && applet
->priv->closure != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "cafe-panel-applet.c", 1708, ((const char*) (
__func__)), "applet->priv->id != NULL && applet->priv->closure != NULL"
); } while (0)
1708 applet->priv->closure != NULL)do { if (applet->priv->id != ((void*)0) && applet
->priv->closure != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "cafe-panel-applet.c", 1708, ((const char*) (
__func__)), "applet->priv->id != NULL && applet->priv->closure != NULL"
); } while (0)
;
1709
1710 params = g_array_sized_new (FALSE(0), TRUE(!(0)), sizeof (GValue), 2);
1711 value.g_type = 0;
1712 g_value_init (&value, G_TYPE_OBJECT((GType) ((20) << (2))));
1713 g_value_set_object (&value, G_OBJECT (applet)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (((GType) ((20) << (2))))))))
);
1714 g_array_append_val (params, value)g_array_append_vals (params, &(value), 1);
1715
1716 value.g_type = 0;
1717 g_value_init (&value, G_TYPE_STRING((GType) ((16) << (2))));
1718 g_value_set_string (&value, applet->priv->id);
1719 g_array_append_val (params, value)g_array_append_vals (params, &(value), 1);
1720
1721 value.g_type = 0;
1722 g_value_init (&value, G_TYPE_BOOLEAN((GType) ((5) << (2))));
1723
1724 g_closure_invoke (applet->priv->closure,
1725 &value, params->len,
1726 (GValue *) params->data,
1727 NULL((void*)0));
1728
1729 for (i = 0; i < params->len; i++)
1730 g_value_unset (&g_array_index (params, GValue, i)(((GValue*) (void *) (params)->data) [(i)]));
1731 g_array_free (params, TRUE(!(0)));
1732
1733 ret = g_value_get_boolean (&value);
1734 g_value_unset (&value);
1735
1736 if (!ret) { /* FIXME */
1737 g_warning ("need to free the control here");
1738
1739 return;
1740 }
1741}
1742
1743void _cafe_panel_applet_apply_css(CtkWidget* widget, CafePanelAppletBackgroundType type)
1744{
1745 CtkStyleContext* context;
1746
1747 context = ctk_widget_get_style_context (widget);
1748
1749 switch (type) {
1750 case PANEL_NO_BACKGROUND:
1751 ctk_style_context_remove_class (context, "cafe-custom-panel-background");
1752 break;
1753 case PANEL_COLOR_BACKGROUND:
1754 case PANEL_PIXMAP_BACKGROUND:
1755 ctk_style_context_add_class (context, "cafe-custom-panel-background");
1756 break;
1757 default:
1758 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "cafe-panel-applet.c"
, 1758, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1759 break;
1760 }
1761}
1762
1763#ifdef HAVE_X111
1764static void _cafe_panel_applet_prepare_css (CtkStyleContext *context)
1765{
1766 CtkCssProvider *provider;
1767
1768 g_return_if_fail (CDK_IS_X11_DISPLAY (cdk_display_get_default ()))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((cdk_display_get_default ())); GType __t = ((cdk_x11_display_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__)), "CDK_IS_X11_DISPLAY (cdk_display_get_default ())"
); return; } } while (0)
;
1769 provider = ctk_css_provider_new ();
1770 ctk_css_provider_load_from_data (provider,
1771 "#PanelPlug {\n"
1772 " background-repeat: no-repeat;\n" /*disable in ctk theme features */
1773 " background-size: cover; " /*that don't work on panel-toplevel */
1774 " }\n"
1775 ".cafe-custom-panel-background{\n" /*prepare CSS for user set theme */
1776 " background-color: rgba (0, 0, 0, 0);\n"
1777 " background-image: none;\n"
1778 "}",
1779 -1, NULL((void*)0));
1780
1781 ctk_style_context_add_provider (context,
1782 CTK_STYLE_PROVIDER (provider)((((CtkStyleProvider*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((provider)), ((ctk_style_provider_get_type (
)))))))
,
1783 CTK_STYLE_PROVIDER_PRIORITY_APPLICATION600);
1784 g_object_unref (provider);
1785}
1786#endif // HAVE_X11
1787
1788static void
1789cafe_panel_applet_init (CafePanelApplet *applet)
1790{
1791 applet->priv = cafe_panel_applet_get_instance_private (applet);
1792
1793 applet->priv->flags = CAFE_PANEL_APPLET_FLAGS_NONE;
1794 applet->priv->orient = CAFE_PANEL_APPLET_ORIENT_UP;
1795 applet->priv->size = 24;
1796
1797 applet->priv->panel_action_group = ctk_action_group_new ("PanelActions");
1798 ctk_action_group_set_translation_domain (applet->priv->panel_action_group, GETTEXT_PACKAGE"cafe-panel");
1799 ctk_action_group_add_actions (applet->priv->panel_action_group,
1800 menu_entries,
1801 G_N_ELEMENTS (menu_entries)(sizeof (menu_entries) / sizeof ((menu_entries)[0])),
1802 applet);
1803 ctk_action_group_add_toggle_actions (applet->priv->panel_action_group,
1804 menu_toggle_entries,
1805 G_N_ELEMENTS (menu_toggle_entries)(sizeof (menu_toggle_entries) / sizeof ((menu_toggle_entries)
[0]))
,
1806 applet);
1807
1808 applet->priv->ui_manager = ctk_ui_manager_new ();
1809 ctk_ui_manager_insert_action_group (applet->priv->ui_manager,
1810 applet->priv->panel_action_group, 1);
1811 ctk_ui_manager_add_ui_from_string (applet->priv->ui_manager,
1812 panel_menu_ui, -1, NULL((void*)0));
1813
1814 ctk_widget_set_events (CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
,
1815 CDK_BUTTON_PRESS_MASK |
1816 CDK_BUTTON_RELEASE_MASK);
1817}
1818
1819static GObject *
1820cafe_panel_applet_constructor (GType type,
1821 guint n_construct_properties,
1822 GObjectConstructParam *construct_properties)
1823{
1824 GObject *object;
1825 CafePanelApplet *applet;
1826
1827 object = G_OBJECT_CLASS (cafe_panel_applet_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cafe_panel_applet_parent_class)), (((GType) ((20) <<
(2))))))))
->constructor (type,
1828 n_construct_properties,
1829 construct_properties);
1830 applet = CAFE_PANEL_APPLET (object)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((cafe_panel_applet_get_type ()))))))
;
1831
1832 if (!applet->priv->out_of_process)
1833 return object;
1834
1835#ifdef HAVE_X111
1836 if (CDK_IS_X11_DISPLAY (cdk_display_get_default ())(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(cdk_display_get_default ())); GType __t = ((cdk_x11_display_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; }))))
)
1837 {
1838 applet->priv->plug = ctk_plug_new (0);
1839
1840 CdkScreen *screen = ctk_widget_get_screen (CTK_WIDGET (applet->priv->plug)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_widget_get_type ()))))
))
);
1841 CdkVisual *visual = cdk_screen_get_rgba_visual (screen);
1842 ctk_widget_set_visual (CTK_WIDGET (applet->priv->plug)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_widget_get_type ()))))
))
, visual);
1843 CtkStyleContext *context;
1844 context = ctk_widget_get_style_context (CTK_WIDGET(applet->priv->plug)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_widget_get_type ()))))
))
);
1845 ctk_style_context_add_class (context,"gnome-panel-menu-bar");
1846 ctk_style_context_add_class (context,"cafe-panel-menu-bar");
1847 ctk_widget_set_name (CTK_WIDGET (applet->priv->plug)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_widget_get_type ()))))
))
, "PanelPlug");
1848 _cafe_panel_applet_prepare_css (context);
1849
1850 g_signal_connect_swapped (G_OBJECT (applet->priv->plug), "embedded",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((applet->priv->plug)), (((GType) ((
20) << (2))))))))), ("embedded"), (((GCallback) (cafe_panel_applet_setup
))), (applet), ((void*)0), G_CONNECT_SWAPPED)
1851 G_CALLBACK (cafe_panel_applet_setup),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((applet->priv->plug)), (((GType) ((
20) << (2))))))))), ("embedded"), (((GCallback) (cafe_panel_applet_setup
))), (applet), ((void*)0), G_CONNECT_SWAPPED)
1852 applet)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((applet->priv->plug)), (((GType) ((
20) << (2))))))))), ("embedded"), (((GCallback) (cafe_panel_applet_setup
))), (applet), ((void*)0), G_CONNECT_SWAPPED)
;
1853
1854 ctk_container_add (CTK_CONTAINER (applet->priv->plug)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_container_get_type ())
)))))
, CTK_WIDGET (applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
);
1855 } else
1856#endif
1857 { // not using X11
1858 g_warning ("Requested construction of an out-of-process applet, which is only possible on X11");
1859 }
1860
1861 return object;
1862}
1863
1864static void
1865cafe_panel_applet_constructed (GObject* object)
1866{
1867 CafePanelApplet* applet = CAFE_PANEL_APPLET(object)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((cafe_panel_applet_get_type ()))))))
;
1868
1869 /* Rename the class to have compatibility with all CTK2 themes
1870 * https://github.com/perberos/Cafe-Desktop-Environment/issues/27
1871 */
1872 ctk_widget_set_name(CTK_WIDGET(applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
, "PanelApplet");
1873
1874 cafe_panel_applet_register_object (applet);
1875}
1876
1877static void
1878cafe_panel_applet_class_init (CafePanelAppletClass *klass)
1879{
1880 GObjectClass *gobject_class = (GObjectClass *) klass;
1881 CtkWidgetClass *widget_class = (CtkWidgetClass *) klass;
1882 CtkBindingSet *binding_set;
1883
1884 gobject_class->get_property = cafe_panel_applet_get_property;
1885 gobject_class->set_property = cafe_panel_applet_set_property;
1886 gobject_class->constructor = cafe_panel_applet_constructor;
1887 gobject_class->constructed = cafe_panel_applet_constructed;
1888 klass->move_focus_out_of_applet = cafe_panel_applet_move_focus_out_of_applet;
1889 klass->change_background = cafe_panel_applet_change_background;
1890 widget_class->button_press_event = cafe_panel_applet_button_press;
1891 widget_class->button_release_event = cafe_panel_applet_button_release;
1892 widget_class->get_request_mode = cafe_panel_applet_get_request_mode;
1893 widget_class->get_preferred_width = cafe_panel_applet_get_preferred_width;
1894 widget_class->get_preferred_height = cafe_panel_applet_get_preferred_height;
1895 widget_class->draw = cafe_panel_applet_draw;
1896 widget_class->size_allocate = cafe_panel_applet_size_allocate;
1897 widget_class->focus = cafe_panel_applet_focus;
1898 widget_class->realize = cafe_panel_applet_realize;
1899 widget_class->key_press_event = cafe_panel_applet_key_press_event;
1900
1901
1902 gobject_class->finalize = cafe_panel_applet_finalize;
1903
1904 g_object_class_install_property (gobject_class,
1905 PROP_OUT_OF_PROCESS,
1906 g_param_spec_boolean ("out-of-process",
1907 "out-of-process",
1908 "out-of-process",
1909 TRUE(!(0)),
1910 G_PARAM_CONSTRUCT_ONLY |
1911 G_PARAM_READWRITE));
1912 g_object_class_install_property (gobject_class,
1913 PROP_ID,
1914 g_param_spec_string ("id",
1915 "Id",
1916 "The Applet identifier",
1917 NULL((void*)0),
1918 G_PARAM_CONSTRUCT_ONLY |
1919 G_PARAM_READWRITE));
1920 g_object_class_install_property (gobject_class,
1921 PROP_CLOSURE,
1922 g_param_spec_pointer ("closure",
1923 "GClosure",
1924 "The Applet closure",
1925 G_PARAM_CONSTRUCT_ONLY |
1926 G_PARAM_READWRITE));
1927 g_object_class_install_property (gobject_class,
1928 PROP_CONNECTION,
1929 g_param_spec_object ("connection",
1930 "Connection",
1931 "The DBus Connection",
1932 G_TYPE_DBUS_CONNECTION(g_dbus_connection_get_type ()),
1933 G_PARAM_CONSTRUCT_ONLY |
1934 G_PARAM_READWRITE));
1935 g_object_class_install_property (gobject_class,
1936 PROP_PREFS_PATH,
1937 g_param_spec_string ("prefs-path",
1938 "PrefsPath",
1939 "GSettings Preferences Path",
1940 NULL((void*)0),
1941 G_PARAM_READWRITE));
1942 g_object_class_install_property (gobject_class,
1943 PROP_ORIENT,
1944 g_param_spec_uint ("orient",
1945 "Orient",
1946 "Panel Applet Orientation",
1947 CAFE_PANEL_APPLET_ORIENT_FIRSTCAFE_PANEL_APPLET_ORIENT_UP,
1948 CAFE_PANEL_APPLET_ORIENT_LASTCAFE_PANEL_APPLET_ORIENT_RIGHT,
1949 CAFE_PANEL_APPLET_ORIENT_UP,
1950 G_PARAM_READWRITE));
1951 g_object_class_install_property (gobject_class,
1952 PROP_SIZE,
1953 g_param_spec_uint ("size",
1954 "Size",
1955 "Panel Applet Size",
1956 0, G_MAXUINT(2147483647 *2U +1U), 0,
1957 G_PARAM_READWRITE));
1958 g_object_class_install_property (gobject_class,
1959 PROP_BACKGROUND,
1960 g_param_spec_string ("background",
1961 "Background",
1962 "Panel Applet Background",
1963 NULL((void*)0),
1964 G_PARAM_READWRITE));
1965 g_object_class_install_property (gobject_class,
1966 PROP_FLAGS,
1967 g_param_spec_uint ("flags",
1968 "Flags",
1969 "Panel Applet flags",
1970 CAFE_PANEL_APPLET_FLAGS_NONE,
1971 CAFE_PANEL_APPLET_FLAGS_ALL(CAFE_PANEL_APPLET_EXPAND_MAJOR|CAFE_PANEL_APPLET_EXPAND_MINOR
|CAFE_PANEL_APPLET_HAS_HANDLE)
,
1972 CAFE_PANEL_APPLET_FLAGS_NONE,
1973 G_PARAM_READWRITE));
1974 g_object_class_install_property (gobject_class,
1975 PROP_SIZE_HINTS,
1976 /* FIXME: value_array? */
1977 g_param_spec_pointer ("size-hints",
1978 "SizeHints",
1979 "Panel Applet Size Hints",
1980 G_PARAM_READWRITE));
1981 g_object_class_install_property (gobject_class,
1982 PROP_LOCKED,
1983 g_param_spec_boolean ("locked",
1984 "Locked",
1985 "Whether Panel Applet is locked",
1986 FALSE(0),
1987 G_PARAM_READWRITE));
1988 g_object_class_install_property (gobject_class,
1989 PROP_LOCKED_DOWN,
1990 g_param_spec_boolean ("locked-down",
1991 "LockedDown",
1992 "Whether Panel Applet is locked down",
1993 FALSE(0),
1994 G_PARAM_READWRITE));
1995
1996 cafe_panel_applet_signals [CHANGE_ORIENT] =
1997 g_signal_new ("change_orient",
1998 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
1999 G_SIGNAL_RUN_LAST,
2000 G_STRUCT_OFFSET (CafePanelAppletClass, change_orient)((glong) __builtin_offsetof(CafePanelAppletClass, change_orient
))
,
2001 NULL((void*)0),
2002 NULL((void*)0),
2003 cafe_panel_applet_marshal_VOID__UINTg_cclosure_marshal_VOID__UINT,
2004 G_TYPE_NONE((GType) ((1) << (2))),
2005 1,
2006 G_TYPE_UINT((GType) ((7) << (2))));
2007
2008 cafe_panel_applet_signals [CHANGE_SIZE] =
2009 g_signal_new ("change_size",
2010 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
2011 G_SIGNAL_RUN_LAST,
2012 G_STRUCT_OFFSET (CafePanelAppletClass, change_size)((glong) __builtin_offsetof(CafePanelAppletClass, change_size
))
,
2013 NULL((void*)0),
2014 NULL((void*)0),
2015 cafe_panel_applet_marshal_VOID__INTg_cclosure_marshal_VOID__INT,
2016 G_TYPE_NONE((GType) ((1) << (2))),
2017 1,
2018 G_TYPE_INT((GType) ((6) << (2))));
2019
2020 cafe_panel_applet_signals [CHANGE_BACKGROUND] =
2021 g_signal_new ("change_background",
2022 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
2023 G_SIGNAL_RUN_LAST,
2024 G_STRUCT_OFFSET (CafePanelAppletClass, change_background)((glong) __builtin_offsetof(CafePanelAppletClass, change_background
))
,
2025 NULL((void*)0),
2026 NULL((void*)0),
2027 cafe_panel_applet_marshal_VOID__ENUM_BOXED_OBJECT,
2028 G_TYPE_NONE((GType) ((1) << (2))),
2029 3,
2030 PANEL_TYPE_CAFE_PANEL_APPLET_BACKGROUND_TYPEcafe_panel_applet_background_type_get_type(),
2031 CDK_TYPE_RGBA(cdk_rgba_get_type ()),
2032 CAIRO_GOBJECT_TYPE_PATTERNcairo_gobject_pattern_get_type ());
2033
2034 cafe_panel_applet_signals [MOVE_FOCUS_OUT_OF_APPLET] =
2035 g_signal_new ("move_focus_out_of_applet",
2036 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
2037 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2038 G_STRUCT_OFFSET (CafePanelAppletClass, move_focus_out_of_applet)((glong) __builtin_offsetof(CafePanelAppletClass, move_focus_out_of_applet
))
,
2039 NULL((void*)0),
2040 NULL((void*)0),
2041 cafe_panel_applet_marshal_VOID__ENUMg_cclosure_marshal_VOID__ENUM,
2042 G_TYPE_NONE((GType) ((1) << (2))),
2043 1,
2044 CTK_TYPE_DIRECTION_TYPE(ctk_direction_type_get_type ()));
2045
2046 binding_set = ctk_binding_set_by_class (gobject_class);
2047 add_tab_bindings (binding_set, 0, CTK_DIR_TAB_FORWARD);
2048 add_tab_bindings (binding_set, CDK_SHIFT_MASK, CTK_DIR_TAB_BACKWARD);
2049 add_tab_bindings (binding_set, CDK_CONTROL_MASK, CTK_DIR_TAB_FORWARD);
2050 add_tab_bindings (binding_set, CDK_CONTROL_MASK | CDK_SHIFT_MASK, CTK_DIR_TAB_BACKWARD);
2051
2052 ctk_widget_class_set_css_name (widget_class, "PanelApplet");
2053}
2054
2055CtkWidget* cafe_panel_applet_new(void)
2056{
2057 CafePanelApplet* applet = g_object_new(PANEL_TYPE_APPLET(cafe_panel_applet_get_type ()), NULL((void*)0));
2058
2059 return CTK_WIDGET(applet)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), ((ctk_widget_get_type ()))))))
;
2060}
2061
2062static CdkEvent *
2063button_press_event_new (CafePanelApplet *applet,
2064 guint button,
2065 guint time)
2066{
2067 CdkDisplay *display;
2068 CdkSeat *seat;
2069 CdkDevice *device;
2070 CdkEvent *event;
2071
2072 display = cdk_display_get_default ();
2073 seat = cdk_display_get_default_seat (display);
2074 device = cdk_seat_get_pointer (seat);
2075
2076 event = cdk_event_new (CDK_BUTTON_PRESS);
2077
2078 event->button.time = time;
2079 event->button.button = button;
2080
2081 cdk_event_set_device (event, device);
2082
2083 return event;
2084}
2085
2086static void
2087method_call_cb (GDBusConnection *connection,
2088 const gchar *sender,
2089 const gchar *object_path,
2090 const gchar *interface_name,
2091 const gchar *method_name,
2092 GVariant *parameters,
2093 GDBusMethodInvocation *invocation,
2094 gpointer user_data)
2095{
2096 CafePanelApplet *applet = CAFE_PANEL_APPLET (user_data)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((cafe_panel_applet_get_type ()))))))
;
2097 CdkEvent *event;
2098
2099 if (g_strcmp0 (method_name, "PopupMenu") == 0) {
2100 guint button;
2101 guint time;
2102
2103 g_variant_get (parameters, "(uu)", &button, &time);
2104
2105 event = button_press_event_new (applet, button, time);
2106 cafe_panel_applet_menu_popup (applet, event);
2107 cdk_event_free (event);
2108
2109 g_dbus_method_invocation_return_value (invocation, NULL((void*)0));
2110 }
2111}
2112
2113static GVariant *
2114get_property_cb (GDBusConnection *connection,
2115 const gchar *sender,
2116 const gchar *object_path,
2117 const gchar *interface_name,
2118 const gchar *property_name,
2119 GError **error,
2120 gpointer user_data)
2121{
2122 CafePanelApplet *applet = CAFE_PANEL_APPLET (user_data)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((cafe_panel_applet_get_type ()))))))
;
2123 GVariant *retval = NULL((void*)0);
2124
2125 if (g_strcmp0 (property_name, "PrefsPath") == 0) {
2126 retval = g_variant_new_string (applet->priv->prefs_path ?
2127 applet->priv->prefs_path : "");
2128 } else if (g_strcmp0 (property_name, "Orient") == 0) {
2129 retval = g_variant_new_uint32 (applet->priv->orient);
2130 } else if (g_strcmp0 (property_name, "Size") == 0) {
2131 retval = g_variant_new_uint32 (applet->priv->size);
2132 } else if (g_strcmp0 (property_name, "Background") == 0) {
2133 retval = g_variant_new_string (applet->priv->background ?
2134 applet->priv->background : "");
2135 } else if (g_strcmp0 (property_name, "Flags") == 0) {
2136 retval = g_variant_new_uint32 (applet->priv->flags);
2137 } else if (g_strcmp0 (property_name, "SizeHints") == 0) {
2138 GVariant **children;
2139 gint i;
2140
2141 children = g_new (GVariant *, applet->priv->size_hints_len)((GVariant * *) g_malloc_n ((applet->priv->size_hints_len
), sizeof (GVariant *)))
;
2142 for (i = 0; i < applet->priv->size_hints_len; i++)
2143 children[i] = g_variant_new_int32 (applet->priv->size_hints[i]);
2144 retval = g_variant_new_array (G_VARIANT_TYPE_INT32((const GVariantType *) "i"),
2145 children, applet->priv->size_hints_len);
2146 g_free (children);
2147 } else if (g_strcmp0 (property_name, "Locked") == 0) {
2148 retval = g_variant_new_boolean (applet->priv->locked);
2149 } else if (g_strcmp0 (property_name, "LockedDown") == 0) {
2150 retval = g_variant_new_boolean (applet->priv->locked_down);
2151 }
2152
2153 return retval;
2154}
2155
2156static gboolean
2157set_property_cb (GDBusConnection *connection,
2158 const gchar *sender,
2159 const gchar *object_path,
2160 const gchar *interface_name,
2161 const gchar *property_name,
2162 GVariant *value,
2163 GError **error,
2164 gpointer user_data)
2165{
2166 CafePanelApplet *applet = CAFE_PANEL_APPLET (user_data)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((cafe_panel_applet_get_type ()))))))
;
2167
2168 if (g_strcmp0 (property_name, "PrefsPath") == 0) {
2169 cafe_panel_applet_set_preferences_path (applet, g_variant_get_string (value, NULL((void*)0)));
2170 } else if (g_strcmp0 (property_name, "Orient") == 0) {
2171 cafe_panel_applet_set_orient (applet, g_variant_get_uint32 (value));
2172 } else if (g_strcmp0 (property_name, "Size") == 0) {
2173 cafe_panel_applet_set_size (applet, g_variant_get_uint32 (value));
2174 } else if (g_strcmp0 (property_name, "Background") == 0) {
2175 cafe_panel_applet_set_background_string (applet, g_variant_get_string (value, NULL((void*)0)));
2176 } else if (g_strcmp0 (property_name, "Flags") == 0) {
2177 cafe_panel_applet_set_flags (applet, g_variant_get_uint32 (value));
2178 } else if (g_strcmp0 (property_name, "SizeHints") == 0) {
2179 const int *size_hints;
2180 gsize n_elements;
2181
2182 size_hints = g_variant_get_fixed_array (value, &n_elements, sizeof (gint32));
2183 cafe_panel_applet_set_size_hints (applet, size_hints, n_elements, 0);
2184 } else if (g_strcmp0 (property_name, "Locked") == 0) {
2185 cafe_panel_applet_set_locked (applet, g_variant_get_boolean (value));
2186 } else if (g_strcmp0 (property_name, "LockedDown") == 0) {
2187 cafe_panel_applet_set_locked_down (applet, g_variant_get_boolean (value));
2188 }
2189
2190 return TRUE(!(0));
2191}
2192
2193static const gchar introspection_xml[] =
2194 "<node>"
2195 "<interface name='org.cafe.panel.applet.Applet'>"
2196 "<method name='PopupMenu'>"
2197 "<arg name='button' type='u' direction='in'/>"
2198 "<arg name='time' type='u' direction='in'/>"
2199 "</method>"
2200 "<property name='PrefsPath' type='s' access='readwrite'/>"
2201 "<property name='Orient' type='u' access='readwrite' />"
2202 "<property name='Size' type='u' access='readwrite'/>"
2203 "<property name='Background' type='s' access='readwrite'/>"
2204 "<property name='Flags' type='u' access='readwrite'/>"
2205 "<property name='SizeHints' type='ai' access='readwrite'/>"
2206 "<property name='Locked' type='b' access='readwrite'/>"
2207 "<property name='LockedDown' type='b' access='readwrite'/>"
2208 "<signal name='Move' />"
2209 "<signal name='RemoveFromPanel' />"
2210 "<signal name='Lock' />"
2211 "<signal name='Unlock' />"
2212 "</interface>"
2213 "</node>";
2214
2215static const GDBusInterfaceVTable interface_vtable = {
2216 method_call_cb,
2217 get_property_cb,
2218 set_property_cb
2219};
2220
2221static GDBusNodeInfo *introspection_data = NULL((void*)0);
2222
2223static void
2224cafe_panel_applet_register_object (CafePanelApplet *applet)
2225{
2226 GError *error = NULL((void*)0);
2227 static gint id = 0;
2228
2229 if (!introspection_data)
2230 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL((void*)0));
2231
2232 applet->priv->object_path = g_strdup_printf (CAFE_PANEL_APPLET_OBJECT_PATH"/org/cafe/panel/applet/%s/%d", applet->priv->id, id++);
2233 applet->priv->object_id =
2234 g_dbus_connection_register_object (applet->priv->connection,
2235 applet->priv->object_path,
2236 introspection_data->interfaces[0],
2237 &interface_vtable,
2238 applet, NULL((void*)0),
2239 &error);
2240 if (!applet->priv->object_id) {
2241 g_printerr ("Failed to register object %s: %s\n", applet->priv->object_path, error->message);
2242 g_error_free (error);
2243 }
2244}
2245
2246static void cafe_panel_applet_factory_main_finalized(gpointer data, GObject* object)
2247{
2248 ctk_main_quit();
2249
2250 if (introspection_data)
2251 {
2252 g_dbus_node_info_unref(introspection_data);
2253 introspection_data = NULL((void*)0);
2254 }
2255}
2256
2257#ifdef HAVE_X111
2258static int (*_x_error_func) (Display *, XErrorEvent *);
2259
2260static int
2261_x_error_handler (Display *display, XErrorEvent *error)
2262{
2263 if (!error->error_code)
2264 return 0;
2265
2266 /* If we got a BadDrawable or a BadWindow, we ignore it for now.
2267 * FIXME: We need to somehow distinguish real errors from
2268 * X-server-induced errors. Keeping a list of windows for which we
2269 * will ignore BadDrawables would be a good idea. */
2270 if (error->error_code == BadDrawable9 ||
2271 error->error_code == BadWindow3)
2272 return 0;
2273
2274 return _x_error_func (display, error);
2275}
2276
2277/*
2278 * To do graphical embedding in the X window system, CAFE Panel
2279 * uses the classic foreign-window-reparenting trick. The
2280 * CtkPlug/CtkSocket widgets are used for this purpose. However,
2281 * serious robustness problems arise if the CtkSocket end of the
2282 * connection unexpectedly dies. The X server sends out DestroyNotify
2283 * events for the descendants of the CtkPlug (i.e., your embedded
2284 * component's windows) in effectively random order. Furthermore, if
2285 * you happened to be drawing on any of those windows when the
2286 * CtkSocket was destroyed (a common state of affairs), an X error
2287 * will kill your application.
2288 *
2289 * To solve this latter problem, CAFE Panel sets up its own X error
2290 * handler which ignores certain X errors that might have been
2291 * caused by such a scenario. Other X errors get passed to cdk_x_error
2292 * normally.
2293 */
2294static void
2295_cafe_panel_applet_setup_x_error_handler (void)
2296{
2297 static gboolean error_handler_setup = FALSE(0);
2298
2299 if (error_handler_setup)
2300 return;
2301
2302 error_handler_setup = TRUE(!(0));
2303
2304 _x_error_func = XSetErrorHandler (_x_error_handler);
2305}
2306#endif
2307
2308static int
2309_cafe_panel_applet_factory_main_internal (const gchar *factory_id,
2310 gboolean out_process,
2311 GType applet_type,
2312 CafePanelAppletFactoryCallback callback,
2313 gpointer user_data)
2314
2315{
2316 CafePanelAppletFactory* factory;
2317 GClosure* closure;
2318
2319 g_return_val_if_fail(factory_id != NULL, 1)do { if ((factory_id != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "factory_id != NULL"
); return (1); } } while (0)
;
2320 g_return_val_if_fail(callback != NULL, 1)do { if ((callback != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return (1); } } while (0)
;
2321 g_assert(g_type_is_a(applet_type, PANEL_TYPE_APPLET))do { if (((applet_type) == ((cafe_panel_applet_get_type ())) ||
(g_type_is_a) ((applet_type), ((cafe_panel_applet_get_type (
)))))) ; else g_assertion_message_expr (((gchar*) 0), "cafe-panel-applet.c"
, 2321, ((const char*) (__func__)), "g_type_is_a(applet_type, PANEL_TYPE_APPLET)"
); } while (0)
;
2322
2323
2324#ifdef HAVE_X111
2325 if (CDK_IS_X11_DISPLAY (cdk_display_get_default ())(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(cdk_display_get_default ())); GType __t = ((cdk_x11_display_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; }))))
) {
2326 /*Use this both in and out of process as the tray applet always uses CtkSocket
2327 *to handle CtkStatusIcons whether the tray itself is built in or out of process
2328 */
2329 _cafe_panel_applet_setup_x_error_handler();
2330 } else
2331#endif
2332 { // not using X11
2333 if (out_process) {
2334 g_warning("Requested out-of-process applet, which is only supported on X11");
2335 return 1;
2336 }
2337 }
2338
2339 closure = g_cclosure_new(G_CALLBACK(callback)((GCallback) (callback)), user_data, NULL((void*)0));
2340 factory = cafe_panel_applet_factory_new(factory_id, out_process, applet_type, closure);
2341 g_closure_unref(closure);
2342
2343 if (cafe_panel_applet_factory_register_service(factory))
2344 {
2345 if (out_process)
2346 {
2347 g_object_weak_ref(G_OBJECT(factory)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((factory)), (((GType) ((20) << (2))))))))
, cafe_panel_applet_factory_main_finalized, NULL((void*)0));
2348 ctk_main();
2349 }
2350
2351 return 0;
2352 }
2353
2354 g_object_unref (factory);
2355
2356 return 1;
2357}
2358
2359/**
2360 * cafe_panel_applet_factory_main:
2361 * @out_process: boolean, dummy to support applets sending it
2362 * @factory_id: Factory ID.
2363 * @applet_type: GType of the applet this factory creates.
2364 * @callback: (scope call): Callback to be called when a new applet is to be created.
2365 * @data: (closure): Callback data.
2366 *
2367 * Returns: 0 on success, 1 if there is an error.
2368 */
2369int
2370cafe_panel_applet_factory_main (const gchar *factory_id,
2371 gboolean out_process, /*Dummy to support applets w issues with this */
2372 GType applet_type,
2373 CafePanelAppletFactoryCallback callback,
2374 gpointer user_data)
2375{
2376 return _cafe_panel_applet_factory_main_internal (factory_id, TRUE(!(0)), applet_type,
2377 callback, user_data);
2378}
2379
2380/**
2381 * cafe_panel_applet_factory_setup_in_process: (skip)
2382 * @factory_id: Factory ID.
2383 * @applet_type: GType of the applet this factory creates.
2384 * @callback: (scope call): Callback to be called when a new applet is to be created.
2385 * @data: (closure): Callback data.
2386 *
2387 * Returns: 0 on success, 1 if there is an error.
2388 */
2389int
2390cafe_panel_applet_factory_setup_in_process (const gchar *factory_id,
2391 GType applet_type,
2392 CafePanelAppletFactoryCallback callback,
2393 gpointer user_data)
2394{
2395 return _cafe_panel_applet_factory_main_internal (factory_id, FALSE(0), applet_type,
2396 callback, user_data);
2397}
2398
2399/**
2400 * cafe_panel_applet_set_background_widget:
2401 * @applet: a #PanelApplet.
2402 * @widget: a #CtkWidget.
2403 *
2404 * Configure #PanelApplet to automatically draw the background of the applet on
2405 * @widget. It is generally enough to call this function with @applet as
2406 * @widget.
2407 *
2408 * Deprecated: 3.20: Do not use this API. Since 3.20 this function does nothing.
2409 **/
2410
2411void
2412cafe_panel_applet_set_background_widget (CafePanelApplet *applet,
2413 CtkWidget *widget)
2414{
2415}
2416
2417guint32
2418cafe_panel_applet_get_xid (CafePanelApplet *applet,
2419 CdkScreen *screen)
2420{
2421 // out_of_process should only be true on X11, so an extra runtime Wayland check is not needed
2422 if (applet->priv->out_of_process == FALSE(0))
2423 return 0;
2424
2425#ifdef HAVE_X111
2426 ctk_window_set_screen (CTK_WINDOW (applet->priv->plug)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_window_get_type ()))))
))
, screen);
2427 ctk_widget_show (applet->priv->plug);
2428
2429 return ctk_plug_get_id (CTK_PLUG (applet->priv->plug)((((CtkPlug*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet->priv->plug)), ((ctk_plug_get_type ()))))))
);
2430#else
2431 return 0;
2432#endif
2433}
2434
2435const gchar *
2436cafe_panel_applet_get_object_path (CafePanelApplet *applet)
2437{
2438 return applet->priv->object_path;
2439}
2440
2441G_MODULE_EXPORT__attribute__((visibility("default"))) CtkWidget *
2442cafe_panel_applet_get_applet_widget (const gchar *factory_id,
2443 guint uid)
2444{
2445 CtkWidget *widget;
2446
2447 widget = cafe_panel_applet_factory_get_applet_widget (factory_id, uid);
2448 if (!widget) {
2449 return NULL((void*)0);
2450 }
2451
2452 cafe_panel_applet_setup (CAFE_PANEL_APPLET (widget)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((cafe_panel_applet_get_type ()))))))
);
2453
2454 return widget;
2455}