~ubuntu-branches/ubuntu/oneiric/gnome-panel/oneiric

« back to all changes in this revision

Viewing changes to libpanel-applet/panel-applet.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher, Sebastien Bacher, Jeremy Bicha
  • Date: 2011-05-30 11:04:49 UTC
  • mfrom: (1.13.10 upstream) (2.2.5 experimental)
  • Revision ID: james.westby@ubuntu.com-20110530110449-hinl17kxkcefjw6x
Tags: 1:3.0.2-0ubuntu1
[ Sebastien Bacher ]
* New upstream version
* debian/control.in:
  - the new libgweather version is in oneiric, use it
  - drop the python and python-gconf depends, 
    they were added for gnome-panel-add which is still using gconf and buggy
* debian/gnome-panel-data.install:
  - don't install the apport hook, it's only getting gconf datas which 
    doesn't work since gnome-panel uses gsettings
* debian/patches/90_build_fixes.patch:
  - restore build fix from git not applied in the new serie
* debian/patches/01_panel_submenus.patch:
  - don't take that Debian diff, the .menus use the upstream naming in Ubuntu
* debian/patches/06_no_resize_grip.patch:
  - dropped, the issue is fixed in the new version
* debian/patches/50_fix-potfiles.patch:
  - dropped, the issue is fixed in the new version
* debian/watch:
  - track unstable series as well

Drop those delta, since gnome-panel is not the default Ubuntu session now we
can go back to an experience closer to the upstream one: 
* debian/control.in:
  - drop the indicators recommends, unity-2d is the ubuntu fallback session
    so we can get back to use an upstream config for gnome-panel and reduce
    the delta we carry
* debian/patches/04_default_panel_config.patch:
  - don't modify the upstream layout
* debian/patches/05_no_session_delay.patch:
  - no need to tweak the upstream session to optimize it
* debian/patches/16_compiz_workspace_switcher.patch:
  - go back to the upstream switcher behaviour    
* debian/patches/25_dynamic_fusa_detection.patch:
  - not needed since we use the upstream layout, could be ported if someone
    is wanting to do the work though
* debian/patches/30_disable-initial-animation.patch, debian/rules:
  - drop the --disable-initial-animation, that was some login optimization
    but since it's not the default desktop you should go back to the 
    upstream behaviour

[ Jeremy Bicha ]   
* New upstream version
* Merge from Debian experimental, remaining Ubuntu changes:
* debian/control:
  - Recommends gnome-settings-daemon which has the timezone polkit service
* debian/rules:
  - Update translations template.
* debian/gnome-panel-data.install:
  - Install apport hook
  - Install the "About Ubuntu" menu item.
* debian/patches/01_layout.patch:
  - Disabled, Help & About Ubuntu don't fit as well in Gnome Panel 3
* debian/patches/01_panel_submenus.patch.
  - Dropped
* debian/patches/03_dnd_places_link.patch:
  - Disabled, when using Drag'n'Drop from Places menu, install a link launcher
    (.desktop file) instead of copying the entire directory.
* debian/patches/17_about-ubuntu-translation.patch:
  - List ubuntu-about.desktop for translation.
* debian/patches/40_unset_menuproxy.patch:
  - Make sure gnome-panel and the applets don't pick up menu proxies.
* debian/patches/50_fix-potfiles.patch
  - Fix i18n
* debian/patches/85_disable_shutdown_on_ltsp.patch:
  - Suppress the shutdown option in the panel if LTSP_CLIENT is set.
* debian/patches/71_change_bookmark_submenu_limit_value.patch
  - Dropped, picked up by Debian
* debian/patches/18_lockdown_lock_editor.patch:
* debian/patches/90_git_wnck_show_realize.patch:
* debian/patches/90_fix_linking_DSO_link.patch:
* debian/patches/91_gir_annotations.patch
* debian/patches/92_git_calendar_day.patch
* debian/patches/92_git_fix_applets_in_multiscreen.patch:
  - Dropped, applied upstream
* debian/watch:
  - watch unstable versions

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
#include <unistd.h>
31
31
#include <stdlib.h>
32
32
#include <string.h>
 
33
#include <errno.h>
33
34
 
34
35
#include <glib/gi18n-lib.h>
35
36
#include <cairo.h>
36
 
#include <gdk/gdk.h>
37
 
#include <gdk/gdkx.h>
 
37
#include <cairo-gobject.h>
38
38
#include <gdk/gdkkeysyms.h>
39
39
#include <gtk/gtk.h>
 
40
#include <gtk/gtkx.h>
40
41
#include <gconf/gconf.h>
41
42
#include <gconf/gconf-client.h>
42
43
#include <X11/Xatom.h>
 
44
#include <cairo-xlib.h>
43
45
 
44
46
#include "panel-applet.h"
 
47
#include "panel-applet-bindings.h"
45
48
#include "panel-applet-factory.h"
46
49
#include "panel-applet-marshal.h"
47
50
#include "panel-applet-enums.h"
48
51
 
 
52
/**
 
53
 * SECTION:applet
 
54
 * @short_description: a widget embedded in a panel.
 
55
 * @stability: Unstable
 
56
 *
 
57
 * Applets are small applications that are embedded in the GNOME panel. They
 
58
 * can be used to give quick access to some features, or to display the state
 
59
 * of something specific.
 
60
 *
 
61
 * The #PanelApplet API hides all of the embedding process as it handles all
 
62
 * the communication with the GNOME panel. It is a subclass of #GtkBin, so you
 
63
 * can add any kind of widgets to it.
 
64
 *
 
65
 * See the <link linkend="getting-started">Getting Started</link> section to
 
66
 * learn how to properly use #PanelApplet.
 
67
 */
 
68
 
 
69
/**
 
70
 * SECTION:applet-factory
 
71
 * @short_description: the factory that will create applets.
 
72
 * @stability: Unstable
 
73
 *
 
74
 * This API is used to create an <link
 
75
 * linkend="getting-started.concepts.applet-factory">applet factory</link>. You
 
76
 * need to call one and only one of these functions to get applets working in
 
77
 * your binary.
 
78
 */
 
79
 
49
80
#define PANEL_APPLET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_APPLET, PanelAppletPrivate))
50
81
 
51
82
struct _PanelAppletPrivate {
58
89
        GClosure          *closure;
59
90
        char              *object_path;
60
91
        guint              object_id;
 
92
        char              *settings_path;
61
93
        char              *prefs_key;
62
94
 
63
95
        GtkUIManager      *ui_manager;
78
110
 
79
111
        gboolean           moving_focus_out;
80
112
 
81
 
        gboolean           locked;
82
113
        gboolean           locked_down;
83
114
};
84
115
 
87
118
        CHANGE_SIZE,
88
119
        CHANGE_BACKGROUND,
89
120
        MOVE_FOCUS_OUT_OF_APPLET,
90
 
        SAVE_YOURSELF,
91
121
        LAST_SIGNAL
92
122
};
93
123
 
98
128
        PROP_ID,
99
129
        PROP_CLOSURE,
100
130
        PROP_CONNECTION,
 
131
        PROP_SETTINGS_PATH,
101
132
        PROP_PREFS_KEY,
102
133
        PROP_ORIENT,
103
134
        PROP_SIZE,
104
135
        PROP_BACKGROUND,
105
136
        PROP_FLAGS,
106
137
        PROP_SIZE_HINTS,
107
 
        PROP_LOCKED,
108
138
        PROP_LOCKED_DOWN
109
139
};
110
140
 
116
146
                                                    PanelApplet       *applet);
117
147
static void       panel_applet_menu_cmd_move       (GtkAction         *action,
118
148
                                                    PanelApplet       *applet);
119
 
static void       panel_applet_menu_cmd_lock       (GtkAction         *action,
120
 
                                                    PanelApplet       *applet);
121
149
static void       panel_applet_register_object     (PanelApplet       *applet);
122
150
 
123
151
static const gchar panel_menu_ui[] =
124
152
        "<ui>\n"
125
153
        "  <popup name=\"PanelAppletPopup\" action=\"PopupAction\">\n"
126
154
        "    <placeholder name=\"AppletItems\"/>\n"
127
 
        "    <separator/>\n"
 
155
        "  </popup>\n"
 
156
        "  <popup name=\"PanelAppletEditPopup\" action=\"PopupEditAction\">\n"
 
157
        "    <menuitem name=\"MoveItem\" action=\"Move\"/>\n"
128
158
        "    <menuitem name=\"RemoveItem\" action=\"Remove\"/>\n"
129
 
        "    <menuitem name=\"MoveItem\" action=\"Move\"/>\n"
130
 
        "    <separator/>\n"
131
 
        "    <menuitem name=\"LockItem\" action=\"Lock\"/>\n"
132
159
        "  </popup>\n"
133
160
        "</ui>\n";
134
161
 
135
162
static const GtkActionEntry menu_entries[] = {
 
163
        { "PopupAction", NULL, "Popup Action",
 
164
          NULL, NULL,
 
165
          NULL },
136
166
        { "Remove", GTK_STOCK_REMOVE, N_("_Remove From Panel"),
137
167
          NULL, NULL,
138
168
          G_CALLBACK (panel_applet_menu_cmd_remove) },
141
171
          G_CALLBACK (panel_applet_menu_cmd_move) }
142
172
};
143
173
 
144
 
static const GtkToggleActionEntry menu_toggle_entries[] = {
145
 
        { "Lock", NULL, N_("Loc_k To Panel"),
146
 
          NULL, NULL,
147
 
          G_CALLBACK (panel_applet_menu_cmd_lock) }
148
 
};
149
 
 
150
174
G_DEFINE_TYPE (PanelApplet, panel_applet, GTK_TYPE_EVENT_BOX)
151
175
 
152
176
#define PANEL_APPLET_INTERFACE   "org.gnome.panel.applet.Applet"
160
184
{
161
185
        GSList *list, *l;
162
186
 
 
187
        g_assert (error != NULL);
 
188
 
163
189
        list = gconf_client_all_entries (client, schema_dir, error);
164
190
 
165
191
        if (*error != NULL)
254
280
        g_slist_free (list);
255
281
}
256
282
 
 
283
/**
 
284
 * panel_applet_add_preferences:
 
285
 * @applet: a #PanelApplet.
 
286
 * @schema_dir: a GConf path of a schema directory.
 
287
 * @error: a #GError, or %NULL.
 
288
 *
 
289
 * Associates the per-instance GConf directory of @applet to the schemas
 
290
 * defined in @schema_dir. This must be called if the applet will save
 
291
 * per-instance settings, to ensure that each key in the per-instance GConf
 
292
 * directory has a defined type, sane default and documentation.
 
293
 *
 
294
 * Deprecated: 3.0: Use #GSettings to store per-instance settings.
 
295
 **/
257
296
void
258
297
panel_applet_add_preferences (PanelApplet  *applet,
259
298
                              const gchar  *schema_dir,
260
 
                              GError      **opt_error)
 
299
                              GError      **error)
261
300
{
262
 
        GError **error = NULL;
 
301
        GError **_error = NULL;
263
302
        GError  *our_error = NULL;
264
303
 
265
304
        g_return_if_fail (PANEL_IS_APPLET (applet));
268
307
        if (!applet->priv->prefs_key)
269
308
                return;
270
309
 
271
 
        if (opt_error)
272
 
                error = opt_error;
 
310
        /* panel_applet_associate_schemas_in_dir() requires a non-NULL error */
 
311
        if (error)
 
312
                _error = error;
273
313
        else
274
 
                error = &our_error;
 
314
                _error = &our_error;
275
315
 
276
316
        panel_applet_associate_schemas_in_dir (applet->priv->client,
277
317
                                               applet->priv->prefs_key,
278
318
                                               schema_dir,
279
 
                                               error);
 
319
                                               _error);
280
320
 
281
 
        if (!opt_error && our_error) {
282
 
                g_warning (G_STRLOC ": failed to add preferences from '%s' : '%s'",
283
 
                           schema_dir, our_error->message);
 
321
        if (!error && our_error)
284
322
                g_error_free (our_error);
285
 
        }
286
323
}
287
324
 
 
325
/**
 
326
 * panel_applet_get_preferences_key:
 
327
 * @applet: a #PanelApplet.
 
328
 *
 
329
 * Gets the GConf path to the per-instance settings of @applet.
 
330
 *
 
331
 * Returns: a copy of the GConf path to the per-instance settings of @applet.
 
332
 *
 
333
 * Deprecated: 3.0: Use #GSettings to store per-instance settings.
 
334
 **/
288
335
char *
289
336
panel_applet_get_preferences_key (PanelApplet *applet)
290
337
{
327
374
        g_object_notify (G_OBJECT (applet), "prefs-key");
328
375
}
329
376
 
 
377
/**
 
378
 * panel_applet_settings_new:
 
379
 * @applet: a #PanelApplet.
 
380
 * @schema: the name of the schema.
 
381
 *
 
382
 * Creates a new #GSettings object for the per-instance settings of @applet,
 
383
 * with a given schema.
 
384
 *
 
385
 * Returns: a new #GSettings object for the per-instance settings of @applet.
 
386
 **/
 
387
GSettings *
 
388
panel_applet_settings_new (PanelApplet *applet,
 
389
                           const char  *schema)
 
390
{
 
391
        g_return_val_if_fail (PANEL_IS_APPLET (applet), NULL);
 
392
        g_return_val_if_fail (schema != NULL, NULL);
 
393
 
 
394
        if (!applet->priv->settings_path)
 
395
                return NULL;
 
396
 
 
397
        return g_settings_new_with_path (schema, applet->priv->settings_path);
 
398
}
 
399
 
 
400
static void
 
401
panel_applet_set_settings_path (PanelApplet *applet,
 
402
                                const char  *settings_path)
 
403
{
 
404
        if (applet->priv->settings_path == settings_path)
 
405
                return;
 
406
 
 
407
        if (g_strcmp0 (applet->priv->settings_path, settings_path) == 0)
 
408
                return;
 
409
 
 
410
        g_free (applet->priv->settings_path);
 
411
        applet->priv->settings_path = NULL;
 
412
 
 
413
        if (settings_path)
 
414
                applet->priv->settings_path = g_strdup (settings_path);
 
415
 
 
416
        g_object_notify (G_OBJECT (applet), "settings-path");
 
417
}
 
418
 
 
419
/**
 
420
 * panel_applet_get_flags:
 
421
 * @applet: a #PanelApplet.
 
422
 *
 
423
 * Gets the #PanelAppletFlags of @applet.
 
424
 *
 
425
 * Returns: the #PanelAppletFlags of @applet.
 
426
 **/
330
427
PanelAppletFlags
331
428
panel_applet_get_flags (PanelApplet *applet)
332
429
{
335
432
        return applet->priv->flags;
336
433
}
337
434
 
 
435
/**
 
436
 * panel_applet_set_flags:
 
437
 * @applet: a #PanelApplet.
 
438
 * @flags: #PanelAppletFlags to use for @applet.
 
439
 *
 
440
 * Sets the #PanelAppletFlags of @applet. Most of the time, at least
 
441
 * %PANEL_APPLET_EXPAND_MINOR should be used.
 
442
 **/
338
443
void
339
444
panel_applet_set_flags (PanelApplet      *applet,
340
445
                        PanelAppletFlags  flags)
412
517
        return FALSE;
413
518
}
414
519
 
 
520
/**
 
521
 * panel_applet_set_size_hints:
 
522
 * @applet: a #PanelApplet.
 
523
 * @size_hints: array of sizes.
 
524
 * @n_elements: length of @size_hints.
 
525
 * @base_size: base size of the applet.
 
526
 *
 
527
 * Give hints to the panel about sizes @applet is comfortable with. This is
 
528
 * generally useful for applets that can take a lot of space, in case the panel
 
529
 * gets full and needs to restrict the size of some applets.
 
530
 *
 
531
 * @size_hints should have an even number of sizes. It is an array of (max,
 
532
 * min) pairs where min(i) > max(i + 1).
 
533
 *
 
534
 * @base_size will be added to all sizes in @size_hints, and is therefore a way
 
535
 * to guarantee a minimum size to @applet.
 
536
 *
 
537
 * The panel will try to allocate a size that is acceptable to @applet, i.e. in
 
538
 * one of the (@base_size + max, @base_size + min) ranges.
 
539
 *
 
540
 * %PANEL_APPLET_EXPAND_MAJOR must be set for @applet to use size hints.
 
541
 **/
415
542
void
416
543
panel_applet_set_size_hints (PanelApplet *applet,
417
544
                             const int   *size_hints,
465
592
        }
466
593
}
467
594
 
 
595
/**
 
596
 * panel_applet_get_size:
 
597
 * @applet: a #PanelApplet.
 
598
 *
 
599
 * Gets the size of the panel @applet is on. For a horizontal panel, the
 
600
 * size if the height of the panel; for a vertical panel, the size is the width
 
601
 * of the panel.
 
602
 *
 
603
 * Returns: the size of the panel @applet is on.
 
604
 *
 
605
 * Deprecated: 3.0: Use the allocation of @applet instead.
 
606
 **/
468
607
guint
469
608
panel_applet_get_size (PanelApplet *applet)
470
609
{
491
630
        g_object_notify (G_OBJECT (applet), "size");
492
631
}
493
632
 
 
633
/**
 
634
 * panel_applet_get_orient:
 
635
 * @applet: a #PanelApplet.
 
636
 *
 
637
 * Gets the #PanelAppletOrient of @applet.
 
638
 *
 
639
 * Returns: the #PanelAppletOrient of @applet.
 
640
 **/
494
641
PanelAppletOrient
495
642
panel_applet_get_orient (PanelApplet *applet)
496
643
{
517
664
        g_object_notify (G_OBJECT (applet), "orient");
518
665
}
519
666
 
520
 
#if 0
521
 
/* Locked should not be public API: it's not useful for applet writers to know
522
 
 * if the applet is locked (as opposed to locked_down). */
523
 
static gboolean
524
 
panel_applet_get_locked (PanelApplet *applet)
525
 
{
526
 
        g_return_val_if_fail (PANEL_IS_APPLET (applet), FALSE);
527
 
 
528
 
        return applet->priv->locked;
529
 
}
530
 
#endif
531
 
 
532
 
static void
533
 
panel_applet_set_locked (PanelApplet *applet,
534
 
                         gboolean     locked)
535
 
{
536
 
        GtkAction *action;
537
 
 
538
 
        g_return_if_fail (PANEL_IS_APPLET (applet));
539
 
 
540
 
        if (applet->priv->locked == locked)
541
 
                return;
542
 
 
543
 
        applet->priv->locked = locked;
544
 
 
545
 
        action = panel_applet_menu_get_action (applet, "Lock");
546
 
        g_signal_handlers_block_by_func (action,
547
 
                                         panel_applet_menu_cmd_lock,
548
 
                                         applet);
549
 
        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), locked);
550
 
        g_signal_handlers_unblock_by_func (action,
551
 
                                           panel_applet_menu_cmd_lock,
552
 
                                           applet);
553
 
 
554
 
        panel_applet_menu_update_actions (applet);
555
 
 
556
 
        g_object_notify (G_OBJECT (applet), "locked");
557
 
 
558
 
        if (applet->priv->connection) {
559
 
                GError *error = NULL;
560
 
 
561
 
                g_dbus_connection_emit_signal (applet->priv->connection,
562
 
                                               NULL,
563
 
                                               applet->priv->object_path,
564
 
                                               PANEL_APPLET_INTERFACE,
565
 
                                               locked ? "Lock" : "Unlock",
566
 
                                               NULL, &error);
567
 
                if (error) {
568
 
                        g_printerr ("Failed to send signal %s: %s\n",
569
 
                                    locked ? "Lock" : "Unlock",
570
 
                                    error->message);
571
 
                        g_error_free (error);
572
 
                }
573
 
        }
574
 
}
575
 
 
 
667
/**
 
668
 * panel_applet_get_locked_down:
 
669
 * @applet: a #PanelApplet.
 
670
 *
 
671
 * Gets whether the panel @applet is on is locked down or not. A locked down
 
672
 * applet should not allow any change to its configuration.
 
673
 *
 
674
 * Returns: %TRUE if the panel @applet is on is locked down, %FALSE otherwise.
 
675
 **/
576
676
gboolean
577
677
panel_applet_get_locked_down (PanelApplet *applet)
578
678
{
681
781
        return None;
682
782
}
683
783
 
 
784
/**
 
785
 * panel_applet_request_focus:
 
786
 * @applet: a #PanelApplet.
 
787
 * @timestamp: the timestamp of the user interaction (typically a button or key
 
788
 * press event) which triggered this call.
 
789
 *
 
790
 * Requests focus for @applet. There is no guarantee that @applet will
 
791
 * successfully get focus after that call.
 
792
 **/
684
793
/* This function
685
794
 *   1) Gets the window id of the panel that contains the applet
686
795
 *      using XQueryTree and XGetWindowProperty to find an ancestor
706
815
        display = gdk_screen_get_display (screen);
707
816
 
708
817
        xdisplay = GDK_DISPLAY_XDISPLAY (display);
709
 
        xroot    = GDK_WINDOW_XWINDOW (root);
 
818
        xroot    = GDK_WINDOW_XID (root);
710
819
 
711
820
        panel_applet_init_atoms (xdisplay);
712
821
 
742
851
static void
743
852
panel_applet_menu_update_actions (PanelApplet *applet)
744
853
{
745
 
        gboolean locked = applet->priv->locked;
746
854
        gboolean locked_down = applet->priv->locked_down;
747
855
 
748
 
        g_object_set (panel_applet_menu_get_action (applet, "Lock"),
749
 
                      "visible", !locked_down, NULL);
750
856
        g_object_set (panel_applet_menu_get_action (applet, "Move"),
751
 
                      "sensitive", !locked,
752
857
                      "visible", !locked_down,
753
858
                      NULL);
754
859
        g_object_set (panel_applet_menu_get_action (applet, "Remove"),
755
 
                      "sensitive", !locked,
756
860
                      "visible", !locked_down,
757
861
                      NULL);
758
862
}
801
905
        }
802
906
}
803
907
 
804
 
static void
805
 
panel_applet_menu_cmd_lock (GtkAction   *action,
806
 
                            PanelApplet *applet)
807
 
{
808
 
        gboolean locked;
809
 
 
810
 
        locked = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
811
 
        panel_applet_set_locked (applet, locked);
812
 
}
813
 
 
 
908
/**
 
909
 * panel_applet_setup_menu:
 
910
 * @applet: a #PanelApplet.
 
911
 * @xml: a menu XML string.
 
912
 * @action_group: a #GtkActionGroup.
 
913
 *
 
914
 * Sets up the context menu of @applet. @xml is a #GtkUIManager UI definition,
 
915
 * describing how to display the menu items. @action_group contains the
 
916
 * various #GtkAction that are referenced in @xml.
 
917
 *
 
918
 * See also the <link linkend="getting-started.context-menu">Context
 
919
 * Menu</link> section.
 
920
 **/
814
921
void
815
922
panel_applet_setup_menu (PanelApplet    *applet,
816
923
                         const gchar    *xml,
817
 
                         GtkActionGroup *applet_action_group)
 
924
                         GtkActionGroup *action_group)
818
925
{
819
926
        gchar  *new_xml;
820
927
        GError *error = NULL;
825
932
        if (applet->priv->applet_action_group)
826
933
                return;
827
934
 
828
 
        applet->priv->applet_action_group = g_object_ref (applet_action_group);
 
935
        applet->priv->applet_action_group = g_object_ref (action_group);
829
936
        gtk_ui_manager_insert_action_group (applet->priv->ui_manager,
830
 
                                            applet_action_group, 0);
 
937
                                            action_group, 0);
831
938
 
832
939
        new_xml = g_strdup_printf ("<ui><popup name=\"PanelAppletPopup\" action=\"AppletItems\">"
833
940
                                   "<placeholder name=\"AppletItems\">%s\n</placeholder>\n"
841
948
        }
842
949
}
843
950
 
 
951
/**
 
952
 * panel_applet_setup_menu_from_file:
 
953
 * @applet: a #PanelApplet.
 
954
 * @filename: path to a menu XML file.
 
955
 * @action_group: a #GtkActionGroup.
 
956
 *
 
957
 * Sets up the context menu of @applet. @filename is the path to a menu XML
 
958
 * file, containing a #GtkUIManager UI definition that describes how to display
 
959
 * the menu items. @action_group contains the various #GtkAction that
 
960
 * are referenced in @xml.
 
961
 *
 
962
 * See also the <link linkend="getting-started.context-menu">Context
 
963
 * Menu</link> section.
 
964
 **/
844
965
void
845
966
panel_applet_setup_menu_from_file (PanelApplet    *applet,
846
967
                                   const gchar    *filename,
847
 
                                   GtkActionGroup *applet_action_group)
 
968
                                   GtkActionGroup *action_group)
848
969
{
849
970
        gchar  *xml = NULL;
850
971
        GError *error = NULL;
851
972
 
852
973
        if (g_file_get_contents (filename, &xml, NULL, &error)) {
853
 
                panel_applet_setup_menu (applet, xml, applet_action_group);
 
974
                panel_applet_setup_menu (applet, xml, action_group);
854
975
        } else {
855
976
                g_warning ("%s", error->message);
856
977
                g_error_free (error);
880
1001
 
881
1002
        panel_applet_set_preferences_key (applet, NULL);
882
1003
 
 
1004
        panel_applet_bindings_clean (applet->priv->client);
 
1005
 
883
1006
        if (applet->priv->client)
884
1007
                g_object_unref (applet->priv->client);
885
1008
        applet->priv->client = NULL;
901
1024
 
902
1025
        g_free (applet->priv->size_hints);
903
1026
        g_free (applet->priv->prefs_key);
 
1027
        g_free (applet->priv->settings_path);
904
1028
        g_free (applet->priv->background);
905
1029
        g_free (applet->priv->id);
906
1030
 
957
1081
 
958
1082
        screen = gtk_widget_get_screen (widget);
959
1083
 
960
 
        gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
 
1084
        gtk_widget_get_preferred_size (GTK_WIDGET (menu), &requisition, NULL);
961
1085
        gdk_window_get_origin (gtk_widget_get_window (widget),
962
1086
                               &menu_x, &menu_y);
963
1087
        gtk_widget_get_pointer (widget, &pointer_x, &pointer_y);
1012
1136
                         guint32      time)
1013
1137
{
1014
1138
        GtkWidget *menu;
 
1139
        GList     *children, *l;
 
1140
        gboolean   visible = FALSE;
1015
1141
 
1016
1142
        menu = gtk_ui_manager_get_widget (applet->priv->ui_manager,
1017
1143
                                          "/PanelAppletPopup");
 
1144
 
 
1145
        children = gtk_container_get_children (GTK_CONTAINER (menu));
 
1146
        for (l = children; l != NULL; l = l->next) {
 
1147
                visible = gtk_widget_get_visible (GTK_WIDGET (l->data));
 
1148
                if (visible)
 
1149
                        break;
 
1150
        }
 
1151
        g_list_free (children);
 
1152
 
 
1153
        if (!visible)
 
1154
                return;
 
1155
 
1018
1156
        gtk_menu_popup (GTK_MENU (menu),
1019
1157
                        NULL, NULL,
1020
1158
                        (GtkMenuPositionFunc) panel_applet_position_menu,
1022
1160
                        button, time);
1023
1161
}
1024
1162
 
 
1163
static void
 
1164
panel_applet_edit_menu_popup (PanelApplet *applet,
 
1165
                              guint        button,
 
1166
                              guint32      time)
 
1167
{
 
1168
        GtkWidget *menu;
 
1169
 
 
1170
        if (applet->priv->locked_down)
 
1171
                return;
 
1172
 
 
1173
        menu = gtk_ui_manager_get_widget (applet->priv->ui_manager,
 
1174
                                          "/PanelAppletEditPopup");
 
1175
        gtk_menu_popup (GTK_MENU (menu),
 
1176
                        NULL, NULL,
 
1177
                        NULL,
 
1178
                        applet,
 
1179
                        button, time);
 
1180
}
 
1181
 
1025
1182
static gboolean
1026
1183
panel_applet_can_focus (GtkWidget *widget)
1027
1184
{
1061
1218
                 * selected.
1062
1219
                 * We don't want to hog the pointer on our parent.
1063
1220
                 */
1064
 
                gdk_display_pointer_ungrab
1065
 
                        (gtk_widget_get_display (widget),
1066
 
                         GDK_CURRENT_TIME);
 
1221
                gdk_device_ungrab (event->device, GDK_CURRENT_TIME);
1067
1222
        } else {
1068
1223
                xevent.xbutton.type = ButtonRelease;
1069
1224
        }
1070
1225
 
1071
1226
        xevent.xbutton.display     = GDK_WINDOW_XDISPLAY (window);
1072
 
        xevent.xbutton.window      = GDK_WINDOW_XWINDOW (socket_window);
1073
 
        xevent.xbutton.root        = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window
1074
 
                                                         (gdk_drawable_get_screen (window)));
 
1227
        xevent.xbutton.window      = GDK_WINDOW_XID (socket_window);
 
1228
        xevent.xbutton.root        = GDK_WINDOW_XID (gdk_screen_get_root_window
 
1229
                                                         (gdk_window_get_screen (window)));
1075
1230
        /*
1076
1231
         * FIXME: the following might cause
1077
1232
         *        big problems for non-GTK apps
1087
1242
        gdk_error_trap_push ();
1088
1243
 
1089
1244
        XSendEvent (GDK_WINDOW_XDISPLAY (window),
1090
 
                    GDK_WINDOW_XWINDOW (socket_window),
 
1245
                    GDK_WINDOW_XID (socket_window),
1091
1246
                    False, NoEventMask, &xevent);
1092
1247
 
1093
 
        gdk_flush ();
1094
 
        gdk_error_trap_pop ();
 
1248
        gdk_error_trap_pop_ignored ();
1095
1249
 
1096
1250
        return TRUE;
1097
1251
}
1110
1264
        }
1111
1265
 
1112
1266
        if (event->button == 3) {
1113
 
                panel_applet_menu_popup (applet, event->button, event->time);
 
1267
                guint modifiers;
 
1268
 
 
1269
                modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
 
1270
 
 
1271
                if (modifiers == panel_applet_bindings_get_mouse_button_modifier_keymask ())
 
1272
                        panel_applet_edit_menu_popup (applet, event->button, event->time);
 
1273
                else
 
1274
                        panel_applet_menu_popup (applet, event->button, event->time);
1114
1275
 
1115
1276
                return TRUE;
1116
1277
        }
1128
1289
}
1129
1290
 
1130
1291
static gboolean
1131
 
panel_applet_popup_menu (GtkWidget *widget)
1132
 
{
1133
 
        panel_applet_menu_popup (PANEL_APPLET (widget), 3, GDK_CURRENT_TIME);
1134
 
 
1135
 
        return TRUE;
1136
 
}
1137
 
 
1138
 
static void
1139
 
panel_applet_size_request (GtkWidget *widget, GtkRequisition *requisition)
1140
 
{
1141
 
        int focus_width = 0;
1142
 
 
1143
 
        GTK_WIDGET_CLASS (panel_applet_parent_class)->size_request (widget,
1144
 
                                                                    requisition);
1145
 
 
1146
 
        if (!panel_applet_can_focus (widget))
1147
 
                return;
1148
 
 
1149
 
        /*
1150
 
         * We are deliberately ignoring focus-padding here to
1151
 
         * save valuable panel real estate.
1152
 
         */
1153
 
        gtk_widget_style_get (widget,
1154
 
                              "focus-line-width", &focus_width,
1155
 
                              NULL);
1156
 
 
1157
 
        requisition->width  += 2 * focus_width;
1158
 
        requisition->height += 2 * focus_width;
 
1292
panel_applet_key_press_event (GtkWidget   *widget,
 
1293
                              GdkEventKey *event)
 
1294
{
 
1295
        gboolean is_popup = FALSE;
 
1296
        gboolean is_edit_popup = FALSE;
 
1297
 
 
1298
        panel_applet_bindings_key_event_is_popup (event, &is_popup, &is_edit_popup);
 
1299
 
 
1300
        if (is_edit_popup)
 
1301
                panel_applet_edit_menu_popup (PANEL_APPLET (widget), 3, event->time);
 
1302
        else if (is_popup)
 
1303
                panel_applet_menu_popup (PANEL_APPLET (widget), 3, event->time);
 
1304
 
 
1305
        return (is_popup || is_edit_popup);
 
1306
}
 
1307
 
 
1308
static GtkSizeRequestMode
 
1309
panel_applet_get_request_mode (GtkWidget *widget)
 
1310
{
 
1311
        PanelApplet *applet = PANEL_APPLET (widget);
 
1312
        PanelAppletOrient orientation;
 
1313
 
 
1314
        orientation = panel_applet_get_orient (applet);
 
1315
        if (orientation == PANEL_APPLET_ORIENT_UP ||
 
1316
            orientation == PANEL_APPLET_ORIENT_DOWN)
 
1317
                return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
 
1318
 
 
1319
        return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
 
1320
}
 
1321
 
 
1322
static void
 
1323
panel_applet_get_preferred_width (GtkWidget *widget,
 
1324
                                  int       *minimum_width,
 
1325
                                  int       *natural_width)
 
1326
{
 
1327
        int focus_width = 0;
 
1328
 
 
1329
        GTK_WIDGET_CLASS (panel_applet_parent_class)->get_preferred_width (widget,
 
1330
                                                                           minimum_width,
 
1331
                                                                           natural_width);
 
1332
        if (!panel_applet_can_focus (widget))
 
1333
                return;
 
1334
 
 
1335
        /* We are deliberately ignoring focus-padding here to
 
1336
         * save valuable panel real estate.
 
1337
         */
 
1338
        gtk_widget_style_get (widget,
 
1339
                              "focus-line-width", &focus_width,
 
1340
                              NULL);
 
1341
 
 
1342
        *minimum_width += 2 * focus_width;
 
1343
        *natural_width += 2 * focus_width;
 
1344
}
 
1345
 
 
1346
static void
 
1347
panel_applet_get_preferred_height (GtkWidget *widget,
 
1348
                                  int       *minimum_height,
 
1349
                                  int       *natural_height)
 
1350
{
 
1351
        int focus_width = 0;
 
1352
 
 
1353
        GTK_WIDGET_CLASS (panel_applet_parent_class)->get_preferred_height (widget,
 
1354
                                                                            minimum_height,
 
1355
                                                                            natural_height);
 
1356
        if (!panel_applet_can_focus (widget))
 
1357
                return;
 
1358
 
 
1359
        /* We are deliberately ignoring focus-padding here to
 
1360
         * save valuable panel real estate.
 
1361
         */
 
1362
        gtk_widget_style_get (widget,
 
1363
                              "focus-line-width", &focus_width,
 
1364
                              NULL);
 
1365
 
 
1366
        *minimum_height += 2 * focus_width;
 
1367
        *natural_height += 2 * focus_width;
1159
1368
}
1160
1369
 
1161
1370
static void
1218
1427
}
1219
1428
 
1220
1429
static gboolean
1221
 
panel_applet_expose (GtkWidget      *widget,
1222
 
                     GdkEventExpose *event) 
 
1430
panel_applet_draw (GtkWidget *widget,
 
1431
                   cairo_t   *cr)
1223
1432
{
1224
 
        GtkAllocation allocation;
 
1433
        GtkStyleContext *context;
1225
1434
        int border_width;
1226
1435
        int focus_width = 0;
1227
 
        int x, y, width, height;
1228
 
 
1229
 
        g_return_val_if_fail (PANEL_IS_APPLET (widget), FALSE);
1230
 
        g_return_val_if_fail (event != NULL, FALSE);
1231
 
 
1232
 
        GTK_WIDGET_CLASS (panel_applet_parent_class)->expose_event (widget,
1233
 
                                                                    event);
 
1436
        gdouble x, y, width, height;
 
1437
 
 
1438
        GTK_WIDGET_CLASS (panel_applet_parent_class)->draw (widget, cr);
1234
1439
 
1235
1440
        if (!gtk_widget_has_focus (widget))
1236
1441
                return FALSE;
1237
1442
 
1238
 
        gtk_widget_get_allocation (widget, &allocation);
 
1443
        width = gtk_widget_get_allocated_width (widget);
 
1444
        height = gtk_widget_get_allocated_height (widget);
1239
1445
 
1240
1446
        /*
1241
1447
         * We are deliberately ignoring focus-padding here to
1247
1453
 
1248
1454
        border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1249
1455
 
1250
 
        x = allocation.x;
1251
 
        y = allocation.y;
1252
 
 
1253
 
        width  = allocation.width  - 2 * border_width;
1254
 
        height = allocation.height - 2 * border_width;
1255
 
 
1256
 
        gtk_paint_focus (gtk_widget_get_style (widget),
1257
 
                         gtk_widget_get_window (widget),
1258
 
                         gtk_widget_get_state (widget),
1259
 
                         &event->area, widget, "panel_applet",
1260
 
                         x, y, width, height);
 
1456
        x = 0; // FIXME: border_width ?
 
1457
        y = 0; // FIXME: border_width ?
 
1458
        width  -= 2 * border_width;
 
1459
        height -= 2 * border_width;
 
1460
 
 
1461
        context = gtk_widget_get_style_context (widget);
 
1462
        gtk_style_context_save (context);
 
1463
 
 
1464
        cairo_save (cr);
 
1465
        gtk_render_focus (context, cr, x, y, width, height);
 
1466
        cairo_restore (cr);
 
1467
 
 
1468
        gtk_style_context_restore (context);
1261
1469
 
1262
1470
        return FALSE;
1263
1471
}
1310
1518
        return ret;
1311
1519
}
1312
1520
 
1313
 
static gboolean
1314
 
panel_applet_parse_color (const gchar *color_str,
1315
 
                          GdkColor    *color)
1316
 
{
1317
 
        int r, g, b;
1318
 
 
1319
 
        g_assert (color_str && color);
1320
 
 
1321
 
        if (sscanf (color_str, "%4x%4x%4x", &r, &g, &b) != 3)
1322
 
                return FALSE;
1323
 
 
1324
 
        color->red   = r;
1325
 
        color->green = g;
1326
 
        color->blue  = b;
1327
 
 
1328
 
        return TRUE;
1329
 
}
1330
 
 
1331
 
static gboolean
1332
 
panel_applet_parse_pixmap_str (const char *str,
1333
 
                               GdkNativeWindow *xid,
1334
 
                               int             *x,
1335
 
                               int             *y)
1336
 
{
1337
 
        char **elements;
1338
 
        char  *tmp;
1339
 
 
1340
 
        g_return_val_if_fail (str != NULL, FALSE);
1341
 
        g_return_val_if_fail (xid != NULL, FALSE);
1342
 
        g_return_val_if_fail (x != NULL, FALSE);
1343
 
        g_return_val_if_fail (y != NULL, FALSE);
1344
 
 
1345
 
        elements = g_strsplit (str, ",", -1);
1346
 
 
1347
 
        if (!elements)
1348
 
                return FALSE;
1349
 
 
1350
 
        if (!elements [0] || !*elements [0] ||
1351
 
            !elements [1] || !*elements [1] ||
1352
 
            !elements [2] || !*elements [2])
1353
 
                goto ERROR_AND_FREE;
1354
 
 
1355
 
        *xid = strtol (elements [0], &tmp, 10);
1356
 
        if (tmp == elements [0])
1357
 
                goto ERROR_AND_FREE;
1358
 
 
1359
 
        *x   = strtol (elements [1], &tmp, 10);
1360
 
        if (tmp == elements [1])
1361
 
                goto ERROR_AND_FREE;
1362
 
 
1363
 
        *y   = strtol (elements [2], &tmp, 10);
1364
 
        if (tmp == elements [2])
1365
 
                goto ERROR_AND_FREE;
1366
 
 
1367
 
        g_strfreev (elements);
1368
 
        return TRUE;
1369
 
 
1370
 
 ERROR_AND_FREE:
1371
 
        g_strfreev (elements);
1372
 
        return FALSE;
1373
 
}
1374
 
 
1375
 
static GdkPixmap *
1376
 
panel_applet_get_pixmap (PanelApplet     *applet,
1377
 
                         GdkNativeWindow  xid,
1378
 
                         int              x,
1379
 
                         int              y)
1380
 
{
1381
 
        gboolean         display_grabbed;
1382
 
        GdkPixmap       *pixmap;
1383
 
        GdkDisplay      *display;
1384
 
        GdkPixmap       *retval;
 
1521
static cairo_surface_t *
 
1522
panel_applet_create_foreign_surface_for_display (GdkDisplay *display,
 
1523
                                                 GdkVisual  *visual,
 
1524
                                                 Window      xid)
 
1525
{
 
1526
        Window window;
 
1527
        gint x, y;
 
1528
        guint width, height, border, depth;
 
1529
 
 
1530
        if (!XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xid, &window,
 
1531
                           &x, &y, &width, &height, &border, &depth))
 
1532
                return NULL;
 
1533
 
 
1534
        return cairo_xlib_surface_create (GDK_DISPLAY_XDISPLAY (display),
 
1535
                                          xid, gdk_x11_visual_get_xvisual (visual),
 
1536
                                          width, height);
 
1537
}
 
1538
 
 
1539
static cairo_pattern_t *
 
1540
panel_applet_get_pattern_from_pixmap (PanelApplet *applet,
 
1541
                                      Window       xid,
 
1542
                                      int          x,
 
1543
                                      int          y)
 
1544
{
1385
1545
        GdkWindow       *window;
1386
1546
        int              width;
1387
1547
        int              height;
1388
 
        cairo_t         *cr;
1389
 
        cairo_pattern_t *pattern;
 
1548
        cairo_t         *cr;
 
1549
        cairo_surface_t *background;
 
1550
        cairo_surface_t *surface;
 
1551
        cairo_matrix_t   matrix;
 
1552
        cairo_pattern_t *pattern;
1390
1553
 
1391
1554
        g_return_val_if_fail (PANEL_IS_APPLET (applet), NULL);
1392
1555
 
1393
1556
        if (!gtk_widget_get_realized (GTK_WIDGET (applet)))
1394
1557
                return NULL;
1395
1558
 
1396
 
        display = gdk_display_get_default ();
1397
 
        display_grabbed = FALSE;
1398
 
 
1399
 
        window = gtk_widget_get_window (GTK_WIDGET (applet));
1400
 
 
1401
 
        pixmap = gdk_pixmap_lookup_for_display (display, xid);
1402
 
        if (pixmap)
1403
 
                g_object_ref (pixmap);
1404
 
        else {
1405
 
                display_grabbed = TRUE;
1406
 
                gdk_x11_display_grab (display);
1407
 
                pixmap = gdk_pixmap_foreign_new_for_display (display, xid);
1408
 
        }
1409
 
 
1410
 
        /* This can happen if the user changes the background very fast.
1411
 
         * We'll get the next update, so it's not a big deal. */
1412
 
        if (pixmap == NULL) {
1413
 
                if (display_grabbed)
1414
 
                        gdk_x11_display_ungrab (display);
1415
 
                return NULL;
1416
 
        }
1417
 
 
1418
 
        gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
1419
 
        retval = gdk_pixmap_new (window, width, height, -1);
1420
 
 
1421
 
        /* the pixmap has no colormap, and we need one */
1422
 
        gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap),
1423
 
                                   gdk_drawable_get_colormap (window));
1424
 
 
1425
 
        cr = gdk_cairo_create (GDK_DRAWABLE (retval));
1426
 
        gdk_cairo_set_source_pixmap (cr, pixmap, -x, -y);
1427
 
        pattern = cairo_get_source (cr);
1428
 
        cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
1429
 
 
1430
 
        cairo_rectangle (cr, 0, 0, width, height);
1431
 
        cairo_fill (cr);
1432
 
 
1433
 
        cairo_destroy (cr);
1434
 
 
1435
 
        g_object_unref (pixmap);
1436
 
 
1437
 
        if (display_grabbed)
1438
 
                gdk_x11_display_ungrab (display);
1439
 
 
1440
 
        return retval;
 
1559
        window = gtk_widget_get_window (GTK_WIDGET (applet));
 
1560
 
 
1561
        gdk_error_trap_push ();
 
1562
        background = panel_applet_create_foreign_surface_for_display (gdk_window_get_display (window),
 
1563
                                                                      gdk_window_get_visual (window),
 
1564
                                                                      xid);
 
1565
        gdk_error_trap_pop_ignored ();
 
1566
 
 
1567
        /* background can be NULL if the user changes the background very fast.
 
1568
         * We'll get the next update, so it's not a big deal. */
 
1569
        if (!background ||
 
1570
            cairo_surface_status (background) != CAIRO_STATUS_SUCCESS) {
 
1571
                if (background)
 
1572
                        cairo_surface_destroy (background);
 
1573
                return NULL;
 
1574
        }
 
1575
 
 
1576
        width = gdk_window_get_width (window);
 
1577
        height = gdk_window_get_height (window);
 
1578
        surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
 
1579
 
 
1580
        gdk_error_trap_push ();
 
1581
        cr = cairo_create (surface);
 
1582
        cairo_set_source_surface (cr, background, -x, -y);
 
1583
        cairo_rectangle (cr, 0, 0, width, height);
 
1584
        cairo_fill (cr);
 
1585
        gdk_error_trap_pop_ignored ();
 
1586
 
 
1587
        cairo_surface_destroy (background);
 
1588
 
 
1589
        pattern = NULL;
 
1590
 
 
1591
        if (cairo_status (cr) == CAIRO_STATUS_SUCCESS) {
 
1592
                pattern = cairo_pattern_create_for_surface (surface);
 
1593
                cairo_matrix_init_translate (&matrix, 0, 0);
 
1594
                cairo_matrix_scale (&matrix, width, height);
 
1595
                cairo_pattern_set_matrix (pattern, &matrix);
 
1596
                cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
 
1597
        }
 
1598
 
 
1599
        cairo_destroy (cr);
 
1600
        cairo_surface_destroy (surface);
 
1601
 
 
1602
        return pattern;
1441
1603
}
1442
1604
 
1443
 
static PanelAppletBackgroundType
1444
 
panel_applet_handle_background_string (PanelApplet  *applet,
1445
 
                                       GdkColor     *color,
1446
 
                                       GdkPixmap   **pixmap)
 
1605
/**
 
1606
 * panel_applet_get_background:
 
1607
 * @applet: a #PanelApplet.
 
1608
 *
 
1609
 * Gets the background pattern for @applet, or %NULL if there is none.
 
1610
 *
 
1611
 * Returns: (transfer full): a new #cairo_pattern_t to use as background for
 
1612
 * @applet.
 
1613
 **/
 
1614
cairo_pattern_t *
 
1615
panel_applet_get_background (PanelApplet *applet)
1447
1616
{
1448
 
        PanelAppletBackgroundType   retval;
1449
 
        char                      **elements;
 
1617
        cairo_pattern_t *pattern = NULL;
 
1618
        GVariant        *variant;
 
1619
        GVariantIter     iter;
 
1620
        GError          *error = NULL;
1450
1621
 
1451
 
        retval = PANEL_NO_BACKGROUND;
 
1622
        g_return_val_if_fail (PANEL_IS_APPLET (applet), NULL);
1452
1623
 
1453
1624
        if (!gtk_widget_get_realized (GTK_WIDGET (applet)) || !applet->priv->background)
1454
 
                return retval;
1455
 
 
1456
 
        elements = g_strsplit (applet->priv->background, ":", -1);
1457
 
 
1458
 
        if (elements [0] && !strcmp (elements [0], "none" )) {
1459
 
                retval = PANEL_NO_BACKGROUND;
1460
 
 
1461
 
        } else if (elements [0] && !strcmp (elements [0], "color")) {
1462
 
                g_return_val_if_fail (color != NULL, PANEL_NO_BACKGROUND);
1463
 
 
1464
 
                if (!elements [1] || !panel_applet_parse_color (elements [1], color)) {
1465
 
 
1466
 
                        g_warning ("Incomplete '%s' background type received", elements [0]);
1467
 
                        g_strfreev (elements);
1468
 
                        return PANEL_NO_BACKGROUND;
1469
 
                }
1470
 
 
1471
 
                retval = PANEL_COLOR_BACKGROUND;
1472
 
 
1473
 
        } else if (elements [0] && !strcmp (elements [0], "pixmap")) {
1474
 
                GdkNativeWindow pixmap_id;
1475
 
                int             x, y;
1476
 
 
1477
 
                g_return_val_if_fail (pixmap != NULL, PANEL_NO_BACKGROUND);
1478
 
 
1479
 
                if (!panel_applet_parse_pixmap_str (elements [1], &pixmap_id, &x, &y)) {
1480
 
                        g_warning ("Incomplete '%s' background type received: %s",
1481
 
                                   elements [0], elements [1]);
1482
 
 
1483
 
                        g_strfreev (elements);
1484
 
                        return PANEL_NO_BACKGROUND;
1485
 
                }
1486
 
 
1487
 
                *pixmap = panel_applet_get_pixmap (applet, pixmap_id, x, y);
1488
 
                if (!*pixmap) {
1489
 
                        g_warning ("Failed to get pixmap %s", elements [1]);
1490
 
                        g_strfreev (elements);
1491
 
                        return PANEL_NO_BACKGROUND;
1492
 
                }
1493
 
 
1494
 
                retval = PANEL_PIXMAP_BACKGROUND;
1495
 
        } else
1496
 
                g_warning ("Unknown background type received");
1497
 
 
1498
 
        g_strfreev (elements);
1499
 
 
1500
 
        return retval;
1501
 
}
1502
 
 
1503
 
PanelAppletBackgroundType
1504
 
panel_applet_get_background (PanelApplet *applet,
1505
 
                             GdkColor *color,
1506
 
                             GdkPixmap **pixmap)
1507
 
{
1508
 
        g_return_val_if_fail (PANEL_IS_APPLET (applet), PANEL_NO_BACKGROUND);
1509
 
 
1510
 
        /* initial sanity */
1511
 
        if (pixmap != NULL)
1512
 
                *pixmap = NULL;
1513
 
        if (color != NULL)
1514
 
                memset (color, 0, sizeof (GdkColor));
1515
 
 
1516
 
        return panel_applet_handle_background_string (applet, color, pixmap);
 
1625
                return NULL;
 
1626
 
 
1627
        variant = g_variant_parse (NULL, applet->priv->background,
 
1628
                                   NULL, NULL, &error);
 
1629
        if (!variant) {
 
1630
                g_warning ("Error parsing background %s: %s\n", applet->priv->background, error->message);
 
1631
                g_error_free (error);
 
1632
                return NULL;
 
1633
        }
 
1634
 
 
1635
        g_variant_iter_init (&iter, variant);
 
1636
        switch (g_variant_iter_n_children (&iter)) {
 
1637
        case 4: {
 
1638
                gdouble red, green, blue, alpha;
 
1639
 
 
1640
                g_variant_get (variant, "(dddd)", &red, &green, &blue, &alpha);
 
1641
                pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
 
1642
        }
 
1643
                break;
 
1644
        case 3: {
 
1645
                guint32 xid;
 
1646
                int x, y;
 
1647
 
 
1648
                g_variant_get (variant, "(uii)", &xid, &x, &y);
 
1649
                pattern = panel_applet_get_pattern_from_pixmap (applet, xid, x, y);
 
1650
                if (!pattern)
 
1651
                        g_warning ("Failed to get pixmap %d, %d, %d", xid, x, y);
 
1652
        }
 
1653
                break;
 
1654
        default:
 
1655
                break;
 
1656
        }
 
1657
 
 
1658
        g_variant_unref (variant);
 
1659
 
 
1660
        return pattern;
1517
1661
}
1518
1662
 
1519
1663
static void
1534
1678
        g_object_notify (G_OBJECT (applet), "background");
1535
1679
}
1536
1680
 
1537
 
static void
1538
 
panel_applet_update_background_for_widget (GtkWidget                 *widget,
1539
 
                                           PanelAppletBackgroundType  type,
1540
 
                                           GdkColor                  *color,
1541
 
                                           GdkPixmap                 *pixmap)
1542
 
{
1543
 
        GtkRcStyle *rc_style;
1544
 
        GtkStyle   *style;
1545
 
 
1546
 
        /* reset style */
1547
 
        gtk_widget_set_style (widget, NULL);
1548
 
        rc_style = gtk_rc_style_new ();
1549
 
        gtk_widget_modify_style (widget, rc_style);
1550
 
        g_object_unref (rc_style);
1551
 
 
1552
 
        switch (type) {
1553
 
        case PANEL_NO_BACKGROUND:
1554
 
                break;
1555
 
        case PANEL_COLOR_BACKGROUND:
1556
 
                gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, color);
1557
 
                break;
1558
 
        case PANEL_PIXMAP_BACKGROUND:
1559
 
                style = gtk_style_copy (gtk_widget_get_style (widget));
1560
 
                if (style->bg_pixmap[GTK_STATE_NORMAL])
1561
 
                        g_object_unref (style->bg_pixmap[GTK_STATE_NORMAL]);
1562
 
                style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref (pixmap);
1563
 
                gtk_widget_set_style (widget, style);
1564
 
                g_object_unref (style);
1565
 
                break;
1566
 
        default:
1567
 
                g_assert_not_reached ();
1568
 
                break;
1569
 
        }
 
1681
static GtkStyleProperties *
 
1682
_panel_applet_get_widget_style_properties (GtkWidget *widget,
 
1683
                                           gboolean   create_if_needed)
 
1684
{
 
1685
        GtkStyleProperties *properties;
 
1686
 
 
1687
        properties = g_object_get_data (G_OBJECT (widget),
 
1688
                                        "panel-applet-style-props");
 
1689
 
 
1690
        if (!properties && create_if_needed) {
 
1691
                properties = gtk_style_properties_new ();
 
1692
                g_object_set_data_full (G_OBJECT (widget),
 
1693
                                        "panel-applet-style-props",
 
1694
                                        properties,
 
1695
                                        (GDestroyNotify) g_object_unref);
 
1696
        }
 
1697
 
 
1698
        return properties;
 
1699
}
 
1700
 
 
1701
static void
 
1702
_panel_applet_reset_widget_style_properties (GtkWidget *widget)
 
1703
{
 
1704
        GtkStyleProperties *properties;
 
1705
 
 
1706
        properties = _panel_applet_get_widget_style_properties (widget, FALSE);
 
1707
 
 
1708
        if (properties)
 
1709
                gtk_style_context_remove_provider (gtk_widget_get_style_context (widget),
 
1710
                                                   GTK_STYLE_PROVIDER (properties));
 
1711
 
 
1712
        g_object_set_data (G_OBJECT (widget), "panel-applet-style-props", NULL);
 
1713
}
 
1714
 
 
1715
static void
 
1716
panel_applet_update_background_for_widget (GtkWidget       *widget,
 
1717
                                           cairo_pattern_t *pattern)
 
1718
{
 
1719
        GtkStyleProperties *properties;
 
1720
 
 
1721
        gtk_widget_reset_style (widget);
 
1722
 
 
1723
        if (!pattern) {
 
1724
                _panel_applet_reset_widget_style_properties (widget);
 
1725
                return;
 
1726
        }
 
1727
 
 
1728
        properties = _panel_applet_get_widget_style_properties (widget, TRUE);
 
1729
 
 
1730
        switch (cairo_pattern_get_type (pattern)) {
 
1731
        case CAIRO_PATTERN_TYPE_SOLID: {
 
1732
                GdkRGBA color;
 
1733
 
 
1734
                cairo_pattern_get_rgba (pattern, &color.red, &color.green, &color.blue, &color.alpha);
 
1735
                gtk_style_properties_set (properties, GTK_STATE_FLAG_NORMAL,
 
1736
                                          "background-color", &color,
 
1737
                                          "background-image", NULL,
 
1738
                                          NULL);
 
1739
        }
 
1740
                break;
 
1741
        case CAIRO_PATTERN_TYPE_SURFACE:
 
1742
                gtk_style_properties_set (properties, GTK_STATE_FLAG_NORMAL,
 
1743
                                          /* background-color can't be NULL,
 
1744
                                           * but is ignored anyway */
 
1745
                                          "background-image", pattern,
 
1746
                                          NULL);
 
1747
                break;
 
1748
        default:
 
1749
                break;
 
1750
        }
 
1751
 
 
1752
        /* Note: this actually replaces the old properties, since it's the same
 
1753
         * pointer */
 
1754
        gtk_style_context_add_provider (gtk_widget_get_style_context (widget),
 
1755
                                        GTK_STYLE_PROVIDER (properties),
 
1756
                                        GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1570
1757
}
1571
1758
 
1572
1759
static void
1573
1760
panel_applet_handle_background (PanelApplet *applet)
1574
1761
{
1575
 
        PanelAppletBackgroundType  type;
1576
 
        GdkColor                   color;
1577
 
        GdkPixmap                 *pixmap;
 
1762
        cairo_pattern_t *pattern;
1578
1763
 
1579
 
        type = panel_applet_get_background (applet, &color, &pixmap);
 
1764
        pattern = panel_applet_get_background (applet);
1580
1765
 
1581
1766
        if (applet->priv->background_widget)
1582
1767
                panel_applet_update_background_for_widget (applet->priv->background_widget,
1583
 
                                                           type, &color, pixmap);
1584
 
 
1585
 
        switch (type) {
1586
 
        case PANEL_NO_BACKGROUND:
1587
 
                g_signal_emit (G_OBJECT (applet),
1588
 
                               panel_applet_signals [CHANGE_BACKGROUND],
1589
 
                               0, PANEL_NO_BACKGROUND, NULL, NULL);
1590
 
                break;
1591
 
        case PANEL_COLOR_BACKGROUND:
1592
 
                g_signal_emit (G_OBJECT (applet),
1593
 
                               panel_applet_signals [CHANGE_BACKGROUND],
1594
 
                               0, PANEL_COLOR_BACKGROUND, &color, NULL);
1595
 
                break;
1596
 
        case PANEL_PIXMAP_BACKGROUND:
1597
 
                g_signal_emit (G_OBJECT (applet),
1598
 
                               panel_applet_signals [CHANGE_BACKGROUND],
1599
 
                               0, PANEL_PIXMAP_BACKGROUND, NULL, pixmap);
1600
 
 
1601
 
                g_object_unref (pixmap);
1602
 
                break;
1603
 
        default:
1604
 
                g_assert_not_reached ();
1605
 
                break;
1606
 
        }
 
1768
                                                           pattern);
 
1769
 
 
1770
        g_signal_emit (G_OBJECT (applet),
 
1771
                        panel_applet_signals [CHANGE_BACKGROUND],
 
1772
                        0, pattern);
 
1773
        if (pattern)
 
1774
                cairo_pattern_destroy (pattern);
1607
1775
}
1608
1776
 
1609
1777
static void
1647
1815
        case PROP_CONNECTION:
1648
1816
                g_value_set_object (value, applet->priv->connection);
1649
1817
                break;
 
1818
        case PROP_SETTINGS_PATH:
 
1819
                g_value_set_string (value, applet->priv->settings_path);
 
1820
                break;
1650
1821
        case PROP_PREFS_KEY:
1651
1822
                g_value_set_string (value, applet->priv->prefs_key);
1652
1823
                break;
1676
1847
                g_value_set_pointer (value, variant);
1677
1848
        }
1678
1849
                break;
1679
 
        case PROP_LOCKED:
1680
 
                g_value_set_boolean (value, applet->priv->locked);
1681
 
                break;
1682
1850
        case PROP_LOCKED_DOWN:
1683
1851
                g_value_set_boolean (value, applet->priv->locked_down);
1684
1852
                break;
1701
1869
                break;
1702
1870
        case PROP_CLOSURE:
1703
1871
                applet->priv->closure = g_value_get_pointer (value);
1704
 
                g_closure_set_marshal (applet->priv->closure,
1705
 
                                       panel_applet_marshal_BOOLEAN__STRING);
 
1872
                /* We know closure should not be NULL, but we'll fail in
 
1873
                 * panel_applet_constructed() with a proper message if this is
 
1874
                 * the case. */
 
1875
                if (applet->priv->closure)
 
1876
                        g_closure_set_marshal (applet->priv->closure,
 
1877
                                               panel_applet_marshal_BOOLEAN__STRING);
1706
1878
                break;
1707
1879
        case PROP_CONNECTION:
1708
1880
                applet->priv->connection = g_value_dup_object (value);
1709
1881
                break;
 
1882
        case PROP_SETTINGS_PATH:
 
1883
                panel_applet_set_settings_path (applet, g_value_get_string (value));
 
1884
                break;
1710
1885
        case PROP_PREFS_KEY:
1711
1886
                panel_applet_set_preferences_key (applet, g_value_get_string (value));
1712
1887
                break;
1731
1906
                panel_applet_set_size_hints (applet, size_hints, n_elements, 0);
1732
1907
        }
1733
1908
                break;
1734
 
        case PROP_LOCKED:
1735
 
                panel_applet_set_locked (applet, g_value_get_boolean (value));
1736
 
                break;
1737
1909
        case PROP_LOCKED_DOWN:
1738
1910
                panel_applet_set_locked_down (applet, g_value_get_boolean (value));
1739
1911
                break;
1747
1919
                  GdkModifierType  modifiers,
1748
1920
                  GtkDirectionType direction)
1749
1921
{
1750
 
        gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
 
1922
        gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
1751
1923
                                      "move_focus_out_of_applet", 1,
1752
1924
                                      GTK_TYPE_DIRECTION_TYPE, direction);
1753
 
        gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
 
1925
        gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
1754
1926
                                      "move_focus_out_of_applet", 1,
1755
1927
                                      GTK_TYPE_DIRECTION_TYPE, direction);
1756
1928
}
1816
1988
                                      menu_entries,
1817
1989
                                      G_N_ELEMENTS (menu_entries),
1818
1990
                                      applet);
1819
 
        gtk_action_group_add_toggle_actions (applet->priv->panel_action_group,
1820
 
                                             menu_toggle_entries,
1821
 
                                             G_N_ELEMENTS (menu_toggle_entries),
1822
 
                                             applet);
1823
1991
 
1824
1992
        applet->priv->ui_manager = gtk_ui_manager_new ();
1825
1993
        gtk_ui_manager_insert_action_group (applet->priv->ui_manager,
1828
1996
                                           panel_menu_ui, -1, NULL);
1829
1997
 
1830
1998
 
 
1999
        panel_applet_bindings_init (applet->priv->client);
1831
2000
 
1832
2001
 
1833
2002
        applet->priv->plug = gtk_plug_new (0);
1847
2016
{
1848
2017
        PanelApplet *applet = PANEL_APPLET (object);
1849
2018
 
1850
 
        panel_applet_register_object (applet);
 
2019
        if (!applet->priv->connection || !applet->priv->closure || !applet->priv->id) {
 
2020
                g_printerr ("Bad use of PanelApplet API: you should not create a PanelApplet object yourself. Please use panel_applet_factory_main() instead.\n");
 
2021
                g_assert_not_reached ();
 
2022
        }
 
2023
 
 
2024
        return panel_applet_register_object (applet);
1851
2025
}
1852
2026
 
1853
2027
static void
1854
2028
panel_applet_class_init (PanelAppletClass *klass)
1855
2029
{
1856
2030
        GObjectClass   *gobject_class = (GObjectClass *) klass;
1857
 
        GtkObjectClass *object_class = (GtkObjectClass *) klass;
1858
2031
        GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
1859
2032
        GtkBindingSet *binding_set;
1860
2033
 
1861
2034
        gobject_class->get_property = panel_applet_get_property;
1862
2035
        gobject_class->set_property = panel_applet_set_property;
1863
2036
        gobject_class->constructed = panel_applet_constructed;
 
2037
        gobject_class->finalize = panel_applet_finalize;
 
2038
 
1864
2039
        klass->move_focus_out_of_applet = panel_applet_move_focus_out_of_applet;
1865
2040
 
1866
2041
        widget_class->button_press_event = panel_applet_button_press;
1867
2042
        widget_class->button_release_event = panel_applet_button_release;
1868
 
        widget_class->size_request = panel_applet_size_request;
 
2043
        widget_class->key_press_event = panel_applet_key_press_event;
 
2044
        widget_class->get_request_mode = panel_applet_get_request_mode;
 
2045
        widget_class->get_preferred_width = panel_applet_get_preferred_width;
 
2046
        widget_class->get_preferred_height = panel_applet_get_preferred_height;
1869
2047
        widget_class->size_allocate = panel_applet_size_allocate;
1870
 
        widget_class->expose_event = panel_applet_expose;
 
2048
        widget_class->draw = panel_applet_draw;
1871
2049
        widget_class->focus = panel_applet_focus;
1872
2050
        widget_class->realize = panel_applet_realize;
1873
 
        widget_class->popup_menu = panel_applet_popup_menu;
1874
 
 
1875
 
        gobject_class->finalize = panel_applet_finalize;
1876
2051
 
1877
2052
        g_type_class_add_private (klass, sizeof (PanelAppletPrivate));
1878
2053
 
 
2054
        /**
 
2055
         * PanelApplet:id: (skip)
 
2056
         *
 
2057
         * Implementation detail.
 
2058
         **/
1879
2059
        g_object_class_install_property (gobject_class,
1880
2060
                                         PROP_ID,
1881
2061
                                         g_param_spec_string ("id",
1884
2064
                                                              NULL,
1885
2065
                                                              G_PARAM_CONSTRUCT_ONLY |
1886
2066
                                                              G_PARAM_READWRITE));
 
2067
        /**
 
2068
         * PanelApplet:closure: (skip)
 
2069
         *
 
2070
         * Implementation detail.
 
2071
         **/
1887
2072
        g_object_class_install_property (gobject_class,
1888
2073
                                         PROP_CLOSURE,
1889
2074
                                         g_param_spec_pointer ("closure",
1891
2076
                                                               "The Applet closure",
1892
2077
                                                               G_PARAM_CONSTRUCT_ONLY |
1893
2078
                                                               G_PARAM_READWRITE));
 
2079
        /**
 
2080
         * PanelApplet:connection: (skip)
 
2081
         *
 
2082
         * Implementation detail.
 
2083
         **/
1894
2084
        g_object_class_install_property (gobject_class,
1895
2085
                                         PROP_CONNECTION,
1896
2086
                                         g_param_spec_object ("connection",
1899
2089
                                                              G_TYPE_DBUS_CONNECTION,
1900
2090
                                                              G_PARAM_CONSTRUCT_ONLY |
1901
2091
                                                              G_PARAM_READWRITE));
 
2092
        /**
 
2093
         * PanelApplet:settings-path:
 
2094
         *
 
2095
         * The GSettings path to the per-instance settings of the applet.
 
2096
         *
 
2097
         * This property gets set when the applet gets embedded.
 
2098
         **/
 
2099
        g_object_class_install_property (gobject_class,
 
2100
                                         PROP_SETTINGS_PATH,
 
2101
                                         g_param_spec_string ("settings-path",
 
2102
                                                              "SettingsPath",
 
2103
                                                              "GSettings path to per-instance settings",
 
2104
                                                              NULL,
 
2105
                                                              G_PARAM_READWRITE));
 
2106
        /**
 
2107
         * PanelApplet:prefs-key:
 
2108
         *
 
2109
         * The GConf path to the per-instance settings of the applet.
 
2110
         *
 
2111
         * This property gets set when the applet gets embedded.
 
2112
         *
 
2113
         * Deprecated: 3.0: Use #GSettings to store per-instance settings.
 
2114
         **/
1902
2115
        g_object_class_install_property (gobject_class,
1903
2116
                                         PROP_PREFS_KEY,
1904
2117
                                         g_param_spec_string ("prefs-key",
1906
2119
                                                              "GConf Preferences Key",
1907
2120
                                                              NULL,
1908
2121
                                                              G_PARAM_READWRITE));
 
2122
        /**
 
2123
         * PanelApplet:orient:
 
2124
         *
 
2125
         * The #PanelAppletOrient of the applet.
 
2126
         *
 
2127
         * This property gets set when the applet gets embedded, and can change
 
2128
         * when the panel position changes.
 
2129
         **/
1909
2130
        g_object_class_install_property (gobject_class,
1910
2131
                                         PROP_ORIENT,
1911
2132
                                         g_param_spec_uint ("orient",
1912
2133
                                                            "Orient",
1913
2134
                                                            "Panel Applet Orientation",
1914
 
                                                            0, G_MAXUINT, 0, /* FIXME */
 
2135
                                                            PANEL_APPLET_ORIENT_FIRST,
 
2136
                                                            PANEL_APPLET_ORIENT_LAST,
 
2137
                                                            PANEL_APPLET_ORIENT_UP,
1915
2138
                                                            G_PARAM_READWRITE));
 
2139
        /**
 
2140
         * PanelApplet:size:
 
2141
         *
 
2142
         * The size of the panel the applet is on. For a horizontal panel, the
 
2143
         * size if the height of the panel; for a vertical panel, the size is
 
2144
         * the width of the panel.
 
2145
         *
 
2146
         * This property gets set when the applet gets embedded, and can change
 
2147
         * when the panel size changes.
 
2148
         *
 
2149
         * Deprecated: 3.0: Use the allocation of @applet instead.
 
2150
         **/
1916
2151
        g_object_class_install_property (gobject_class,
1917
2152
                                         PROP_SIZE,
1918
2153
                                         g_param_spec_uint ("size",
1920
2155
                                                            "Panel Applet Size",
1921
2156
                                                            0, G_MAXUINT, 0,
1922
2157
                                                            G_PARAM_READWRITE));
 
2158
        /**
 
2159
         * PanelApplet:background: (skip)
 
2160
         *
 
2161
         * Implementation detail.
 
2162
         **/
1923
2163
        g_object_class_install_property (gobject_class,
1924
2164
                                         PROP_BACKGROUND,
1925
2165
                                         g_param_spec_string ("background",
1927
2167
                                                              "Panel Applet Background",
1928
2168
                                                              NULL,
1929
2169
                                                              G_PARAM_READWRITE));
 
2170
        /**
 
2171
         * PanelApplet:flags:
 
2172
         *
 
2173
         * The #PanelAppletFlags of the applet.
 
2174
         **/
1930
2175
        g_object_class_install_property (gobject_class,
1931
2176
                                         PROP_FLAGS,
1932
2177
                                         g_param_spec_uint ("flags",
1933
2178
                                                            "Flags",
1934
2179
                                                            "Panel Applet flags",
1935
 
                                                            0, G_MAXUINT, 0, /* FIXME */
 
2180
                                                            PANEL_APPLET_FLAGS_NONE,
 
2181
                                                            PANEL_APPLET_FLAGS_ALL,
 
2182
                                                            PANEL_APPLET_FLAGS_NONE,
1936
2183
                                                            G_PARAM_READWRITE));
 
2184
        /**
 
2185
         * PanelApplet:size-hints:
 
2186
         *
 
2187
         * The size hints set for the applet. See panel_applet_set_size_hints().
 
2188
         **/
1937
2189
        g_object_class_install_property (gobject_class,
1938
2190
                                         PROP_SIZE_HINTS,
1939
2191
                                         /* FIXME: value_array? */
1940
2192
                                         g_param_spec_pointer ("size-hints",
1941
2193
                                                               "SizeHints",
1942
 
                                                               "Panel Applet Size Hints",
1943
 
                                                               G_PARAM_READWRITE));
1944
 
        g_object_class_install_property (gobject_class,
1945
 
                                         PROP_LOCKED,
1946
 
                                         g_param_spec_boolean ("locked",
1947
 
                                                               "Locked",
1948
 
                                                               "Whether Panel Applet is locked",
1949
 
                                                               FALSE,
1950
 
                                                               G_PARAM_READWRITE));
 
2194
                                                               "Size hints of the applet",
 
2195
                                                               G_PARAM_READWRITE));
 
2196
        /**
 
2197
         * PanelApplet:locked-down:
 
2198
         *
 
2199
         * Whether the panel the applet is on is locked down.
 
2200
         **/
1951
2201
        g_object_class_install_property (gobject_class,
1952
2202
                                         PROP_LOCKED_DOWN,
1953
2203
                                         g_param_spec_boolean ("locked-down",
1954
2204
                                                               "LockedDown",
1955
 
                                                               "Whether Panel Applet is locked down",
 
2205
                                                               "Whether the panel the applet is on is locked down",
1956
2206
                                                               FALSE,
1957
2207
                                                               G_PARAM_READWRITE));
1958
2208
 
 
2209
        /**
 
2210
         * PanelApplet::change-orient:
 
2211
         * @applet: the #PanelApplet which emitted the signal.
 
2212
         * @orient: the new #PanelAppletOrient of @applet.
 
2213
         *
 
2214
         * Emitted when the #PanelAppletOrient of @applet has changed.
 
2215
         **/
1959
2216
        panel_applet_signals [CHANGE_ORIENT] =
1960
2217
                g_signal_new ("change_orient",
1961
2218
                              G_TYPE_FROM_CLASS (klass),
1963
2220
                              G_STRUCT_OFFSET (PanelAppletClass, change_orient),
1964
2221
                              NULL,
1965
2222
                              NULL,
1966
 
                              panel_applet_marshal_VOID__UINT,
 
2223
                              g_cclosure_marshal_VOID__UINT,
1967
2224
                              G_TYPE_NONE,
1968
2225
                              1,
1969
2226
                              G_TYPE_UINT);
1970
2227
 
 
2228
        /**
 
2229
         * PanelApplet::change-size:
 
2230
         * @applet: the #PanelApplet which emitted the signal.
 
2231
         * @size: the new size of the panel @applet is on.
 
2232
         *
 
2233
         * Emitted when the size of the panel @applet is on has changed.
 
2234
         *
 
2235
         * Deprecated: 3.0: Use the #GtkWidget::size-allocate signal instead.
 
2236
         **/
1971
2237
        panel_applet_signals [CHANGE_SIZE] =
1972
2238
                g_signal_new ("change_size",
1973
2239
                              G_TYPE_FROM_CLASS (klass),
1975
2241
                              G_STRUCT_OFFSET (PanelAppletClass, change_size),
1976
2242
                              NULL,
1977
2243
                              NULL,
1978
 
                              panel_applet_marshal_VOID__INT,
 
2244
                              g_cclosure_marshal_VOID__INT,
1979
2245
                              G_TYPE_NONE,
1980
2246
                              1,
1981
2247
                              G_TYPE_INT);
1982
2248
 
 
2249
        /**
 
2250
         * PanelApplet::change-background:
 
2251
         * @applet: the #PanelApplet which emitted the signal.
 
2252
         * @pattern: the new background pattern for @applet, or %NULL if there is none.
 
2253
         *
 
2254
         * Emitted when the background of @applet has changed.
 
2255
         **/
1983
2256
        panel_applet_signals [CHANGE_BACKGROUND] =
1984
2257
                g_signal_new ("change_background",
1985
2258
                              G_TYPE_FROM_CLASS (klass),
1987
2260
                              G_STRUCT_OFFSET (PanelAppletClass, change_background),
1988
2261
                              NULL,
1989
2262
                              NULL,
1990
 
                              panel_applet_marshal_VOID__ENUM_BOXED_OBJECT,
 
2263
                              g_cclosure_marshal_VOID__BOXED,
1991
2264
                              G_TYPE_NONE,
1992
 
                              3,
1993
 
                              PANEL_TYPE_PANEL_APPLET_BACKGROUND_TYPE,
1994
 
                              GDK_TYPE_COLOR,
1995
 
                              GDK_TYPE_PIXMAP);
 
2265
                              1,
 
2266
                              CAIRO_GOBJECT_TYPE_PATTERN);
1996
2267
 
 
2268
        /**
 
2269
         * PanelApplet::move-focus-out-of-applet: (skip)
 
2270
         * @applet: the #PanelApplet which emitted the signal.
 
2271
         * @direction: the move direction.
 
2272
         *
 
2273
         * Emitted when the focus is moved out of @applet. This is an
 
2274
         * implementation detail.
 
2275
         **/
1997
2276
        panel_applet_signals [MOVE_FOCUS_OUT_OF_APPLET] =
1998
2277
                g_signal_new ("move_focus_out_of_applet",
1999
2278
                              G_TYPE_FROM_CLASS (klass),
2001
2280
                              G_STRUCT_OFFSET (PanelAppletClass, move_focus_out_of_applet),
2002
2281
                              NULL,
2003
2282
                              NULL,
2004
 
                              panel_applet_marshal_VOID__ENUM,
 
2283
                              g_cclosure_marshal_VOID__ENUM,
2005
2284
                              G_TYPE_NONE,
2006
2285
                              1,
2007
2286
                              GTK_TYPE_DIRECTION_TYPE);
2008
2287
 
2009
 
        binding_set = gtk_binding_set_by_class (object_class);
 
2288
        binding_set = gtk_binding_set_by_class (gobject_class);
2010
2289
        add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
2011
2290
        add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
2012
2291
        add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
2013
2292
        add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
2014
2293
}
2015
2294
 
2016
 
GtkWidget *
2017
 
panel_applet_new (void)
2018
 
{
2019
 
        PanelApplet *applet;
2020
 
 
2021
 
        applet = g_object_new (PANEL_TYPE_APPLET, NULL);
2022
 
 
2023
 
        return GTK_WIDGET (applet);
2024
 
}
2025
 
 
2026
2295
static void
2027
2296
method_call_cb (GDBusConnection       *connection,
2028
2297
                const gchar           *sender,
2043
2312
                panel_applet_menu_popup (applet, button, time);
2044
2313
 
2045
2314
                g_dbus_method_invocation_return_value (invocation, NULL);
 
2315
        } else if (g_strcmp0 (method_name, "PopupEditMenu") == 0) {
 
2316
                guint button;
 
2317
                guint time;
 
2318
 
 
2319
                g_variant_get (parameters, "(uu)", &button, &time);
 
2320
                panel_applet_edit_menu_popup (applet, button, time);
 
2321
 
 
2322
                g_dbus_method_invocation_return_value (invocation, NULL);
2046
2323
        }
2047
2324
}
2048
2325
 
2058
2335
        PanelApplet *applet = PANEL_APPLET (user_data);
2059
2336
        GVariant    *retval = NULL;
2060
2337
 
2061
 
        if (g_strcmp0 (property_name, "PrefsKey") == 0) {
 
2338
        if (g_strcmp0 (property_name, "SettingsPath") == 0) {
 
2339
                retval = g_variant_new_string (applet->priv->settings_path ?
 
2340
                                               applet->priv->settings_path : "");
 
2341
        } else if (g_strcmp0 (property_name, "PrefsKey") == 0) {
2062
2342
                retval = g_variant_new_string (applet->priv->prefs_key ?
2063
2343
                                               applet->priv->prefs_key : "");
2064
2344
        } else if (g_strcmp0 (property_name, "Orient") == 0) {
2080
2360
                retval = g_variant_new_array (G_VARIANT_TYPE_INT32,
2081
2361
                                              children, applet->priv->size_hints_len);
2082
2362
                g_free (children);
2083
 
        } else if (g_strcmp0 (property_name, "Locked") == 0) {
2084
 
                retval = g_variant_new_boolean (applet->priv->locked);
2085
2363
        } else if (g_strcmp0 (property_name, "LockedDown") == 0) {
2086
2364
                retval = g_variant_new_boolean (applet->priv->locked_down);
2087
2365
        }
2101
2379
{
2102
2380
        PanelApplet *applet = PANEL_APPLET (user_data);
2103
2381
 
2104
 
        if (g_strcmp0 (property_name, "PrefsKey") == 0) {
 
2382
        if (g_strcmp0 (property_name, "SettingsPath") == 0) {
 
2383
                panel_applet_set_settings_path (applet, g_variant_get_string (value, NULL));
 
2384
        } else if (g_strcmp0 (property_name, "PrefsKey") == 0) {
2105
2385
                panel_applet_set_preferences_key (applet, g_variant_get_string (value, NULL));
2106
2386
        } else if (g_strcmp0 (property_name, "Orient") == 0) {
2107
2387
                panel_applet_set_orient (applet, g_variant_get_uint32 (value));
2117
2397
 
2118
2398
                size_hints = g_variant_get_fixed_array (value, &n_elements, sizeof (gint32));
2119
2399
                panel_applet_set_size_hints (applet, size_hints, n_elements, 0);
2120
 
        } else if (g_strcmp0 (property_name, "Locked") == 0) {
2121
 
                panel_applet_set_locked (applet, g_variant_get_boolean (value));
2122
2400
        } else if (g_strcmp0 (property_name, "LockedDown") == 0) {
2123
2401
                panel_applet_set_locked_down (applet, g_variant_get_boolean (value));
2124
2402
        }
2133
2411
              "<arg name='button' type='u' direction='in'/>"
2134
2412
              "<arg name='time' type='u' direction='in'/>"
2135
2413
            "</method>"
 
2414
            "<method name='PopupEditMenu'>"
 
2415
              "<arg name='button' type='u' direction='in'/>"
 
2416
              "<arg name='time' type='u' direction='in'/>"
 
2417
            "</method>"
 
2418
            "<property name='SettingsPath' type='s' access='readwrite'/>"
2136
2419
            "<property name='PrefsKey' type='s' access='readwrite'/>"
2137
2420
            "<property name='Orient' type='u' access='readwrite' />"
2138
2421
            "<property name='Size' type='u' access='readwrite'/>"
2139
2422
            "<property name='Background' type='s' access='readwrite'/>"
2140
2423
            "<property name='Flags' type='u' access='readwrite'/>"
2141
2424
            "<property name='SizeHints' type='ai' access='readwrite'/>"
2142
 
            "<property name='Locked' type='b' access='readwrite'/>"
2143
2425
            "<property name='LockedDown' type='b' access='readwrite'/>"
2144
2426
            "<signal name='Move' />"
2145
2427
            "<signal name='RemoveFromPanel' />"
2146
 
            "<signal name='Lock' />"
2147
 
            "<signal name='Unlock' />"
2148
2428
          "</interface>"
2149
2429
        "</node>";
2150
2430
 
2240
2520
        _x_error_func = XSetErrorHandler (_x_error_handler);
2241
2521
}
2242
2522
 
2243
 
/**
2244
 
 * panel_applet_factory_main:
2245
 
 * @factory_id: Factory ID.
2246
 
 * @out_process: If the factory is on a separate process or not.
2247
 
 * @applet_type: GType of the applet this factory creates.
2248
 
 * @callback: (scope call): Callback to be called when a new applet is to be created.
2249
 
 * @data: (closure): Callback data.
2250
 
 *
2251
 
 * Returns: 0 on success, 1 if there is an error.
2252
 
 */
2253
 
int
2254
 
panel_applet_factory_main (const gchar               *factory_id,
2255
 
                           gboolean                   out_process,
2256
 
                           GType                      applet_type,
2257
 
                           PanelAppletFactoryCallback callback,
2258
 
                           gpointer                   user_data)
 
2523
static int
 
2524
_panel_applet_factory_main_internal (const gchar               *factory_id,
 
2525
                                     gboolean                   out_process,
 
2526
                                     GType                      applet_type,
 
2527
                                     PanelAppletFactoryCallback callback,
 
2528
                                     gpointer                   user_data)
2259
2529
{
2260
2530
        PanelAppletFactory *factory;
2261
2531
        GClosure           *closure;
2287
2557
        return 1;
2288
2558
}
2289
2559
 
 
2560
/**
 
2561
 * panel_applet_factory_main:
 
2562
 * @factory_id: identifier of an applet factory.
 
2563
 * @applet_type: GType of the applet this factory creates.
 
2564
 * @callback: (scope call): callback to be called when a new applet is created.
 
2565
 * @data: (closure): callback data.
 
2566
 *
 
2567
 * Creates the applet factory for @factory_id, so that the factory can create
 
2568
 * instances of the applet types it is associated with.
 
2569
 *
 
2570
 * Applet instances created by the applet factory will use @applet_type as
 
2571
 * GType. Unless you subclass #PanelApplet, you should use %PANEL_TYPE_APPLET
 
2572
 * as @applet_type.
 
2573
 *
 
2574
 * On creation of the applet instances, @callback is called to setup the
 
2575
 * applet. If @callback returns %FALSE, the creation of the applet instance is
 
2576
 * cancelled.
 
2577
 *
 
2578
 * If using C, it is recommended to use #PANEL_APPLET_OUT_PROCESS_FACTORY
 
2579
 * instead as it will create a main() function for you.
 
2580
 *
 
2581
 * It can only be used once, and is incompatible with the use of
 
2582
 * %PANEL_APPLET_IN_PROCESS_FACTORY and %PANEL_APPLET_OUT_PROCESS_FACTORY.
 
2583
 *
 
2584
 * Returns: 0 on success, 1 if there is an error.
 
2585
 **/
 
2586
int
 
2587
panel_applet_factory_main (const gchar               *factory_id,
 
2588
                           GType                      applet_type,
 
2589
                           PanelAppletFactoryCallback callback,
 
2590
                           gpointer                   data)
 
2591
{
 
2592
        return _panel_applet_factory_main_internal (factory_id, TRUE, applet_type,
 
2593
                                                    callback, data);
 
2594
}
 
2595
 
 
2596
/**
 
2597
 * panel_applet_factory_setup_in_process: (skip)
 
2598
 * @factory_id: identifier of an applet factory.
 
2599
 * @applet_type: GType of the applet this factory creates.
 
2600
 * @callback: (scope call): callback to be called when a new applet is created.
 
2601
 * @data: (closure): callback data.
 
2602
 *
 
2603
 * Creates the applet factory for @factory_id, so that the factory can create
 
2604
 * instances of the applet types it is associated with.
 
2605
 *
 
2606
 * Applet instances created by the applet factory will use @applet_type as
 
2607
 * GType. Unless you subclass #PanelApplet, you should use %PANEL_TYPE_APPLET
 
2608
 * as @applet_type.
 
2609
 *
 
2610
 * On creation of the applet instances, @callback is called to setup the
 
2611
 * applet. If @callback returns %FALSE, the creation of the applet instance is
 
2612
 * cancelled.
 
2613
 *
 
2614
 * It can only be used once, and is incompatible with the use of
 
2615
 * %PANEL_APPLET_IN_PROCESS_FACTORY and %PANEL_APPLET_OUT_PROCESS_FACTORY.
 
2616
 *
 
2617
 * Returns: 0 on success, 1 if there is an error.
 
2618
 **/
 
2619
int
 
2620
panel_applet_factory_setup_in_process (const gchar               *factory_id,
 
2621
                                       GType                      applet_type,
 
2622
                                       PanelAppletFactoryCallback callback,
 
2623
                                       gpointer                   data)
 
2624
{
 
2625
        return _panel_applet_factory_main_internal (factory_id, FALSE, applet_type,
 
2626
                                                    callback, data);
 
2627
}
 
2628
 
 
2629
/**
 
2630
 * panel_applet_set_background_widget:
 
2631
 * @applet: a #PanelApplet.
 
2632
 * @widget: a #GtkWidget.
 
2633
 *
 
2634
 * Configure #PanelApplet to automatically draw the background of the applet on
 
2635
 * @widget. It is generally enough to call this function with @applet as
 
2636
 * @widget.
 
2637
 **/
2290
2638
void
2291
2639
panel_applet_set_background_widget (PanelApplet *applet,
2292
2640
                                    GtkWidget   *widget)
2293
2641
{
2294
2642
        applet->priv->background_widget = widget;
2295
2643
 
2296
 
        if (widget) {
2297
 
                PanelAppletBackgroundType  type;
2298
 
                GdkColor                   color;
2299
 
                GdkPixmap                 *pixmap;
 
2644
        if (widget && gtk_widget_get_realized (widget)) {
 
2645
                cairo_pattern_t *pattern;
2300
2646
 
2301
 
                type = panel_applet_get_background (applet, &color, &pixmap);
2302
 
                panel_applet_update_background_for_widget (widget, type,
2303
 
                                                           &color, pixmap);
2304
 
                if (type == PANEL_PIXMAP_BACKGROUND)
2305
 
                        g_object_unref (pixmap);
 
2647
                pattern = panel_applet_get_background (applet);
 
2648
                panel_applet_update_background_for_widget (widget, pattern);
 
2649
                if (pattern)
 
2650
                        cairo_pattern_destroy (pattern);
2306
2651
        }
2307
2652
}
2308
2653