Change default settings.
[lxde/lxpanel.git] / src / panel.c
CommitLineData
a52c2257
HJYP
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <unistd.h>
10#include <errno.h>
11#include <locale.h>
12#include <string.h>
13#include <signal.h>
e7cb732b 14#include <glib/gi18n.h>
a52c2257
HJYP
15
16#include "plugin.h"
17#include "panel.h"
18#include "misc.h"
19#include "bg.h"
20#include "gtkbgbox.h"
21
22static gchar *cfgfile = NULL;
23static gchar version[] = VERSION;
24gchar *cprofile = "default";
25
26int config = 0;
27FbEv *fbev;
28
29//#define DEBUG
30#include "dbg.h"
31
32int log_level;
33
34FILE *pconf; // plugin part of profile file
35
36panel *p;
37
38
39/****************************************************
40 * panel's handlers for WM events *
41 ****************************************************/
42/*
43static void
44panel_del_wm_strut(panel *p)
45{
46 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT);
47 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL);
48}
49*/
50
51
52static void
53panel_set_wm_strut(panel *p)
54{
55 gulong data[12] = { 0 };
56 int i = 4;
57
58 ENTER;
59 if (!GTK_WIDGET_MAPPED (p->topgwin))
60 return;
61 switch (p->edge) {
62 case EDGE_LEFT:
63 i = 0;
64 data[i] = p->aw;
65 data[4 + i*2] = p->ay;
66 data[5 + i*2] = p->ay + p->ah;
67 break;
68 case EDGE_RIGHT:
69 i = 1;
70 data[i] = p->aw;
71 data[4 + i*2] = p->ay;
72 data[5 + i*2] = p->ay + p->ah;
73 break;
74 case EDGE_TOP:
75 i = 2;
76 data[i] = p->ah;
77 data[4 + i*2] = p->ax;
78 data[5 + i*2] = p->ax + p->aw;
79 break;
80 case EDGE_BOTTOM:
81 i = 3;
82 data[i] = p->ah;
83 data[4 + i*2] = p->ax;
84 data[5 + i*2] = p->ax + p->aw;
85 break;
86 default:
87 ERR("wrong edge %d. strut won't be set\n", p->edge);
88 RET();
89 }
90 DBG("type %d. width %d. from %d to %d\n", i, data[i], data[4 + i*2], data[5 + i*2]);
91
92 /* if wm supports STRUT_PARTIAL it will ignore STRUT */
93 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL,
94 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 12);
95 /* old spec, for wms that do not support STRUT_PARTIAL */
96 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT,
97 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 4);
98
99 RET();
100}
101
102static void
103print_wmdata(panel *p)
104{
105 int i;
106
107 ENTER;
108 RET();
109 DBG("desktop %d/%d\n", p->curdesk, p->desknum);
110 DBG("workarea\n");
111 for (i = 0; i < p->wa_len/4; i++)
112 DBG("(%d, %d) x (%d, %d)\n",
113 p->workarea[4*i + 0],
114 p->workarea[4*i + 1],
115 p->workarea[4*i + 2],
116 p->workarea[4*i + 3]);
117 RET();
118}
119
120
121static GdkFilterReturn
122panel_event_filter(GdkXEvent *xevent, GdkEvent *event, panel *p)
123{
124 Atom at;
125 Window win;
126 XEvent *ev = (XEvent *) xevent;
127
128 ENTER;
129 DBG("win = 0x%x\n", ev->xproperty.window);
130 if (ev->type != PropertyNotify )
131 RET(GDK_FILTER_CONTINUE);
132
133 at = ev->xproperty.atom;
134 win = ev->xproperty.window;
135 DBG("win=%x at=%d\n", win, at);
136 if (win == GDK_ROOT_WINDOW()) {
137 if (at == a_NET_CLIENT_LIST) {
138 DBG("A_NET_CLIENT_LIST\n");
139 fb_ev_trigger(fbev, EV_CLIENT_LIST);
140 } else if (at == a_NET_CURRENT_DESKTOP) {
141 DBG("A_NET_CURRENT_DESKTOP\n");
142 p->curdesk = get_net_current_desktop();
143 fb_ev_trigger(fbev, EV_CURRENT_DESKTOP);
144 } else if (at == a_NET_NUMBER_OF_DESKTOPS) {
145 DBG("A_NET_NUMBER_OF_DESKTOPS\n");
146 p->desknum = get_net_number_of_desktops();
147 fb_ev_trigger(fbev, EV_NUMBER_OF_DESKTOPS);
148 } else if (at == a_NET_DESKTOP_NAMES) {
149 DBG("A_NET_DESKTOP_NAMES\n");
150 fb_ev_trigger(fbev, EV_DESKTOP_NAMES);
151 } else if (at == a_NET_ACTIVE_WINDOW) {
152 DBG("A_NET_ACTIVE_WINDOW\n");
153 fb_ev_trigger(fbev, EV_ACTIVE_WINDOW);
154 }else if (at == a_NET_CLIENT_LIST_STACKING) {
155 DBG("A_NET_CLIENT_LIST_STACKING\n");
156 fb_ev_trigger(fbev, EV_CLIENT_LIST_STACKING);
157 } else if (at == a_XROOTPMAP_ID) {
158 DBG("a_XROOTPMAP_ID\n");
159 if (p->transparent) {
160 fb_bg_notify_changed_bg(p->bg);
161 }
162 } else if (at == a_NET_WORKAREA) {
163 DBG("A_NET_WORKAREA\n");
164 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
165 print_wmdata(p);
166 } else
167 RET(GDK_FILTER_CONTINUE);
168 RET(GDK_FILTER_REMOVE);
169 }
170 DBG("non root %x\n", win);
171 RET(GDK_FILTER_CONTINUE);
172}
173
174/****************************************************
175 * panel's handlers for GTK events *
176 ****************************************************/
177
178
179static gint
180panel_delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
181{
182 ENTER;
183 RET(FALSE);
184}
185
186static gint
187panel_destroy_event(GtkWidget * widget, GdkEvent * event, gpointer data)
188{
189 //panel *p = (panel *) data;
190
191 ENTER;
192 //if (!p->self_destroy)
193 gtk_main_quit();
194 RET(FALSE);
195}
196
197
198static void
199panel_realize(GtkWidget *widget, panel *p)
200{
201 ENTER;
202 RET();
203
204}
205static gint
206panel_size_req(GtkWidget *widget, GtkRequisition *req, panel *p)
207{
208 ENTER;
209 DBG("IN req=(%d, %d)\n", req->width, req->height);
210 if (p->widthtype == WIDTH_REQUEST)
211 p->width = (p->orientation == ORIENT_HORIZ) ? req->width : req->height;
212 if (p->heighttype == HEIGHT_REQUEST)
213 p->height = (p->orientation == ORIENT_HORIZ) ? req->height : req->width;
214 calculate_position(p);
215 req->width = p->aw;
216 req->height = p->ah;
217 DBG("OUT req=(%d, %d)\n", req->width, req->height);
218 RET( TRUE );
219}
220
221static gint
222panel_size_alloc(GtkWidget *widget, GtkAllocation *a, panel *p)
223{
224 ENTER;
225 DBG("installed alloc: size (%d, %d). pos (%d, %d)\n", aa->width, aa->height, aa->x, aa->y);
226 DBG("suggested alloc: size (%d, %d). pos (%d, %d)\n", a->width, a->height, a->x, a->y);
227 DBG("prev pref alloc: size (%d, %d). pos (%d, %d)\n", p->aw, p->ah, p->ax, p->ay);
228 if (p->widthtype == WIDTH_REQUEST)
229 p->width = (p->orientation == ORIENT_HORIZ) ? a->width : a->height;
230 if (p->heighttype == HEIGHT_REQUEST)
231 p->height = (p->orientation == ORIENT_HORIZ) ? a->height : a->width;
232 calculate_position(p);
233 DBG("curr pref alloc: size (%d, %d). pos (%d, %d)\n", p->aw, p->ah, p->ax, p->ay);
234 if (a->width == p->aw && a->height == p->ah && a->x == p->ax && a->y == p ->ay) {
235 DBG("actual coords eq to preffered. just returning\n");
236 RET(TRUE);
237 }
238
239 gtk_window_move(GTK_WINDOW(p->topgwin), p->ax, p->ay);
240 DBG("moving to %d %d\n", p->ax, p->ay);
241 if (p->setstrut)
242 panel_set_wm_strut(p);
243 RET(TRUE);
244}
245
246
247static gboolean
248panel_configure_event (GtkWidget *widget, GdkEventConfigure *e, panel *p)
249{
250 ENTER;
251 if (e->width == p->cw && e->height == p->ch && e->x == p->cx && e->y == p->cy)
252 RET(TRUE);
253 p->cw = e->width;
254 p->ch = e->height;
255 p->cx = e->x;
256 p->cy = e->y;
257 DBG("here\n");
258 if (p->transparent)
259 fb_bg_notify_changed_bg(p->bg);
260 DBG("here\n");
261 DBG("geom: size (%d, %d). pos (%d, %d)\n", e->width, e->height, e->x, e->y);
262 RET(FALSE);
263
264}
265
266
267/****************************************************
268 * panel creation *
269 ****************************************************/
270static void
271make_round_corners(panel *p)
272{
273 GtkWidget *b1, *b2, *img;
274 GtkWidget *(*box_new) (gboolean, gint);
275 void (*box_pack)(GtkBox *, GtkWidget *, gboolean, gboolean, guint);
276 gchar *s1, *s2;
277#define IMGPREFIX PACKAGE_DATA_DIR "/lxpanel/images/"
278
279 ENTER;
280 if (p->edge == EDGE_TOP) {
281 s1 = IMGPREFIX "top-left.xpm";
282 s2 = IMGPREFIX "top-right.xpm";
283 } else if (p->edge == EDGE_BOTTOM) {
284 s1 = IMGPREFIX "bottom-left.xpm";
285 s2 = IMGPREFIX "bottom-right.xpm";
286 } else if (p->edge == EDGE_LEFT) {
287 s1 = IMGPREFIX "top-left.xpm";
288 s2 = IMGPREFIX "bottom-left.xpm";
289 } else if (p->edge == EDGE_RIGHT) {
290 s1 = IMGPREFIX "top-right.xpm";
291 s2 = IMGPREFIX "bottom-right.xpm";
292 } else
293 RET();
294
295 box_new = (p->orientation == ORIENT_HORIZ) ? gtk_vbox_new : gtk_hbox_new;
296 b1 = box_new(0, FALSE);
297 gtk_widget_show(b1);
298 b2 = box_new(0, FALSE);
299 gtk_widget_show(b2);
300
301 box_pack = (p->edge == EDGE_TOP || p->edge == EDGE_LEFT) ?
302 gtk_box_pack_start : gtk_box_pack_end;
303
304 img = gtk_image_new_from_file(s1);
305 gtk_widget_show(img);
306 box_pack(GTK_BOX(b1), img, FALSE, FALSE, 0);
307 img = gtk_image_new_from_file(s2);
308 gtk_widget_show(img);
309 box_pack(GTK_BOX(b2), img, FALSE, FALSE, 0);
310 gtk_box_pack_start(GTK_BOX(p->lbox), b1, FALSE, FALSE, 0);
311 gtk_box_pack_end(GTK_BOX(p->lbox), b2, FALSE, FALSE, 0);
312 RET();
313}
314
315void
316panel_start_gui(panel *p)
317{
318 Atom state[3];
319 XWMHints wmhints;
320 guint32 val;
321
322
323 ENTER;
324
325 // main toplevel window
326 p->topgwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
327 gtk_container_set_border_width(GTK_CONTAINER(p->topgwin), 0);
328 gtk_window_set_resizable(GTK_WINDOW(p->topgwin), FALSE);
329 gtk_window_set_wmclass(GTK_WINDOW(p->topgwin), "panel", "lxpanel");
330 gtk_window_set_title(GTK_WINDOW(p->topgwin), "panel");
331 gtk_window_set_position(GTK_WINDOW(p->topgwin), GTK_WIN_POS_NONE);
332 gtk_window_set_decorated(GTK_WINDOW(p->topgwin), FALSE);
333
334 g_signal_connect(G_OBJECT(p->topgwin), "delete-event",
335 G_CALLBACK(panel_delete_event), p);
336 g_signal_connect(G_OBJECT(p->topgwin), "destroy-event",
337 G_CALLBACK(panel_destroy_event), p);
338 g_signal_connect (G_OBJECT (p->topgwin), "size-request",
339 (GCallback) panel_size_req, p);
340 g_signal_connect (G_OBJECT (p->topgwin), "size-allocate",
341 (GCallback) panel_size_alloc, p);
342 g_signal_connect (G_OBJECT (p->topgwin), "configure-event",
343 (GCallback) panel_configure_event, p);
344 g_signal_connect (G_OBJECT (p->topgwin), "realize",
345 (GCallback) panel_realize, p);
346
347 gtk_widget_realize(p->topgwin);
348 //gdk_window_set_decorations(p->topgwin->window, 0);
349 gtk_widget_set_app_paintable(p->topgwin, TRUE);
350
351 // background box all over toplevel
352 p->bbox = gtk_bgbox_new();
353 gtk_container_add(GTK_CONTAINER(p->topgwin), p->bbox);
354 gtk_widget_show(p->bbox);
355 gtk_container_set_border_width(GTK_CONTAINER(p->bbox), 0);
356 if (p->transparent) {
357 p->bg = fb_bg_get_for_display();
358 gtk_bgbox_set_background(p->bbox, BG_ROOT, p->tintcolor, p->alpha);
359 }
360
361 // main layout manager as a single child of background widget box
362 p->lbox = p->my_box_new(FALSE, 0);
363 gtk_container_set_border_width(GTK_CONTAINER(p->lbox), 0);
364 gtk_container_add(GTK_CONTAINER(p->bbox), p->lbox);
365 gtk_widget_show(p->lbox);
366 if (p->round_corners)
367 make_round_corners(p);
368
369 p->box = p->my_box_new(FALSE, p->spacing);
370 gtk_container_set_border_width(GTK_CONTAINER(p->box), 0);
371 gtk_box_pack_start(GTK_BOX(p->lbox), p->box, TRUE, TRUE, 0);
372 gtk_widget_show(p->box);
373
374 p->topxwin = GDK_WINDOW_XWINDOW(GTK_WIDGET(p->topgwin)->window);
375 DBG("topxwin = %x\n", p->topxwin);
376
377 /* the settings that should be done before window is mapped */
378 wmhints.flags = InputHint;
379 wmhints.input = 0;
380 XSetWMHints (GDK_DISPLAY(), p->topxwin, &wmhints);
381#define WIN_HINTS_SKIP_FOCUS (1<<0) /* "alt-tab" skips this win */
382 val = WIN_HINTS_SKIP_FOCUS;
383 XChangeProperty(GDK_DISPLAY(), p->topxwin,
384 XInternAtom(GDK_DISPLAY(), "_WIN_HINTS", False), XA_CARDINAL, 32,
385 PropModeReplace, (unsigned char *) &val, 1);
386
387 if (p->setdocktype) {
388 state[0] = a_NET_WM_WINDOW_TYPE_DOCK;
389 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_WINDOW_TYPE, XA_ATOM,
390 32, PropModeReplace, (unsigned char *) state, 1);
391 }
392
393 /* window mapping point */
394 gtk_widget_show_all(p->topgwin);
395
396 /* the settings that should be done after window is mapped */
397
398 /* send it to running wm */
399 Xclimsg(p->topxwin, a_NET_WM_DESKTOP, 0xFFFFFFFF, 0, 0, 0, 0);
400 /* and assign it ourself just for case when wm is not running */
401 val = 0xFFFFFFFF;
402 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_DESKTOP, XA_CARDINAL, 32,
403 PropModeReplace, (unsigned char *) &val, 1);
404
405 state[0] = a_NET_WM_STATE_SKIP_PAGER;
406 state[1] = a_NET_WM_STATE_SKIP_TASKBAR;
407 state[2] = a_NET_WM_STATE_STICKY;
408 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STATE, XA_ATOM,
409 32, PropModeReplace, (unsigned char *) state, 3);
410
411 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), PropertyChangeMask);
412 gdk_window_add_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
413
414 calculate_position(p);
415 gdk_window_move_resize(p->topgwin->window, p->ax, p->ay, p->aw, p->ah);
416 if (p->setstrut)
417 panel_set_wm_strut(p);
418
419 RET();
420}
421
422static int
423panel_parse_global(panel *p, FILE *fp)
424{
425 line s;
426 s.len = 256;
427
428 ENTER;
429 while (get_line(fp, &s) != LINE_NONE) {
430 if (s.type == LINE_VAR) {
431 if (!g_ascii_strcasecmp(s.t[0], "edge")) {
432 p->edge = str2num(edge_pair, s.t[1], EDGE_NONE);
433 } else if (!g_ascii_strcasecmp(s.t[0], "allign")) {
434 p->allign = str2num(allign_pair, s.t[1], ALLIGN_NONE);
435 } else if (!g_ascii_strcasecmp(s.t[0], "margin")) {
436 p->margin = atoi(s.t[1]);
437 } else if (!g_ascii_strcasecmp(s.t[0], "widthtype")) {
438 p->widthtype = str2num(width_pair, s.t[1], WIDTH_NONE);
439 } else if (!g_ascii_strcasecmp(s.t[0], "width")) {
440 p->width = atoi(s.t[1]);
441 } else if (!g_ascii_strcasecmp(s.t[0], "heighttype")) {
442 p->heighttype = str2num(height_pair, s.t[1], HEIGHT_NONE);
443 } else if (!g_ascii_strcasecmp(s.t[0], "height")) {
444 p->height = atoi(s.t[1]);
445 } else if (!g_ascii_strcasecmp(s.t[0], "spacing")) {
446 p->spacing = atoi(s.t[1]);
447 } else if (!g_ascii_strcasecmp(s.t[0], "SetDockType")) {
448 p->setdocktype = str2num(bool_pair, s.t[1], 0);
449 } else if (!g_ascii_strcasecmp(s.t[0], "SetPartialStrut")) {
450 p->setstrut = str2num(bool_pair, s.t[1], 0);
451 } else if (!g_ascii_strcasecmp(s.t[0], "RoundCorners")) {
452 p->round_corners = str2num(bool_pair, s.t[1], 0);
453 } else if (!g_ascii_strcasecmp(s.t[0], "Transparent")) {
454 p->transparent = str2num(bool_pair, s.t[1], 0);
455 } else if (!g_ascii_strcasecmp(s.t[0], "Alpha")) {
456 p->alpha = atoi(s.t[1]);
457 if (p->alpha > 255)
458 p->alpha = 255;
459 } else if (!g_ascii_strcasecmp(s.t[0], "TintColor")) {
460 if (!gdk_color_parse (s.t[1], &p->gtintcolor))
461 gdk_color_parse ("white", &p->gtintcolor);
462 p->tintcolor = gcolor2rgb24(&p->gtintcolor);
463 DBG("tintcolor=%x\n", p->tintcolor);
464 } else {
465 ERR( "lxpanel: %s - unknown var in Global section\n", s.t[0]);
466 RET(0);
467 }
468 } else if (s.type == LINE_BLOCK_END) {
469 break;
470 } else {
471 ERR( "lxpanel: illegal in this context %s\n", s.str);
472 RET(0);
473 }
474 }
475 p->orientation = (p->edge == EDGE_TOP || p->edge == EDGE_BOTTOM)
476 ? ORIENT_HORIZ : ORIENT_VERT;
477 if (p->orientation == ORIENT_HORIZ) {
478 p->my_box_new = gtk_hbox_new;
479 p->my_separator_new = gtk_vseparator_new;
480 } else {
481 p->my_box_new = gtk_vbox_new;
482 p->my_separator_new = gtk_hseparator_new;
483 }
484 if (p->width < 0)
485 p->width = 100;
486 if (p->widthtype == WIDTH_PERCENT && p->width > 100)
487 p->width = 100;
488 p->heighttype = HEIGHT_PIXEL;
489 if (p->heighttype == HEIGHT_PIXEL) {
490 if (p->height < PANEL_HEIGHT_MIN)
491 p->height = PANEL_HEIGHT_MIN;
492 else if (p->height > PANEL_HEIGHT_MAX)
493 p->height = PANEL_HEIGHT_MAX;
494 }
495 p->curdesk = get_net_current_desktop();
496 p->desknum = get_net_number_of_desktops();
497 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
498 print_wmdata(p);
499 panel_start_gui(p);
500 RET(1);
501}
502
503static int
504panel_parse_plugin(panel *p, FILE *fp)
505{
506 line s;
507 plugin *plug = NULL;
508 gchar *type = NULL;
509 FILE *tmpfp;
510 int expand , padding, border;
511
512 ENTER;
513 s.len = 256;
514 if (!(tmpfp = tmpfile())) {
515 ERR( "can't open temporary file with tmpfile()\n");
516 RET(0);
517 }
518 border = expand = padding = 0;
519 while (get_line(fp, &s) != LINE_BLOCK_END) {
520 if (s.type == LINE_NONE) {
521 ERR( "lxpanel: bad line %s\n", s.str);
522 goto error;
523 }
524 if (s.type == LINE_VAR) {
525 if (!g_ascii_strcasecmp(s.t[0], "type")) {
526 type = g_strdup(s.t[1]);
527 DBG("plug %s\n", type);
528 } else if (!g_ascii_strcasecmp(s.t[0], "expand"))
529 expand = str2num(bool_pair, s.t[1], 0);
530 else if (!g_ascii_strcasecmp(s.t[0], "padding"))
531 padding = atoi(s.t[1]);
532 else if (!g_ascii_strcasecmp(s.t[0], "border"))
533 border = atoi(s.t[1]);
534 else {
535 ERR( "lxpanel: unknown var %s\n", s.t[0]);
536 goto error;
537 }
538 } else if (s.type == LINE_BLOCK_START) {
539 if (!g_ascii_strcasecmp(s.t[0], "Config")) {
540 int pno = 1;
541 while (pno) {
542 get_line_as_is(fp, &s);
543 if (s.type == LINE_NONE) {
544 ERR( "lxpanel: unexpected eof\n");
545 goto error;
546 } else if (s.type == LINE_BLOCK_START) {
547 pno++;
548 } else if (s.type == LINE_BLOCK_END) {
549 pno--;
550 }
551 fprintf(tmpfp, "%s\n", s.str);
552 }
553 } else {
554 ERR( "lxpanel: unknown block %s\n", s.t[0]);
555 goto error;
556 }
557 } else {
558 ERR( "lxpanel: illegal in this context %s\n", s.str);
559 goto error;
560 }
561 }
562
563 if (!type || !(plug = plugin_load(type))) {
564 ERR( "lxpanel: can't load %s plugin\n", type);
565 goto error;
566 }
567 plug->panel = p;
568 plug->fp = tmpfp;
569 plug->expand = expand;
570 plug->padding = padding;
571 plug->border = border;
572 fprintf(tmpfp, "}\n");
573 fseek(tmpfp, 0, SEEK_SET);
574 DBG("starting\n");
575 if (!plugin_start(plug)) {
576 ERR( "lxpanel: can't start plugin %s\n", type);
577 goto error;
578 }
579 DBG("plug %s\n", type);
580 p->plugins = g_list_append(p->plugins, plug);
581 RET(1);
582
583 error:
584 fclose(tmpfp);
585 g_free(type);
586 if (plug)
587 plugin_put(plug);
588 RET(0);
589
590}
591
592
593int
594panel_start(panel *p, FILE *fp)
595{
596 line s;
597 long pos;
598
599 /* parse global section */
600 ENTER;
601 s.len = 256;
602 memset(p, 0, sizeof(panel));
603 p->allign = ALLIGN_CENTER;
604 p->edge = EDGE_BOTTOM;
605 p->widthtype = WIDTH_PERCENT;
606 p->width = 100;
607 p->heighttype = HEIGHT_PIXEL;
608 p->height = PANEL_HEIGHT_DEFAULT;
609 p->setdocktype = 1;
610 p->setstrut = 1;
611 p->round_corners = 0;
612 p->transparent = 0;
613 p->alpha = 127;
614 p->tintcolor = 0xFFFFFFFF;
615 p->spacing = 0;
616 fbev = fb_ev_new();
617 if ((get_line(fp, &s) != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Global")) {
618 ERR( "lxpanel: config file must start from Global section\n");
619 RET(0);
620 }
621 if (!panel_parse_global(p, fp))
622 RET(0);
623
624 if (!(pconf = tmpfile())) {
625 ERR("can't open temporary file\n");
626 RET(0);
627 }
628 pos = ftell(fp);
629 while (get_line_as_is(fp, &s) != LINE_NONE)
630 fprintf(pconf, "%s\n", s.str);
631 fseek(fp, pos, SEEK_SET);
632
633 while (get_line(fp, &s) != LINE_NONE) {
634 if ((s.type != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Plugin")) {
635 ERR( "lxpanel: expecting Plugin section\n");
636 RET(0);
637 }
638 if (!panel_parse_plugin(p, fp))
639 RET(0);
640 }
641 gtk_widget_show_all(p->topgwin);
642 print_wmdata(p);
643 RET(1);
644}
645
646static void
647delete_plugin(gpointer data, gpointer udata)
648{
649 ENTER;
650 plugin_stop((plugin *)data);
651 plugin_put((plugin *)data);
652 RET();
653
654}
655
656void panel_stop(panel *p)
657{
658 ENTER;
659
660 g_list_foreach(p->plugins, delete_plugin, NULL);
661 g_list_free(p->plugins);
662 p->plugins = NULL;
663
664 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), NoEventMask);
665 gdk_window_remove_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
666 gtk_widget_destroy(p->topgwin);
667 g_object_unref(fbev);
668 g_free(p->workarea);
669 fclose(pconf);
670 gdk_flush();
671 XFlush(GDK_DISPLAY());
672 XSync(GDK_DISPLAY(), True);
673 RET();
674}
675
676
677void
678usage()
679{
680 ENTER;
e7cb732b
HJYP
681 g_print(_("lxpanel %s - lightweight GTK2+ panel for UNIX desktops\n"), version);
682 g_print(_("Command line options:\n"));
683 g_print(_(" --help -- print this help and exit\n"));
684 g_print(_(" --version -- print version and exit\n"));
685 g_print(_(" --log <number> -- set log level 0-5. 0 - none 5 - chatty\n"));
686 g_print(_(" --configure -- launch configuration utility\n"));
687 g_print(_(" --profile name -- use specified profile\n"));
688 g_print("\n");
689 g_print(_(" -h -- same as --help\n"));
690 g_print(_(" -p -- same as --profile\n"));
691 g_print(_(" -v -- same as --version\n"));
692 g_print(_(" -C -- same as --configure\n"));
693 g_print(_("\nVisit http://lxpanel.sourceforge.net/ for detailed documentation,\n\n"));
a52c2257
HJYP
694}
695
696FILE *
697open_profile(gchar *profile)
698{
699 gchar *fname;
700 FILE *fp;
701
702 ENTER;
703 LOG(LOG_INFO, "loading %s profile\n", profile);
704 fname = g_strdup_printf("%s/.lxpanel/%s", getenv("HOME"), profile);
705 fp = fopen(fname, "r");
706 LOG(LOG_INFO, " %s %s\n", fname, fp ? "ok" : "no");
707 if (fp) {
708 cfgfile = fname;
709 RET(fp);
710 }
711 //ERR("Can't load %s\n", fname);
712 g_free(fname);
713
714 /* check private configuration directory */
715 fname = g_strdup_printf(PACKAGE_DATA_DIR "/lxpanel/%s", profile);
716 fp = fopen(fname, "r");
717 LOG(LOG_INFO, " %s %s\n", fname, fp ? "ok" : "no");
718 if (fp) {
719 cfgfile = fname;
720 RET(fp);
721 }
722 //ERR("Can't load %s\n", fname);
723 g_free(fname);
724 LOG(LOG_ERR, "Can't open '%s' profile\n", profile);
725 RET(NULL);
726}
727
728void
729handle_error(Display * d, XErrorEvent * ev)
730{
731 char buf[256];
732
733 ENTER;
734 if (log_level >= LOG_WARN) {
735 XGetErrorText(GDK_DISPLAY(), ev->error_code, buf, 256);
736 LOG(LOG_WARN, "lxpanel : X error: %s\n", buf);
737 }
738 RET();
739}
740
741static void
742sig_usr(int signum)
743{
744 if (signum != SIGUSR1)
745 return;
746 gtk_main_quit();
747}
748
749int
750main(int argc, char *argv[], char *env[])
751{
752 int i;
753 int quit = 0;
754 void configure();
755 FILE *pfp; /* current profile FP */
756
757 ENTER;
758 //printf("sizeof(gulong)=%d\n", sizeof(gulong));
759 setlocale(LC_CTYPE, "");
760 gtk_init(&argc, &argv);
761
762#ifdef ENABLE_NLS
763 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
764 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
765 textdomain ( GETTEXT_PACKAGE );
766#endif
767
768 XSetLocaleModifiers("");
769 XSetErrorHandler((XErrorHandler) handle_error);
770 resolve_atoms();
771 for (i = 1; i < argc; i++) {
772 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
773 usage();
774 exit(0);
775 } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
776 printf("lxpanel %s\n", version);
777 exit(0);
778 } else if (!strcmp(argv[i], "--log")) {
779 i++;
780 if (i == argc) {
781 ERR( "lxpanel: missing log level\n");
782 usage();
783 exit(1);
784 } else {
785 log_level = atoi(argv[i]);
786 }
787 } else if (!strcmp(argv[i], "--configure") || !strcmp(argv[i], "-C")) {
788 config = 1;
789 } else if (!strcmp(argv[i], "--profile") || !strcmp(argv[i], "-p")) {
790 i++;
791 if (i == argc) {
792 ERR( "lxpanel: missing profile name\n");
793 usage();
794 exit(1);
795 } else {
796 cprofile = g_strdup(argv[i]);
797 }
798 } else {
799 printf("lxpanel: unknown option - %s\n", argv[i]);
800 usage();
801 exit(1);
802 }
803 }
804 signal(SIGUSR1, sig_usr);
805 do {
806 if (!(pfp = open_profile(cprofile)))
807 exit(1);
808 p = g_new0(panel, 1);
809 g_return_val_if_fail (p != NULL, 1);
810 if (!panel_start(p, pfp)) {
811 ERR( "lxpanel: can't start panel\n");
812 exit(1);
813 }
814 fclose(pfp);
815 if (config)
816 configure();
817 gtk_main();
818 panel_stop(p);
819 g_free(p);
820 } while (quit == 0);
821
822 exit(0);
823}
824