1 
2 #include "plugin.h"
3 
4 #include <gdk-pixbuf/gdk-pixbuf.h>
5 #include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
6 #include <gdk/gdk.h>
7 #include <string.h>
8 #include <stdlib.h>
9 
10 
11 
12 #include "misc.h"
13 #include "bg.h"
14 #include "gtkbgbox.h"
15 
16 
17 //#define DEBUGPRN
18 #include "dbg.h"
19 extern panel *the_panel;
20 struct _plugin_instance *stam;
21 
22 
23 /**************************************************************/
24 static GHashTable *class_ht;
25 
26 
27 void
class_register(plugin_class * p)28 class_register(plugin_class *p)
29 {
30     ENTER;
31     if (!class_ht) {
32         class_ht = g_hash_table_new(g_str_hash, g_str_equal);
33         DBG("creating class hash table\n");
34     }
35     DBG("registering %s\n", p->type);
36     if (g_hash_table_lookup(class_ht, p->type)) {
37         ERR("Can't register plugin %s. Such name already exists.\n", p->type);
38         exit(1);
39     }
40     p->dynamic = (the_panel != NULL); /* dynamic modules register after main */
41     g_hash_table_insert(class_ht, p->type, p);
42     RET();
43 }
44 
45 void
class_unregister(plugin_class * p)46 class_unregister(plugin_class *p)
47 {
48     ENTER;
49     DBG("unregistering %s\n", p->type);
50     if (!g_hash_table_remove(class_ht, p->type)) {
51         ERR("Can't unregister plugin %s. No such name\n", p->type);
52     }
53     if (!g_hash_table_size(class_ht)) {
54         DBG("dwstroying class hash table\n");
55         g_hash_table_destroy(class_ht);
56         class_ht = NULL;
57     }
58     RET();
59 }
60 
61 void
class_put(char * name)62 class_put(char *name)
63 {
64     GModule *m;
65     gchar *s;
66     plugin_class *tmp;
67 
68     ENTER;
69     DBG("%s\n", name);
70     if (!(class_ht && (tmp = g_hash_table_lookup(class_ht, name))))
71         RET();
72     tmp->count--;
73     if (tmp->count || !tmp->dynamic)
74         RET();
75 
76     s = g_strdup_printf(LIBDIR "/fbpanel/%s.so", name);
77     DBG("loading module %s\n", s);
78     m = g_module_open(s, G_MODULE_BIND_LAZY);
79     g_free(s);
80     if (m) {
81         /* Close it twise to undo initial open in class_get */
82         g_module_close(m);
83         g_module_close(m);
84     }
85     RET();
86 }
87 
88 gpointer
class_get(char * name)89 class_get(char *name)
90 {
91     GModule *m;
92     plugin_class *tmp;
93     gchar *s;
94 
95     ENTER;
96     DBG("%s\n", name);
97     if (class_ht && (tmp = g_hash_table_lookup(class_ht, name))) {
98         DBG("found\n");
99         tmp->count++;
100         RET(tmp);
101     }
102     s = g_strdup_printf(LIBDIR "/fbpanel/%s.so", name);
103     DBG("loading module %s\n", s);
104     m = g_module_open(s, G_MODULE_BIND_LAZY);
105     g_free(s);
106     if (m) {
107         if (class_ht && (tmp = g_hash_table_lookup(class_ht, name))) {
108             DBG("found\n");
109             tmp->count++;
110             RET(tmp);
111         }
112     }
113     RET(NULL);
114 }
115 
116 
117 
118 /**************************************************************/
119 
120 plugin_instance *
plugin_load(char * type)121 plugin_load(char *type)
122 {
123     plugin_class *pc = NULL;
124     plugin_instance  *pp = NULL;
125 
126     ENTER;
127     /* nothing was found */
128     if (!(pc = class_get(type)))
129         RET(NULL);
130 
131     DBG("%s priv_size=%d\n", pc->type, pc->priv_size);
132     pp = g_malloc0(pc->priv_size);
133     g_return_val_if_fail (pp != NULL, NULL);
134     pp->class = pc;
135     RET(pp);
136 }
137 
138 
139 void
plugin_put(plugin_instance * this)140 plugin_put(plugin_instance *this)
141 {
142     gchar *type;
143 
144     ENTER;
145     type = this->class->type;
146     g_free(this);
147     class_put(type);
148     RET();
149 }
150 
151 gboolean panel_button_press_event(GtkWidget *widget, GdkEventButton *event,
152         panel *p);
153 
154 int
plugin_start(plugin_instance * this)155 plugin_start(plugin_instance *this)
156 {
157     ENTER;
158 
159     DBG("%s\n", this->class->type);
160     if (!this->class->invisible) {
161         this->pwid = gtk_bgbox_new();
162         gtk_widget_set_name(this->pwid, this->class->type);
163         gtk_box_pack_start(GTK_BOX(this->panel->box), this->pwid, this->expand,
164                 TRUE, this->padding);
165         DBG("%s expand %d\n", this->class->type, this->expand);
166         gtk_container_set_border_width(GTK_CONTAINER(this->pwid), this->border);
167         DBG("here this->panel->transparent = %d\n", this->panel->transparent);
168         if (this->panel->transparent) {
169             DBG("here g\n");
170             gtk_bgbox_set_background(this->pwid, BG_INHERIT,
171                     this->panel->tintcolor, this->panel->alpha);
172         }
173         DBG("here\n");
174         g_signal_connect (G_OBJECT (this->pwid), "button-press-event",
175               (GCallback) panel_button_press_event, this->panel);
176         gtk_widget_show(this->pwid);
177         DBG("here\n");
178     } else {
179         /* create a no-window widget and do not show it it's usefull to have
180          * unmaped widget for invisible plugins so their indexes in plugin list
181          * are the same as in panel->box. required for children reordering */
182         this->pwid = gtk_vbox_new(TRUE, 0);
183         gtk_box_pack_start(GTK_BOX(this->panel->box), this->pwid, FALSE,
184                 TRUE,0);
185         gtk_widget_hide(this->pwid);
186     }
187     DBG("here\n");
188     if (!this->class->constructor(this)) {
189         DBG("here\n");
190         gtk_widget_destroy(this->pwid);
191         RET(0);
192     }
193     RET(1);
194 }
195 
196 
197 void
plugin_stop(plugin_instance * this)198 plugin_stop(plugin_instance *this)
199 {
200     ENTER;
201     DBG("%s\n", this->class->type);
202     this->class->destructor(this);
203     this->panel->plug_num--;
204     gtk_widget_destroy(this->pwid);
205     RET();
206 }
207 
208 
209 GtkWidget *
default_plugin_edit_config(plugin_instance * pl)210 default_plugin_edit_config(plugin_instance *pl)
211 {
212     GtkWidget *vbox, *label;
213     gchar *msg;
214 
215     ENTER;
216     vbox = gtk_vbox_new(FALSE, 0);
217     /* XXX: harcoded default profile name */
218     msg = g_strdup_printf("Graphical '%s' plugin configuration\n is not "
219           "implemented yet.\n"
220           "Please edit manually\n\t~/.config/fbpanel/default\n\n"
221           "You can use as example files in \n\t%s/share/fbpanel/\n"
222           "or visit\n"
223           "\thttp://fbpanel.sourceforge.net/docs.html", pl->class->name,
224           PREFIX);
225     label = gtk_label_new(msg);
226     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
227     gtk_label_set_selectable(GTK_LABEL(label), TRUE);
228     gtk_box_pack_end(GTK_BOX(vbox), label, TRUE, TRUE, 5);
229     gtk_container_set_border_width(GTK_CONTAINER(vbox), 14);
230     g_free(msg);
231 
232     RET(vbox);
233 }
234