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