1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3
* panel-applet-frame-bonobo.c: panel side container for applets
5
* Copyright (C) 2001 - 2003 Sun Microsystems, Inc.
6
* Copyright (C) 2010 Vincent Untz <vuntz@gnome.org>
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2 of the
11
* License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24
* Mark McLoughlin <mark@skynet.ie>
31
#include <libbonoboui.h>
33
#include <panel-applet-frame.h>
34
#include <panel-applets-manager.h>
36
#include "GNOME_Panel.h"
38
#include "panel-applet-frame-bonobo.h"
40
G_DEFINE_TYPE (PanelAppletFrameBonobo,
41
panel_applet_frame_bonobo,
42
PANEL_TYPE_APPLET_FRAME)
44
struct _PanelAppletFrameBonoboPrivate
46
GNOME_Vertigo_PanelAppletShell applet_shell;
48
Bonobo_PropertyBag property_bag;
49
BonoboUIComponent *ui_component;
52
#define PROPERTY_ORIENT "panel-applet-orient"
53
#define PROPERTY_SIZE "panel-applet-size"
54
#define PROPERTY_BACKGROUND "panel-applet-background"
55
#define PROPERTY_FLAGS "panel-applet-flags"
56
#define PROPERTY_SIZE_HINTS "panel-applet-size-hints"
57
#define PROPERTY_LOCKED_DOWN "panel-applet-locked-down"
60
PANEL_SIZE_XX_SMALL = GNOME_Vertigo_PANEL_XX_SMALL,
61
PANEL_SIZE_X_SMALL = GNOME_Vertigo_PANEL_X_SMALL,
62
PANEL_SIZE_SMALL = GNOME_Vertigo_PANEL_SMALL,
63
PANEL_SIZE_MEDIUM = GNOME_Vertigo_PANEL_MEDIUM,
64
PANEL_SIZE_LARGE = GNOME_Vertigo_PANEL_LARGE,
65
PANEL_SIZE_X_LARGE = GNOME_Vertigo_PANEL_X_LARGE,
66
PANEL_SIZE_XX_LARGE = GNOME_Vertigo_PANEL_XX_LARGE
69
/* Keep in sync with panel-applet.h. Uggh. */
71
APPLET_FLAGS_NONE = 0,
72
APPLET_EXPAND_MAJOR = 1 << 0,
73
APPLET_EXPAND_MINOR = 1 << 1,
74
APPLET_HAS_HANDLE = 1 << 2
78
panel_applet_frame_bonobo_error_quark (void)
80
static GQuark ret = 0;
83
ret = g_quark_from_static_string ("panel_applet_frame_bonobo_error");
90
get_panel_applet_orient (PanelOrientation orientation)
92
/* For some reason libpanel-applet and panel use a different logic for
93
* orientation, so we need to convert it. We should fix this. */
94
switch (orientation) {
95
case PANEL_ORIENTATION_TOP:
97
case PANEL_ORIENTATION_BOTTOM:
99
case PANEL_ORIENTATION_LEFT:
101
case PANEL_ORIENTATION_RIGHT:
104
g_assert_not_reached ();
110
panel_applet_frame_bonobo_update_flags (PanelAppletFrame *frame,
111
const CORBA_any *any)
118
flags = BONOBO_ARG_GET_SHORT (any);
120
major = (flags & APPLET_EXPAND_MAJOR) != 0;
121
minor = (flags & APPLET_EXPAND_MINOR) != 0;
122
has_handle = (flags & APPLET_HAS_HANDLE) != 0;
124
_panel_applet_frame_update_flags (frame, major, minor, has_handle);
128
panel_applet_frame_bonobo_update_size_hints (PanelAppletFrame *frame,
129
const CORBA_any *any)
131
CORBA_sequence_CORBA_long *seq;
135
_panel_applet_frame_update_size_hints (frame, seq->_buffer, seq->_length);
139
panel_applet_frame_bonobo_init_properties (PanelAppletFrame *frame)
141
PanelAppletFrameBonobo *bonobo_frame = PANEL_APPLET_FRAME_BONOBO (frame);
144
any = bonobo_pbclient_get_value (bonobo_frame->priv->property_bag,
149
panel_applet_frame_bonobo_update_flags (frame, any);
153
any = bonobo_pbclient_get_value (bonobo_frame->priv->property_bag,
155
TC_CORBA_sequence_CORBA_long,
158
panel_applet_frame_bonobo_update_size_hints (frame, any);
164
panel_applet_frame_bonobo_sync_menu_state (PanelAppletFrame *frame,
169
gboolean locked_down)
171
PanelAppletFrameBonobo *bonobo_frame = PANEL_APPLET_FRAME_BONOBO (frame);
173
bonobo_ui_component_set_prop (bonobo_frame->priv->ui_component,
174
"/commands/LockAppletToPanel",
179
/* First sensitivity */
180
bonobo_ui_component_set_prop (bonobo_frame->priv->ui_component,
181
"/commands/LockAppletToPanel",
183
lockable ? "1" : "0",
186
bonobo_ui_component_set_prop (bonobo_frame->priv->ui_component,
187
"/commands/RemoveAppletFromPanel",
189
(locked && !lockable) ? "0" : (removable ? "1" : "0"),
192
bonobo_ui_component_set_prop (bonobo_frame->priv->ui_component,
193
"/commands/MoveApplet",
195
locked ? "0" : (movable ? "1" : "0"),
198
bonobo_ui_component_set_prop (bonobo_frame->priv->ui_component,
199
"/commands/LockAppletToPanel",
201
locked_down ? "1" : "0",
204
bonobo_ui_component_set_prop (bonobo_frame->priv->ui_component,
205
"/commands/LockSeparator",
207
locked_down ? "1" : "0",
210
bonobo_ui_component_set_prop (bonobo_frame->priv->ui_component,
211
"/commands/RemoveAppletFromPanel",
213
locked_down ? "1" : "0",
216
bonobo_ui_component_set_prop (bonobo_frame->priv->ui_component,
217
"/commands/MoveApplet",
219
locked_down ? "1" : "0",
224
panel_applet_frame_bonobo_popup_menu (PanelAppletFrame *frame,
228
PanelAppletFrameBonobo *bonobo_frame = PANEL_APPLET_FRAME_BONOBO (frame);
229
CORBA_Environment env;
231
CORBA_exception_init (&env);
233
GNOME_Vertigo_PanelAppletShell_popup_menu (bonobo_frame->priv->applet_shell,
234
button, timestamp, &env);
235
if (BONOBO_EX (&env))
236
g_warning ("Exception from popup_menu '%s'\n", env._id);
238
CORBA_exception_free (&env);
242
panel_applet_frame_bonobo_change_orientation (PanelAppletFrame *frame,
243
PanelOrientation orientation)
245
PanelAppletFrameBonobo *bonobo_frame = PANEL_APPLET_FRAME_BONOBO (frame);
246
CORBA_unsigned_short orient = 0;
248
switch (orientation) {
249
case PANEL_ORIENTATION_TOP:
250
orient = GNOME_Vertigo_PANEL_ORIENT_DOWN;
252
case PANEL_ORIENTATION_BOTTOM:
253
orient = GNOME_Vertigo_PANEL_ORIENT_UP;
255
case PANEL_ORIENTATION_LEFT:
256
orient = GNOME_Vertigo_PANEL_ORIENT_RIGHT;
258
case PANEL_ORIENTATION_RIGHT:
259
orient = GNOME_Vertigo_PANEL_ORIENT_LEFT;
262
g_assert_not_reached ();
266
bonobo_pbclient_set_short (bonobo_frame->priv->property_bag,
271
gtk_widget_queue_resize (GTK_WIDGET (frame));
275
panel_applet_frame_bonobo_change_size (PanelAppletFrame *frame,
278
PanelAppletFrameBonobo *bonobo_frame = PANEL_APPLET_FRAME_BONOBO (frame);
280
/* Normalise the size to the constants defined in the IDL. */
281
size = size <= PANEL_SIZE_XX_SMALL ? PANEL_SIZE_XX_SMALL :
282
size <= PANEL_SIZE_X_SMALL ? PANEL_SIZE_X_SMALL :
283
size <= PANEL_SIZE_SMALL ? PANEL_SIZE_SMALL :
284
size <= PANEL_SIZE_MEDIUM ? PANEL_SIZE_MEDIUM :
285
size <= PANEL_SIZE_LARGE ? PANEL_SIZE_LARGE :
286
size <= PANEL_SIZE_X_LARGE ? PANEL_SIZE_X_LARGE : PANEL_SIZE_XX_LARGE;
288
bonobo_pbclient_set_short (bonobo_frame->priv->property_bag,
295
panel_applet_frame_bonobo_change_background (PanelAppletFrame *frame,
296
PanelBackgroundType type)
298
PanelAppletFrameBonobo *bonobo_frame = PANEL_APPLET_FRAME_BONOBO (frame);
301
bg_str = _panel_applet_frame_get_background_string (
302
frame, PANEL_WIDGET (GTK_WIDGET (frame)->parent), type);
304
if (bg_str != NULL) {
305
bonobo_pbclient_set_string (bonobo_frame->priv->property_bag,
314
panel_applet_frame_bonobo_applet_broken (ORBitConnection *cnx,
315
PanelAppletFrame *frame)
317
_panel_applet_frame_applet_broken (frame);
321
popup_handle_remove (BonoboUIComponent *uic,
322
PanelAppletFrame *frame,
323
const gchar *verbname)
325
_panel_applet_frame_applet_remove (frame);
329
popup_handle_move (BonoboUIComponent *uic,
330
PanelAppletFrame *frame,
331
const gchar *verbname)
333
_panel_applet_frame_applet_move (frame);
337
listener_popup_handle_lock (BonoboUIComponent *uic,
339
Bonobo_UIComponent_EventType type,
343
PanelAppletFrame *frame;
346
g_assert (!strcmp (path, "LockAppletToPanel"));
348
if (type != Bonobo_UIComponent_STATE_CHANGED)
354
frame = (PanelAppletFrame *) data;
355
locked = (strcmp (state, "1") == 0);
357
_panel_applet_frame_applet_lock (frame, locked);
359
panel_applet_frame_sync_menu_state (frame);
362
static BonoboUIVerb popup_verbs [] = {
363
BONOBO_UI_UNSAFE_VERB ("RemoveAppletFromPanel", popup_handle_remove),
364
BONOBO_UI_UNSAFE_VERB ("MoveApplet", popup_handle_move),
371
panel_applet_frame_bonobo_finalize (GObject *object)
373
PanelAppletFrameBonobo *frame = PANEL_APPLET_FRAME_BONOBO (object);
375
if (frame->priv->control) {
376
/* do this before unref'ing every bonobo stuff since it looks
377
* like we can receive some events when unref'ing them */
378
ORBit_small_unlisten_for_broken (frame->priv->control,
379
G_CALLBACK (panel_applet_frame_bonobo_applet_broken));
380
bonobo_object_release_unref (frame->priv->control, NULL);
381
frame->priv->control = CORBA_OBJECT_NIL;
384
if (frame->priv->property_bag)
385
bonobo_object_release_unref (
386
frame->priv->property_bag, NULL);
388
if (frame->priv->applet_shell)
389
bonobo_object_release_unref (
390
frame->priv->applet_shell, NULL);
392
if (frame->priv->ui_component)
393
bonobo_object_unref (
394
BONOBO_OBJECT (frame->priv->ui_component));
396
G_OBJECT_CLASS (panel_applet_frame_bonobo_parent_class)->finalize (object);
400
panel_applet_frame_bonobo_init (PanelAppletFrameBonobo *frame)
402
GtkWidget *container;
404
frame->priv = G_TYPE_INSTANCE_GET_PRIVATE (frame,
405
PANEL_TYPE_APPLET_FRAME_BONOBO,
406
PanelAppletFrameBonoboPrivate);
408
frame->priv->applet_shell = CORBA_OBJECT_NIL;
409
frame->priv->control = CORBA_OBJECT_NIL;
410
frame->priv->property_bag = CORBA_OBJECT_NIL;
411
frame->priv->ui_component = NULL;
415
panel_applet_frame_bonobo_class_init (PanelAppletFrameBonoboClass *class)
417
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
418
PanelAppletFrameClass *frame_class = PANEL_APPLET_FRAME_CLASS (class);
420
gobject_class->finalize = panel_applet_frame_bonobo_finalize;
422
frame_class->init_properties = panel_applet_frame_bonobo_init_properties;
423
frame_class->sync_menu_state = panel_applet_frame_bonobo_sync_menu_state;
424
frame_class->popup_menu = panel_applet_frame_bonobo_popup_menu;
425
frame_class->change_orientation = panel_applet_frame_bonobo_change_orientation;
426
frame_class->change_size = panel_applet_frame_bonobo_change_size;
427
frame_class->change_background = panel_applet_frame_bonobo_change_background;
429
g_type_class_add_private (class, sizeof (PanelAppletFrameBonoboPrivate));
432
static GNOME_Vertigo_PanelAppletShell
433
panel_applet_frame_get_applet_shell (Bonobo_Control control)
435
CORBA_Environment env;
436
GNOME_Vertigo_PanelAppletShell retval;
438
CORBA_exception_init (&env);
440
retval = Bonobo_Unknown_queryInterface (control,
441
"IDL:GNOME/Vertigo/PanelAppletShell:1.0",
443
if (BONOBO_EX (&env)) {
444
g_warning ("Unable to obtain AppletShell interface from control\n");
446
retval = CORBA_OBJECT_NIL;
449
CORBA_exception_free (&env);
454
static G_CONST_RETURN char *
455
panel_applet_frame_get_orient_string (PanelAppletFrame *frame,
456
PanelAppletFrameActivating *frame_act)
458
PanelOrientation orientation;
459
const char *retval = NULL;
461
orientation = panel_applet_frame_activating_get_orientation (frame_act);
463
switch (orientation) {
464
case PANEL_ORIENTATION_TOP:
467
case PANEL_ORIENTATION_BOTTOM:
470
case PANEL_ORIENTATION_LEFT:
473
case PANEL_ORIENTATION_RIGHT:
477
g_assert_not_reached ();
484
static G_CONST_RETURN char *
485
panel_applet_frame_get_size_string (PanelAppletFrame *frame,
486
PanelAppletFrameActivating *frame_act)
488
const char *retval = NULL;
491
size = panel_applet_frame_activating_get_size (frame_act);
493
if (size <= PANEL_SIZE_XX_SMALL)
495
else if (size <= PANEL_SIZE_X_SMALL)
497
else if (size <= PANEL_SIZE_SMALL)
499
else if (size <= PANEL_SIZE_MEDIUM)
501
else if (size <= PANEL_SIZE_LARGE)
503
else if (size <= PANEL_SIZE_X_LARGE)
512
panel_applet_frame_construct_item (PanelAppletFrame *frame,
513
PanelAppletFrameActivating *frame_act)
516
char *conf_path = NULL;
518
gboolean locked_down;
520
conf_path = panel_applet_frame_activating_get_conf_path (frame_act);
523
bg_str = _panel_applet_frame_get_background_string (
524
frame, panel, panel->background.type);
528
bg_str = g_strdup ("");
530
locked_down = panel_applet_frame_activating_get_locked_down (frame_act);
532
retval = g_strdup_printf (
534
"background=%s;orient=%s;size=%s;locked_down=%s",
536
panel_applet_frame_get_orient_string (frame, frame_act),
537
panel_applet_frame_get_size_string (frame, frame_act),
538
locked_down ? "true" : "false");
547
panel_applet_frame_event_listener (BonoboListener *listener,
549
const CORBA_any *any,
550
CORBA_Environment *ev,
551
PanelAppletFrame *frame)
553
if (!strcmp (event, "Bonobo/Property:change:" PROPERTY_FLAGS))
554
panel_applet_frame_bonobo_update_flags (frame, any);
556
else if (!strcmp (event, "Bonobo/Property:change:" PROPERTY_SIZE_HINTS))
557
panel_applet_frame_bonobo_update_size_hints (frame, any);
561
panel_applet_frame_bonobo_activated (CORBA_Object object,
562
const char *error_reason,
565
PanelAppletFrameActivating *frame_act;
566
PanelAppletFrameBonobo *bonobo_frame;
567
PanelAppletFrame *frame;
569
BonoboControlFrame *control_frame;
570
Bonobo_Control control;
571
Bonobo_ItemContainer container;
572
CORBA_Environment corba_ev;
576
GError *gerror = NULL;
579
bonobo_frame = PANEL_APPLET_FRAME_BONOBO (data);
580
frame = PANEL_APPLET_FRAME (data);
581
frame_act = g_object_get_data (G_OBJECT (frame), "panel-applet-frame-activating");
582
g_object_set_data (G_OBJECT (frame), "panel-applet-frame-activating", NULL);
584
/* according to the source of bonobo control == NULL && no
585
exception can happen, so handle it */
586
if (error_reason != NULL || object == CORBA_OBJECT_NIL) {
587
gerror = g_error_new_literal (panel_applet_frame_bonobo_error_quark (), 0, error_reason);
591
CORBA_exception_init (&corba_ev);
593
item_name = panel_applet_frame_construct_item (frame,
596
bonobo_frame->priv->control = CORBA_OBJECT_NIL;
597
container = Bonobo_Unknown_queryInterface (object,
598
"IDL:Bonobo/ItemContainer:1.0",
600
if (!BONOBO_EX (&corba_ev) && container != CORBA_OBJECT_NIL) {
601
Bonobo_Unknown containee;
603
containee = Bonobo_ItemContainer_getObjectByName (container,
607
bonobo_object_release_unref (container, NULL);
609
if (!BONOBO_EX (&corba_ev) && containee != CORBA_OBJECT_NIL) {
610
bonobo_frame->priv->control =
611
Bonobo_Unknown_queryInterface (containee,
612
"IDL:Bonobo/Control:1.0",
615
bonobo_object_release_unref (containee, NULL);
620
if (bonobo_frame->priv->control == CORBA_OBJECT_NIL) {
621
error = bonobo_exception_get_text (&corba_ev);
622
gerror = g_error_new (panel_applet_frame_bonobo_error_quark (), 0, "failed to get Bonobo/Control interface:\n", error);
623
CORBA_exception_free (&corba_ev);
624
bonobo_object_release_unref (object, NULL);
629
widget = bonobo_widget_new_control_from_objref (bonobo_frame->priv->control,
632
CORBA_exception_free (&corba_ev);
633
bonobo_object_release_unref (object, NULL);
636
gerror = g_error_new_literal (panel_applet_frame_bonobo_error_quark (), 0, "no widget created");
640
control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (widget));
641
if (control_frame == NULL) {
642
gerror = g_error_new_literal (panel_applet_frame_bonobo_error_quark (), 0, "cannot get control frame");
646
bonobo_frame->priv->property_bag =
647
bonobo_control_frame_get_control_property_bag (control_frame,
649
if (bonobo_frame->priv->property_bag == NULL || BONOBO_EX (&corba_ev)) {
650
error = bonobo_exception_get_text (&corba_ev);
651
CORBA_exception_free (&corba_ev);
652
gerror = g_error_new (panel_applet_frame_bonobo_error_quark (), 0, "cannot get property bag frame:\n%s", error);
657
bonobo_event_source_client_add_listener (bonobo_frame->priv->property_bag,
658
(BonoboListenerCallbackFn) panel_applet_frame_event_listener,
659
"Bonobo/Property:change:panel-applet",
663
bonobo_frame->priv->ui_component =
664
bonobo_control_frame_get_popup_component (control_frame,
666
if (bonobo_frame->priv->ui_component == NULL || BONOBO_EX (&corba_ev)) {
667
error = bonobo_exception_get_text (&corba_ev);
668
CORBA_exception_free (&corba_ev);
669
gerror = g_error_new (panel_applet_frame_bonobo_error_quark (), 0, "cannot get popup component:\n%s", error);
674
bonobo_ui_util_set_ui (bonobo_frame->priv->ui_component, DATADIR,
675
"GNOME_Panel_Popup.xml", "panel", NULL);
677
bonobo_ui_component_add_listener (bonobo_frame->priv->ui_component,
679
listener_popup_handle_lock,
682
bonobo_ui_component_add_verb_list_with_data (
683
bonobo_frame->priv->ui_component, popup_verbs, frame);
685
control = bonobo_control_frame_get_control (control_frame);
687
CORBA_exception_free (&corba_ev);
688
gerror = g_error_new_literal (panel_applet_frame_bonobo_error_quark (), 0, "cannot get control");
692
bonobo_frame->priv->applet_shell = panel_applet_frame_get_applet_shell (control);
693
if (bonobo_frame->priv->applet_shell == CORBA_OBJECT_NIL) {
694
CORBA_exception_free (&corba_ev);
695
gerror = g_error_new_literal (panel_applet_frame_bonobo_error_quark (), 0, "cannot get applet shell");
699
CORBA_exception_free (&corba_ev);
701
ORBit_small_listen_for_broken (object,
702
G_CALLBACK (panel_applet_frame_bonobo_applet_broken),
705
gtk_container_add (GTK_CONTAINER (frame), widget);
711
g_object_unref (widget);
713
gerror = g_error_new_literal (panel_applet_frame_bonobo_error_quark (), 0, "unknown error");
716
_panel_applet_frame_activated (frame, frame_act, gerror);
720
panel_applet_frame_bonobo_load (const gchar *iid,
721
PanelAppletFrameActivating *frame_act)
723
PanelAppletFrameBonobo *bonobo_frame;
724
PanelAppletFrame *frame;
725
CORBA_Environment ev;
727
g_return_val_if_fail (iid != NULL, FALSE);
728
g_return_val_if_fail (frame_act != NULL, FALSE);
730
if (!panel_applets_manager_factory_activate (iid))
733
bonobo_frame = g_object_new (PANEL_TYPE_APPLET_FRAME_BONOBO, NULL);
734
frame = PANEL_APPLET_FRAME (bonobo_frame);
735
_panel_applet_frame_set_iid (frame, iid);
737
g_object_set_data (G_OBJECT (frame), "panel-applet-frame-activating", frame_act);
739
CORBA_exception_init (&ev);
741
bonobo_activation_activate_from_id_async ((gchar *) iid, 0,
742
(BonoboActivationCallback) panel_applet_frame_bonobo_activated,
745
CORBA_exception_free (&ev);