Delete unused files.
[lxde/lxpanel.git] / src / panel.c
CommitLineData
16fb8c2e 1/**
e68b47dc
JH
2 * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
a52c2257
HJYP
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
28#include <errno.h>
29#include <locale.h>
30#include <string.h>
e7cb732b 31#include <glib/gi18n.h>
e68b47dc 32#include <gdk/gdkx.h>
a52c2257
HJYP
33
34#include "plugin.h"
35#include "panel.h"
36#include "misc.h"
37#include "bg.h"
38#include "gtkbgbox.h"
39
77886b88
HJYP
40#include "lxpanelctl.h"
41
a52c2257
HJYP
42static gchar *cfgfile = NULL;
43static gchar version[] = VERSION;
44gchar *cprofile = "default";
45
e68b47dc 46static int config = 0;
a52c2257
HJYP
47FbEv *fbev;
48
49//#define DEBUG
50#include "dbg.h"
51
52int log_level;
a52c2257
HJYP
53panel *p;
54
f7cb330e
HJYP
55gboolean is_restarting = FALSE;
56
a52c2257
HJYP
57/****************************************************
58 * panel's handlers for WM events *
59 ****************************************************/
60/*
61static void
62panel_del_wm_strut(panel *p)
63{
64 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT);
65 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL);
66}
67*/
68
69
bee4c26e 70void panel_set_wm_strut(panel *p)
a52c2257
HJYP
71{
72 gulong data[12] = { 0 };
73 int i = 4;
74
75 ENTER;
76 if (!GTK_WIDGET_MAPPED (p->topgwin))
77 return;
bee4c26e
HJYP
78 if ( ! p->setstrut )
79 {
80 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL);
81 /* old spec, for wms that do not support STRUT_PARTIAL */
82 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT);
83 return;
84 }
85
a52c2257
HJYP
86 switch (p->edge) {
87 case EDGE_LEFT:
88 i = 0;
89 data[i] = p->aw;
90 data[4 + i*2] = p->ay;
91 data[5 + i*2] = p->ay + p->ah;
92 break;
93 case EDGE_RIGHT:
94 i = 1;
95 data[i] = p->aw;
96 data[4 + i*2] = p->ay;
97 data[5 + i*2] = p->ay + p->ah;
98 break;
99 case EDGE_TOP:
100 i = 2;
101 data[i] = p->ah;
102 data[4 + i*2] = p->ax;
103 data[5 + i*2] = p->ax + p->aw;
104 break;
105 case EDGE_BOTTOM:
106 i = 3;
107 data[i] = p->ah;
108 data[4 + i*2] = p->ax;
109 data[5 + i*2] = p->ax + p->aw;
110 break;
111 default:
112 ERR("wrong edge %d. strut won't be set\n", p->edge);
113 RET();
bee4c26e 114 }
a52c2257 115 DBG("type %d. width %d. from %d to %d\n", i, data[i], data[4 + i*2], data[5 + i*2]);
bee4c26e 116
a52c2257 117 /* if wm supports STRUT_PARTIAL it will ignore STRUT */
bee4c26e 118 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL,
a52c2257
HJYP
119 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 12);
120 /* old spec, for wms that do not support STRUT_PARTIAL */
bee4c26e
HJYP
121 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT,
122 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 4);
a52c2257
HJYP
123
124 RET();
125}
126
127static void
128print_wmdata(panel *p)
129{
130 int i;
131
132 ENTER;
133 RET();
134 DBG("desktop %d/%d\n", p->curdesk, p->desknum);
135 DBG("workarea\n");
136 for (i = 0; i < p->wa_len/4; i++)
137 DBG("(%d, %d) x (%d, %d)\n",
138 p->workarea[4*i + 0],
139 p->workarea[4*i + 1],
140 p->workarea[4*i + 2],
141 p->workarea[4*i + 3]);
142 RET();
143}
144
145
e996608e 146/* defined in plugins/menu.c */
8c44345a 147gboolean show_system_menu( gpointer system_menu );
e996608e
HJYP
148
149/* built-in commands, defined in configurator.c */
77886b88
HJYP
150void configure(void);
151void restart(void);
152void gtk_run(void);
153
8c44345a 154static void process_client_msg ( panel *p, XClientMessageEvent* ev )
77886b88 155{
8c44345a 156 int cmd = ev->data.b[0];
77886b88
HJYP
157 switch( cmd )
158 {
159 case LXPANEL_CMD_SYS_MENU:
5297da29 160 if( p->system_menus )
8c44345a 161 {
5297da29 162 /* show_system_menu( p->system_menus->data ); */
8c44345a
HJYP
163 /* FIXME: I've no idea why this doesn't work without timeout
164 under some WMs, like icewm. */
5297da29
HJYP
165 g_timeout_add( 200, (GSourceFunc)show_system_menu,
166 p->system_menus->data );
8c44345a 167 }
77886b88
HJYP
168 break;
169 case LXPANEL_CMD_RUN:
170 gtk_run();
171 break;
172 case LXPANEL_CMD_CONFIG:
173 configure();
174 break;
175 case LXPANEL_CMD_RESTART:
176 restart();
177 break;
178 case LXPANEL_CMD_EXIT:
179 gtk_main_quit();
180 break;
181 }
182}
183
a52c2257
HJYP
184static GdkFilterReturn
185panel_event_filter(GdkXEvent *xevent, GdkEvent *event, panel *p)
186{
187 Atom at;
188 Window win;
189 XEvent *ev = (XEvent *) xevent;
190
191 ENTER;
192 DBG("win = 0x%x\n", ev->xproperty.window);
77886b88
HJYP
193 if (ev->type != PropertyNotify ) {
194 /* private client message from lxpanelctl */
195 if( ev->type == ClientMessage && ev->xproperty.atom == a_LXPANEL_CMD )
196 {
8c44345a 197 process_client_msg( p, (XClientMessageEvent*)ev );
77886b88 198 }
a52c2257 199 RET(GDK_FILTER_CONTINUE);
77886b88
HJYP
200 }
201
a52c2257
HJYP
202 at = ev->xproperty.atom;
203 win = ev->xproperty.window;
204 DBG("win=%x at=%d\n", win, at);
205 if (win == GDK_ROOT_WINDOW()) {
206 if (at == a_NET_CLIENT_LIST) {
207 DBG("A_NET_CLIENT_LIST\n");
208 fb_ev_trigger(fbev, EV_CLIENT_LIST);
209 } else if (at == a_NET_CURRENT_DESKTOP) {
210 DBG("A_NET_CURRENT_DESKTOP\n");
211 p->curdesk = get_net_current_desktop();
212 fb_ev_trigger(fbev, EV_CURRENT_DESKTOP);
213 } else if (at == a_NET_NUMBER_OF_DESKTOPS) {
214 DBG("A_NET_NUMBER_OF_DESKTOPS\n");
215 p->desknum = get_net_number_of_desktops();
216 fb_ev_trigger(fbev, EV_NUMBER_OF_DESKTOPS);
217 } else if (at == a_NET_DESKTOP_NAMES) {
218 DBG("A_NET_DESKTOP_NAMES\n");
219 fb_ev_trigger(fbev, EV_DESKTOP_NAMES);
220 } else if (at == a_NET_ACTIVE_WINDOW) {
221 DBG("A_NET_ACTIVE_WINDOW\n");
222 fb_ev_trigger(fbev, EV_ACTIVE_WINDOW);
223 }else if (at == a_NET_CLIENT_LIST_STACKING) {
224 DBG("A_NET_CLIENT_LIST_STACKING\n");
225 fb_ev_trigger(fbev, EV_CLIENT_LIST_STACKING);
226 } else if (at == a_XROOTPMAP_ID) {
227 DBG("a_XROOTPMAP_ID\n");
228 if (p->transparent) {
229 fb_bg_notify_changed_bg(p->bg);
230 }
231 } else if (at == a_NET_WORKAREA) {
232 DBG("A_NET_WORKAREA\n");
0dcb6bf5 233 g_free( p->workarea );
a52c2257
HJYP
234 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
235 print_wmdata(p);
236 } else
237 RET(GDK_FILTER_CONTINUE);
238 RET(GDK_FILTER_REMOVE);
239 }
240 DBG("non root %x\n", win);
241 RET(GDK_FILTER_CONTINUE);
242}
243
244/****************************************************
245 * panel's handlers for GTK events *
246 ****************************************************/
247
bee4c26e 248
a52c2257
HJYP
249static gint
250panel_delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
251{
252 ENTER;
253 RET(FALSE);
254}
255
256static gint
257panel_destroy_event(GtkWidget * widget, GdkEvent * event, gpointer data)
258{
259 //panel *p = (panel *) data;
260
bee4c26e 261 ENTER;
a52c2257
HJYP
262 //if (!p->self_destroy)
263 gtk_main_quit();
264 RET(FALSE);
265}
266
267
268static void
269panel_realize(GtkWidget *widget, panel *p)
270{
271 ENTER;
272 RET();
273
274}
275static gint
276panel_size_req(GtkWidget *widget, GtkRequisition *req, panel *p)
277{
278 ENTER;
279 DBG("IN req=(%d, %d)\n", req->width, req->height);
280 if (p->widthtype == WIDTH_REQUEST)
281 p->width = (p->orientation == ORIENT_HORIZ) ? req->width : req->height;
282 if (p->heighttype == HEIGHT_REQUEST)
283 p->height = (p->orientation == ORIENT_HORIZ) ? req->height : req->width;
284 calculate_position(p);
285 req->width = p->aw;
286 req->height = p->ah;
287 DBG("OUT req=(%d, %d)\n", req->width, req->height);
288 RET( TRUE );
289}
290
291static gint
292panel_size_alloc(GtkWidget *widget, GtkAllocation *a, panel *p)
293{
294 ENTER;
9939506e 295 DBG("installed alloc: size (%d, %d). pos (%d, %d)\n", a->width, a->height, a->x, a->y);
a52c2257
HJYP
296 DBG("suggested alloc: size (%d, %d). pos (%d, %d)\n", a->width, a->height, a->x, a->y);
297 DBG("prev pref alloc: size (%d, %d). pos (%d, %d)\n", p->aw, p->ah, p->ax, p->ay);
298 if (p->widthtype == WIDTH_REQUEST)
299 p->width = (p->orientation == ORIENT_HORIZ) ? a->width : a->height;
300 if (p->heighttype == HEIGHT_REQUEST)
301 p->height = (p->orientation == ORIENT_HORIZ) ? a->height : a->width;
302 calculate_position(p);
303 DBG("curr pref alloc: size (%d, %d). pos (%d, %d)\n", p->aw, p->ah, p->ax, p->ay);
304 if (a->width == p->aw && a->height == p->ah && a->x == p->ax && a->y == p ->ay) {
305 DBG("actual coords eq to preffered. just returning\n");
306 RET(TRUE);
307 }
308
309 gtk_window_move(GTK_WINDOW(p->topgwin), p->ax, p->ay);
310 DBG("moving to %d %d\n", p->ax, p->ay);
bee4c26e 311 panel_set_wm_strut(p);
a52c2257
HJYP
312 RET(TRUE);
313}
314
315
316static gboolean
317panel_configure_event (GtkWidget *widget, GdkEventConfigure *e, panel *p)
318{
319 ENTER;
320 if (e->width == p->cw && e->height == p->ch && e->x == p->cx && e->y == p->cy)
321 RET(TRUE);
322 p->cw = e->width;
323 p->ch = e->height;
324 p->cx = e->x;
325 p->cy = e->y;
326 DBG("here\n");
327 if (p->transparent)
328 fb_bg_notify_changed_bg(p->bg);
329 DBG("here\n");
330 DBG("geom: size (%d, %d). pos (%d, %d)\n", e->width, e->height, e->x, e->y);
331 RET(FALSE);
bee4c26e 332
a52c2257
HJYP
333}
334
335
336/****************************************************
337 * panel creation *
338 ****************************************************/
339static void
340make_round_corners(panel *p)
341{
a97d06a6
HJYP
342 /* FIXME: This should be re-written with shape extension of X11 */
343#if 0
a52c2257
HJYP
344 GtkWidget *b1, *b2, *img;
345 GtkWidget *(*box_new) (gboolean, gint);
346 void (*box_pack)(GtkBox *, GtkWidget *, gboolean, gboolean, guint);
347 gchar *s1, *s2;
348#define IMGPREFIX PACKAGE_DATA_DIR "/lxpanel/images/"
bee4c26e 349
a52c2257
HJYP
350 ENTER;
351 if (p->edge == EDGE_TOP) {
352 s1 = IMGPREFIX "top-left.xpm";
353 s2 = IMGPREFIX "top-right.xpm";
354 } else if (p->edge == EDGE_BOTTOM) {
355 s1 = IMGPREFIX "bottom-left.xpm";
356 s2 = IMGPREFIX "bottom-right.xpm";
357 } else if (p->edge == EDGE_LEFT) {
358 s1 = IMGPREFIX "top-left.xpm";
359 s2 = IMGPREFIX "bottom-left.xpm";
360 } else if (p->edge == EDGE_RIGHT) {
361 s1 = IMGPREFIX "top-right.xpm";
362 s2 = IMGPREFIX "bottom-right.xpm";
363 } else
364 RET();
bee4c26e 365
a52c2257
HJYP
366 box_new = (p->orientation == ORIENT_HORIZ) ? gtk_vbox_new : gtk_hbox_new;
367 b1 = box_new(0, FALSE);
368 gtk_widget_show(b1);
369 b2 = box_new(0, FALSE);
370 gtk_widget_show(b2);
371
372 box_pack = (p->edge == EDGE_TOP || p->edge == EDGE_LEFT) ?
373 gtk_box_pack_start : gtk_box_pack_end;
bee4c26e 374
a52c2257
HJYP
375 img = gtk_image_new_from_file(s1);
376 gtk_widget_show(img);
377 box_pack(GTK_BOX(b1), img, FALSE, FALSE, 0);
378 img = gtk_image_new_from_file(s2);
379 gtk_widget_show(img);
380 box_pack(GTK_BOX(b2), img, FALSE, FALSE, 0);
381 gtk_box_pack_start(GTK_BOX(p->lbox), b1, FALSE, FALSE, 0);
382 gtk_box_pack_end(GTK_BOX(p->lbox), b2, FALSE, FALSE, 0);
bee4c26e 383 RET();
a97d06a6 384#endif
bee4c26e
HJYP
385}
386
387void panel_set_dock_type(panel *p)
388{
389 if (p->setdocktype) {
390 Atom state = a_NET_WM_WINDOW_TYPE_DOCK;
391 XChangeProperty(GDK_DISPLAY(), p->topxwin,
392 a_NET_WM_WINDOW_TYPE, XA_ATOM, 32,
393 PropModeReplace, (unsigned char *) &state, 1);
394 }
395 else {
396 XDeleteProperty( GDK_DISPLAY(), p->topxwin, a_NET_WM_WINDOW_TYPE );
397 }
a52c2257
HJYP
398}
399
0defe4b9 400static void
a52c2257
HJYP
401panel_start_gui(panel *p)
402{
403 Atom state[3];
404 XWMHints wmhints;
405 guint32 val;
6db11841 406
a52c2257
HJYP
407 ENTER;
408
409 // main toplevel window
410 p->topgwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
411 gtk_container_set_border_width(GTK_CONTAINER(p->topgwin), 0);
412 gtk_window_set_resizable(GTK_WINDOW(p->topgwin), FALSE);
413 gtk_window_set_wmclass(GTK_WINDOW(p->topgwin), "panel", "lxpanel");
414 gtk_window_set_title(GTK_WINDOW(p->topgwin), "panel");
415 gtk_window_set_position(GTK_WINDOW(p->topgwin), GTK_WIN_POS_NONE);
416 gtk_window_set_decorated(GTK_WINDOW(p->topgwin), FALSE);
77886b88 417
a52c2257
HJYP
418 g_signal_connect(G_OBJECT(p->topgwin), "delete-event",
419 G_CALLBACK(panel_delete_event), p);
420 g_signal_connect(G_OBJECT(p->topgwin), "destroy-event",
421 G_CALLBACK(panel_destroy_event), p);
422 g_signal_connect (G_OBJECT (p->topgwin), "size-request",
423 (GCallback) panel_size_req, p);
424 g_signal_connect (G_OBJECT (p->topgwin), "size-allocate",
425 (GCallback) panel_size_alloc, p);
426 g_signal_connect (G_OBJECT (p->topgwin), "configure-event",
427 (GCallback) panel_configure_event, p);
428 g_signal_connect (G_OBJECT (p->topgwin), "realize",
429 (GCallback) panel_realize, p);
6db11841 430
a52c2257
HJYP
431 gtk_widget_realize(p->topgwin);
432 //gdk_window_set_decorations(p->topgwin->window, 0);
433 gtk_widget_set_app_paintable(p->topgwin, TRUE);
6db11841 434
a52c2257
HJYP
435 // background box all over toplevel
436 p->bbox = gtk_bgbox_new();
437 gtk_container_add(GTK_CONTAINER(p->topgwin), p->bbox);
438 gtk_widget_show(p->bbox);
439 gtk_container_set_border_width(GTK_CONTAINER(p->bbox), 0);
2de71c90
FC
440
441 /* font color */
442 gtk_widget_modify_text(GTK_WIDGET(p->bbox), GTK_STATE_NORMAL, &p->gfontcolor);
443
444 /* background image */
4532640a
FC
445 //p->defstyle = gtk_style_copy(p->bbox->style);
446 p->defstyle = gtk_style_new();
2de71c90
FC
447 if (p->background) {
448 p->bbox->style->bg_pixmap[0] = fb_bg_get_pix_from_file(p->bbox, p->background_file);
449 gtk_bgbox_set_background(p->bbox, BG_STYLE, 0, 0);
450 } else if (p->transparent) {
a52c2257 451 p->bg = fb_bg_get_for_display();
bee4c26e 452 gtk_bgbox_set_background(p->bbox, BG_ROOT, p->tintcolor, p->alpha);
a52c2257
HJYP
453 }
454
455 // main layout manager as a single child of background widget box
a97d06a6 456 p->box = p->my_box_new(FALSE, 0);
a52c2257 457 gtk_container_set_border_width(GTK_CONTAINER(p->box), 0);
a97d06a6 458 gtk_container_add(GTK_CONTAINER(p->bbox), p->box);
a52c2257 459 gtk_widget_show(p->box);
a97d06a6
HJYP
460 if (p->round_corners)
461 make_round_corners(p);
6db11841 462
a52c2257
HJYP
463 p->topxwin = GDK_WINDOW_XWINDOW(GTK_WIDGET(p->topgwin)->window);
464 DBG("topxwin = %x\n", p->topxwin);
465
466 /* the settings that should be done before window is mapped */
467 wmhints.flags = InputHint;
468 wmhints.input = 0;
bee4c26e 469 XSetWMHints (GDK_DISPLAY(), p->topxwin, &wmhints);
a52c2257
HJYP
470#define WIN_HINTS_SKIP_FOCUS (1<<0) /* "alt-tab" skips this win */
471 val = WIN_HINTS_SKIP_FOCUS;
472 XChangeProperty(GDK_DISPLAY(), p->topxwin,
473 XInternAtom(GDK_DISPLAY(), "_WIN_HINTS", False), XA_CARDINAL, 32,
474 PropModeReplace, (unsigned char *) &val, 1);
475
bee4c26e 476 panel_set_dock_type(p);
a52c2257
HJYP
477
478 /* window mapping point */
479 gtk_widget_show_all(p->topgwin);
480
481 /* the settings that should be done after window is mapped */
482
483 /* send it to running wm */
484 Xclimsg(p->topxwin, a_NET_WM_DESKTOP, 0xFFFFFFFF, 0, 0, 0, 0);
485 /* and assign it ourself just for case when wm is not running */
486 val = 0xFFFFFFFF;
487 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_DESKTOP, XA_CARDINAL, 32,
488 PropModeReplace, (unsigned char *) &val, 1);
489
490 state[0] = a_NET_WM_STATE_SKIP_PAGER;
491 state[1] = a_NET_WM_STATE_SKIP_TASKBAR;
492 state[2] = a_NET_WM_STATE_STICKY;
493 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STATE, XA_ATOM,
494 32, PropModeReplace, (unsigned char *) state, 3);
495
77886b88 496 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), SubstructureNotifyMask|PropertyChangeMask);
a52c2257
HJYP
497 gdk_window_add_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
498
499 calculate_position(p);
500 gdk_window_move_resize(p->topgwin->window, p->ax, p->ay, p->aw, p->ah);
bee4c26e 501 panel_set_wm_strut(p);
77886b88 502
239cb032
HJYP
503 p->tooltips = gtk_tooltips_new();
504#if GLIB_CHECK_VERSION( 2, 10, 0 )
505 g_object_ref_sink( p->tooltips );
506#else
507 g_object_ref( p->tooltips );
508 gtk_object_sink( p->tooltips );
509#endif
510
a52c2257
HJYP
511 RET();
512}
513
a97d06a6
HJYP
514void panel_set_orientation(panel *p)
515{
516 GList* l;
517 p->orientation = (p->edge == EDGE_TOP || p->edge == EDGE_BOTTOM)
518 ? ORIENT_HORIZ : ORIENT_VERT;
519 if (p->orientation == ORIENT_HORIZ) {
520 p->my_box_new = gtk_hbox_new;
521 p->my_separator_new = gtk_vseparator_new;
522 } else {
523 p->my_box_new = gtk_vbox_new;
524 p->my_separator_new = gtk_hseparator_new;
525 }
526
527 /* recreate the main layout box */
528 if( p->box ) {
5a343ad5
JH
529 GtkBox* newbox = GTK_BOX(recreate_box( GTK_BOX(p->box), p->orientation ));
530 if( GTK_WIDGET(newbox) != p->box ) {
531 p->box = GTK_WIDGET(newbox);
532 gtk_container_add( GTK_CONTAINER(p->bbox), GTK_WIDGET(newbox) );
a97d06a6
HJYP
533 }
534 }
535 /* NOTE: This loop won't be executed when panel started since
536 plugins are not loaded at that time.
537 This is used when the orientation of the panel is changed
538 from the config dialog, and plugins should be re-layout.
539 */
540 for( l = p->plugins; l; l = l->next ) {
541 plugin* pl = (plugin*)l->data;
542 if( pl->class->orientation ) {
543 pl->class->orientation( pl );
544 }
545 }
546}
547
a52c2257 548static int
db449f6e 549panel_parse_global(panel *p, char **fp)
a52c2257
HJYP
550{
551 line s;
552 s.len = 256;
6db11841 553
a52c2257 554 ENTER;
c69ac68e 555 while (lxpanel_get_line(fp, &s) != LINE_NONE) {
a52c2257
HJYP
556 if (s.type == LINE_VAR) {
557 if (!g_ascii_strcasecmp(s.t[0], "edge")) {
558 p->edge = str2num(edge_pair, s.t[1], EDGE_NONE);
559 } else if (!g_ascii_strcasecmp(s.t[0], "allign")) {
560 p->allign = str2num(allign_pair, s.t[1], ALLIGN_NONE);
561 } else if (!g_ascii_strcasecmp(s.t[0], "margin")) {
562 p->margin = atoi(s.t[1]);
563 } else if (!g_ascii_strcasecmp(s.t[0], "widthtype")) {
564 p->widthtype = str2num(width_pair, s.t[1], WIDTH_NONE);
565 } else if (!g_ascii_strcasecmp(s.t[0], "width")) {
566 p->width = atoi(s.t[1]);
567 } else if (!g_ascii_strcasecmp(s.t[0], "heighttype")) {
568 p->heighttype = str2num(height_pair, s.t[1], HEIGHT_NONE);
569 } else if (!g_ascii_strcasecmp(s.t[0], "height")) {
570 p->height = atoi(s.t[1]);
571 } else if (!g_ascii_strcasecmp(s.t[0], "spacing")) {
572 p->spacing = atoi(s.t[1]);
573 } else if (!g_ascii_strcasecmp(s.t[0], "SetDockType")) {
574 p->setdocktype = str2num(bool_pair, s.t[1], 0);
575 } else if (!g_ascii_strcasecmp(s.t[0], "SetPartialStrut")) {
576 p->setstrut = str2num(bool_pair, s.t[1], 0);
577 } else if (!g_ascii_strcasecmp(s.t[0], "RoundCorners")) {
578 p->round_corners = str2num(bool_pair, s.t[1], 0);
579 } else if (!g_ascii_strcasecmp(s.t[0], "Transparent")) {
580 p->transparent = str2num(bool_pair, s.t[1], 0);
581 } else if (!g_ascii_strcasecmp(s.t[0], "Alpha")) {
582 p->alpha = atoi(s.t[1]);
583 if (p->alpha > 255)
584 p->alpha = 255;
585 } else if (!g_ascii_strcasecmp(s.t[0], "TintColor")) {
586 if (!gdk_color_parse (s.t[1], &p->gtintcolor))
587 gdk_color_parse ("white", &p->gtintcolor);
588 p->tintcolor = gcolor2rgb24(&p->gtintcolor);
589 DBG("tintcolor=%x\n", p->tintcolor);
2de71c90
FC
590 } else if (!g_ascii_strcasecmp(s.t[0], "useFontColor")) {
591 p->usefontcolor = str2num(bool_pair, s.t[1], 0);
592 } else if (!g_ascii_strcasecmp(s.t[0], "FontColor")) {
593 if (!gdk_color_parse (s.t[1], &p->gfontcolor))
594 gdk_color_parse ("black", &p->gfontcolor);
595 p->tintcolor = gcolor2rgb24(&p->gfontcolor);
596 DBG("fontcolor=%x\n", p->fontcolor);
597 } else if (!g_ascii_strcasecmp(s.t[0], "Background")) {
598 p->background = str2num(bool_pair, s.t[1], 0);
599 } else if( !g_ascii_strcasecmp(s.t[0], "BackgroundFile") ) {
600 p->background_file = g_strdup( s.t[1] );
239cb032
HJYP
601 } else if( !g_ascii_strcasecmp(s.t[0], "FileManager") ) {
602 p->file_manager = g_strdup( s.t[1] );
603 } else if( !g_ascii_strcasecmp(s.t[0], "Terminal") ) {
604 p->terminal = g_strdup( s.t[1] );
389975e0
HJYP
605 } else if( !g_ascii_strcasecmp(s.t[0], "LogoutCommand") ) {
606 p->logout_command = g_strdup( s.t[1] );
a52c2257
HJYP
607 } else {
608 ERR( "lxpanel: %s - unknown var in Global section\n", s.t[0]);
609 RET(0);
610 }
611 } else if (s.type == LINE_BLOCK_END) {
612 break;
613 } else {
614 ERR( "lxpanel: illegal in this context %s\n", s.str);
615 RET(0);
616 }
617 }
a97d06a6 618 panel_set_orientation( p );
a52c2257
HJYP
619 if (p->width < 0)
620 p->width = 100;
621 if (p->widthtype == WIDTH_PERCENT && p->width > 100)
622 p->width = 100;
623 p->heighttype = HEIGHT_PIXEL;
624 if (p->heighttype == HEIGHT_PIXEL) {
625 if (p->height < PANEL_HEIGHT_MIN)
626 p->height = PANEL_HEIGHT_MIN;
627 else if (p->height > PANEL_HEIGHT_MAX)
628 p->height = PANEL_HEIGHT_MAX;
629 }
2de71c90
FC
630
631 if (p->background)
632 p->transparent = 0;
633
a52c2257
HJYP
634 p->curdesk = get_net_current_desktop();
635 p->desknum = get_net_number_of_desktops();
636 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
637 print_wmdata(p);
239cb032 638
a52c2257
HJYP
639 panel_start_gui(p);
640 RET(1);
641}
642
643static int
db449f6e 644panel_parse_plugin(panel *p, char **fp)
a52c2257
HJYP
645{
646 line s;
647 plugin *plug = NULL;
648 gchar *type = NULL;
a52c2257 649 int expand , padding, border;
db449f6e
HJYP
650 char* pconfig = NULL;
651
a52c2257
HJYP
652 ENTER;
653 s.len = 256;
a52c2257 654 border = expand = padding = 0;
c69ac68e 655 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
a52c2257
HJYP
656 if (s.type == LINE_NONE) {
657 ERR( "lxpanel: bad line %s\n", s.str);
658 goto error;
659 }
660 if (s.type == LINE_VAR) {
661 if (!g_ascii_strcasecmp(s.t[0], "type")) {
662 type = g_strdup(s.t[1]);
663 DBG("plug %s\n", type);
664 } else if (!g_ascii_strcasecmp(s.t[0], "expand"))
665 expand = str2num(bool_pair, s.t[1], 0);
666 else if (!g_ascii_strcasecmp(s.t[0], "padding"))
667 padding = atoi(s.t[1]);
668 else if (!g_ascii_strcasecmp(s.t[0], "border"))
669 border = atoi(s.t[1]);
670 else {
671 ERR( "lxpanel: unknown var %s\n", s.t[0]);
672 goto error;
673 }
674 } else if (s.type == LINE_BLOCK_START) {
675 if (!g_ascii_strcasecmp(s.t[0], "Config")) {
db449f6e 676 pconfig = *fp;
a52c2257
HJYP
677 int pno = 1;
678 while (pno) {
679 get_line_as_is(fp, &s);
680 if (s.type == LINE_NONE) {
681 ERR( "lxpanel: unexpected eof\n");
682 goto error;
683 } else if (s.type == LINE_BLOCK_START) {
684 pno++;
685 } else if (s.type == LINE_BLOCK_END) {
686 pno--;
bee4c26e 687 }
db449f6e 688 }
a52c2257
HJYP
689 } else {
690 ERR( "lxpanel: unknown block %s\n", s.t[0]);
691 goto error;
692 }
693 } else {
694 ERR( "lxpanel: illegal in this context %s\n", s.str);
695 goto error;
696 }
697 }
db449f6e 698
a52c2257
HJYP
699 if (!type || !(plug = plugin_load(type))) {
700 ERR( "lxpanel: can't load %s plugin\n", type);
701 goto error;
702 }
db449f6e 703
a52c2257 704 plug->panel = p;
a52c2257
HJYP
705 plug->expand = expand;
706 plug->padding = padding;
707 plug->border = border;
a52c2257 708 DBG("starting\n");
db449f6e 709 if (!plugin_start(plug, pconfig ? &pconfig : NULL)) {
a52c2257
HJYP
710 ERR( "lxpanel: can't start plugin %s\n", type);
711 goto error;
712 }
713 DBG("plug %s\n", type);
714 p->plugins = g_list_append(p->plugins, plug);
0dcb6bf5
HJYP
715
716 g_free( type );
a52c2257 717 RET(1);
db449f6e 718
a52c2257 719 error:
a52c2257
HJYP
720 g_free(type);
721 if (plug)
722 plugin_put(plug);
723 RET(0);
a52c2257
HJYP
724}
725
726
0defe4b9 727static int
db449f6e 728panel_start( panel *p, char **fp )
a52c2257
HJYP
729{
730 line s;
db449f6e 731
a52c2257
HJYP
732 /* parse global section */
733 ENTER;
734 s.len = 256;
735 memset(p, 0, sizeof(panel));
736 p->allign = ALLIGN_CENTER;
737 p->edge = EDGE_BOTTOM;
738 p->widthtype = WIDTH_PERCENT;
739 p->width = 100;
740 p->heighttype = HEIGHT_PIXEL;
741 p->height = PANEL_HEIGHT_DEFAULT;
742 p->setdocktype = 1;
743 p->setstrut = 1;
744 p->round_corners = 0;
745 p->transparent = 0;
746 p->alpha = 127;
747 p->tintcolor = 0xFFFFFFFF;
2de71c90
FC
748 p->usefontcolor = 0;
749 p->fontcolor = 0x00000000;
a52c2257
HJYP
750 p->spacing = 0;
751 fbev = fb_ev_new();
c69ac68e 752 if ((lxpanel_get_line(fp, &s) != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Global")) {
a52c2257
HJYP
753 ERR( "lxpanel: config file must start from Global section\n");
754 RET(0);
755 }
756 if (!panel_parse_global(p, fp))
757 RET(0);
758
c69ac68e 759 while (lxpanel_get_line(fp, &s) != LINE_NONE) {
a52c2257
HJYP
760 if ((s.type != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Plugin")) {
761 ERR( "lxpanel: expecting Plugin section\n");
762 RET(0);
763 }
9939506e 764 panel_parse_plugin(p, fp);
a52c2257
HJYP
765 }
766 gtk_widget_show_all(p->topgwin);
767 print_wmdata(p);
768 RET(1);
769}
770
771static void
772delete_plugin(gpointer data, gpointer udata)
773{
774 ENTER;
775 plugin_stop((plugin *)data);
776 plugin_put((plugin *)data);
777 RET();
a52c2257
HJYP
778}
779
780void panel_stop(panel *p)
781{
782 ENTER;
783
784 g_list_foreach(p->plugins, delete_plugin, NULL);
785 g_list_free(p->plugins);
786 p->plugins = NULL;
8c44345a 787
5297da29 788 if( p->system_menus ){
8c44345a 789 do{
5297da29 790 } while ( g_source_remove_by_user_data( p->system_menus ) );
8c44345a
HJYP
791 }
792
239cb032
HJYP
793 g_object_unref( p->tooltips );
794
a52c2257
HJYP
795 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), NoEventMask);
796 gdk_window_remove_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
797 gtk_widget_destroy(p->topgwin);
798 g_object_unref(fbev);
799 g_free(p->workarea);
2de71c90 800 g_free( p->background_file );
239cb032
HJYP
801 g_free( p->file_manager );
802 g_free( p->terminal );
389975e0 803 g_free( p->logout_command );
5297da29 804 g_slist_free( p->system_menus );
a52c2257
HJYP
805 gdk_flush();
806 XFlush(GDK_DISPLAY());
807 XSync(GDK_DISPLAY(), True);
808 RET();
809}
810
811
0defe4b9 812static void
a52c2257
HJYP
813usage()
814{
815 ENTER;
e7cb732b
HJYP
816 g_print(_("lxpanel %s - lightweight GTK2+ panel for UNIX desktops\n"), version);
817 g_print(_("Command line options:\n"));
818 g_print(_(" --help -- print this help and exit\n"));
819 g_print(_(" --version -- print version and exit\n"));
820 g_print(_(" --log <number> -- set log level 0-5. 0 - none 5 - chatty\n"));
821 g_print(_(" --configure -- launch configuration utility\n"));
822 g_print(_(" --profile name -- use specified profile\n"));
823 g_print("\n");
824 g_print(_(" -h -- same as --help\n"));
825 g_print(_(" -p -- same as --profile\n"));
826 g_print(_(" -v -- same as --version\n"));
827 g_print(_(" -C -- same as --configure\n"));
828 g_print(_("\nVisit http://lxpanel.sourceforge.net/ for detailed documentation,\n\n"));
a52c2257
HJYP
829}
830
e68b47dc 831static char*
db449f6e 832load_profile(gchar *profile)
a52c2257
HJYP
833{
834 gchar *fname;
db449f6e 835 char* ret;
a52c2257
HJYP
836
837 ENTER;
838 LOG(LOG_INFO, "loading %s profile\n", profile);
839 fname = g_strdup_printf("%s/.lxpanel/%s", getenv("HOME"), profile);
db449f6e
HJYP
840 g_file_get_contents( fname, &ret, NULL, NULL );
841 if (ret) {
a52c2257 842 cfgfile = fname;
db449f6e 843 RET(ret);
a52c2257
HJYP
844 }
845 //ERR("Can't load %s\n", fname);
846 g_free(fname);
db449f6e 847
a52c2257
HJYP
848 /* check private configuration directory */
849 fname = g_strdup_printf(PACKAGE_DATA_DIR "/lxpanel/%s", profile);
db449f6e
HJYP
850 g_file_get_contents( fname, &ret, NULL, NULL );
851 if (ret) {
a52c2257 852 cfgfile = fname;
db449f6e 853 RET(ret);
a52c2257
HJYP
854 }
855 //ERR("Can't load %s\n", fname);
856 g_free(fname);
857 LOG(LOG_ERR, "Can't open '%s' profile\n", profile);
858 RET(NULL);
859}
860
e68b47dc 861static void
a52c2257
HJYP
862handle_error(Display * d, XErrorEvent * ev)
863{
864 char buf[256];
865
866 ENTER;
867 if (log_level >= LOG_WARN) {
868 XGetErrorText(GDK_DISPLAY(), ev->error_code, buf, 256);
869 LOG(LOG_WARN, "lxpanel : X error: %s\n", buf);
870 }
871 RET();
872}
873
e68b47dc
JH
874/* Lightweight lock related functions - X clipboard hacks */
875
876#define CLIPBOARD_NAME "LXPANEL_SELECTION"
877
878/*
879 * clipboard_get_func - dummy get_func for gtk_clipboard_set_with_data ()
880 */
881static void
882clipboard_get_func(
883 GtkClipboard *clipboard G_GNUC_UNUSED,
884 GtkSelectionData *selection_data G_GNUC_UNUSED,
885 guint info G_GNUC_UNUSED,
886 gpointer user_data_or_owner G_GNUC_UNUSED)
887{
888}
889
890/*
891 * clipboard_clear_func - dummy clear_func for gtk_clipboard_set_with_data ()
892 */
893static void clipboard_clear_func(
894 GtkClipboard *clipboard G_GNUC_UNUSED,
895 gpointer user_data_or_owner G_GNUC_UNUSED)
896{
897}
898
899/*
900 * Lightweight version for checking single instance.
901 * Try and get the CLIPBOARD_NAME clipboard instead of using file manipulation.
902 *
903 * Returns TRUE if successfully retrieved and FALSE otherwise.
904 */
16fb8c2e 905static gboolean check_main_lock()
e68b47dc
JH
906{
907 static const GtkTargetEntry targets[] = { { CLIPBOARD_NAME, 0, 0 } };
908 gboolean retval = FALSE;
909 GtkClipboard *clipboard;
910 Atom atom;
911
912 atom = gdk_x11_get_xatom_by_name(CLIPBOARD_NAME);
913
914 XGrabServer(GDK_DISPLAY());
915
916 if (XGetSelectionOwner(GDK_DISPLAY(), atom) != None)
917 goto out;
918
919 clipboard = gtk_clipboard_get(gdk_atom_intern(CLIPBOARD_NAME, FALSE));
920
921 if (gtk_clipboard_set_with_data(clipboard, targets,
922 G_N_ELEMENTS (targets),
923 clipboard_get_func,
924 clipboard_clear_func, NULL))
925 retval = TRUE;
926
927out:
928 XUngrabServer (GDK_DISPLAY ());
929 gdk_flush ();
930
931 return retval;
932}
933#undef CLIPBOARD_NAME
934
a52c2257
HJYP
935int
936main(int argc, char *argv[], char *env[])
937{
938 int i;
a52c2257 939 void configure();
db449f6e 940 char *fp, *pfp; /* point to current position of profile data in memory */
f277dbb7 941
a52c2257
HJYP
942 ENTER;
943 //printf("sizeof(gulong)=%d\n", sizeof(gulong));
944 setlocale(LC_CTYPE, "");
f277dbb7 945
a52c2257
HJYP
946 gtk_init(&argc, &argv);
947
948#ifdef ENABLE_NLS
949 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
950 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
951 textdomain ( GETTEXT_PACKAGE );
952#endif
953
954 XSetLocaleModifiers("");
955 XSetErrorHandler((XErrorHandler) handle_error);
956 resolve_atoms();
957 for (i = 1; i < argc; i++) {
958 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
959 usage();
960 exit(0);
961 } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
962 printf("lxpanel %s\n", version);
963 exit(0);
964 } else if (!strcmp(argv[i], "--log")) {
965 i++;
966 if (i == argc) {
967 ERR( "lxpanel: missing log level\n");
968 usage();
969 exit(1);
970 } else {
971 log_level = atoi(argv[i]);
972 }
973 } else if (!strcmp(argv[i], "--configure") || !strcmp(argv[i], "-C")) {
974 config = 1;
975 } else if (!strcmp(argv[i], "--profile") || !strcmp(argv[i], "-p")) {
976 i++;
977 if (i == argc) {
978 ERR( "lxpanel: missing profile name\n");
979 usage();
980 exit(1);
981 } else {
982 cprofile = g_strdup(argv[i]);
983 }
984 } else {
985 printf("lxpanel: unknown option - %s\n", argv[i]);
986 usage();
987 exit(1);
988 }
989 }
f277dbb7 990
e68b47dc
JH
991 /* Check for duplicated panel instances */
992 if (!check_main_lock() && !config) {
993 printf("There is alreay an instance of LXPanel. Now to exit\n");
994 exit(1);
995 }
996
f277dbb7
HJYP
997 /* Add our own icons to the search path of icon theme */
998 gtk_icon_theme_append_search_path( gtk_icon_theme_get_default(),
999 PACKAGE_DATA_DIR "/lxpanel/images" );
1000
f7cb330e
HJYP
1001restart:
1002 is_restarting = FALSE;
1003
6a6ad54e
HJYP
1004 if (!(fp = pfp = load_profile(cprofile)))
1005 exit(1);
1006 p = g_new0(panel, 1);
1007 g_return_val_if_fail (p != NULL, 1);
1008 if (!panel_start(p, &pfp)) {
1009 ERR( "lxpanel: can't start panel\n");
1010 exit(1);
5541b8d2 1011 }
6a6ad54e
HJYP
1012 g_free( fp );
1013 if (config)
1014 configure();
1015
1016 gtk_main();
1017 panel_stop(p);
1018 g_free( cfgfile );
1019 g_free(p);
5541b8d2 1020
f7cb330e
HJYP
1021 if( is_restarting )
1022 goto restart;
1023
5541b8d2 1024 return 0;
a52c2257
HJYP
1025}
1026