1 /*
2  * appbar.cc - Defines how appbar looks and feels
3  * Copyright (C) 2001 Frank Hale
4  * frankhale@yahoo.com
5  * http://sapphire.sourceforge.net/
6  *
7  * Updated: 24 July 2001
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  */
23 
24 #include "appbar.hh"
25 
26 Appbar *ab;
27 
28 unsigned long palette[PALETTE_COUNT];
29 
signal_handler(int signal)30 void signal_handler(int signal)
31 {
32   switch(signal)
33   {
34 	case SIGQUIT:
35 	case SIGINT:
36   	case SIGTERM:
37 		ab->quit();
38     	break;
39 
40 	//case SIGHUP:
41    	//break;
42 
43   	case SIGCHLD:
44     		wait(NULL);
45     	break;
46   }
47 }
48 
init_signals()49 void init_signals()
50 {
51 	struct sigaction act;
52 
53 	act.sa_handler=signal_handler;
54   	act.sa_flags=0;
55 
56   	sigaction(SIGQUIT, &act, NULL);
57 	sigaction(SIGTERM, &act, NULL);
58 	sigaction(SIGINT, &act, NULL);
59   	//sigaction(SIGHUP, &act, NULL);
60   	sigaction(SIGCHLD, &act, NULL);
61 }
62 
Appbar(char * filename)63 Appbar::Appbar(char* filename)
64 {
65 	XSizeHints appbarSizeHints;
66     	CARD32 data[2];
67 
68 	::ab=this;
69 
70 	init_signals();
71 
72 	placement = VERTICAL;
73 	screen_placement = NORTHWEST;
74 	one_click = false;
75 	temp_color=0;
76 
77 	hidden=true;
78 	window_width=0;
79 
80 	if (!(dpy = XOpenDisplay (NULL)))
81 	{
82 		std::cerr << "Can't open display!" << std::endl;
83 		exit(0);
84 	}
85 
86 	screen = DefaultScreen(dpy);
87 	depth = DefaultDepth(dpy, screen);
88 	visual = DefaultVisual(dpy, screen);
89 	root = RootWindow(dpy, screen);
90 
91 	// The to and from structures are used in creating
92 	// the color theme for the main window. This is just
93 	// a default, this is configurable in the rc file.
94 
95 	// Nice shade of gray
96 	from.red   = 0xcc;
97 	from.green = 0xcc;
98 	from.blue  = 0xcc;
99 
100 	// Another nice shade of gray
101 	to.red	 = 0x99;
102 	to.green = 0x99;
103 	to.blue	 = 0x99;
104 
105 	gnome[WIN_STATE]=XInternAtom(dpy, "_WIN_STATE", False);
106   	gnome[WIN_HINTS]=XInternAtom(dpy, "_WIN_HINTS", False);
107   	gnome[WIN_LAYER]=XInternAtom(dpy, "_WIN_LAYER", False);
108 	motif=XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
109 
110 	atom_wm_state  = XInternAtom(dpy, "WM_STATE", False);
111 	atom_wm_protos = XInternAtom(dpy, "WM_PROTOCOLS", False);
112 	atom_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
113 
114 	net_wm_state_skip_taskbar = XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False);
115 	net_wm_state_skip_pager = XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False);
116 	net_wm_state_sticky = XInternAtom(dpy, "_NET_WM_STATE_STICKY", False);
117  	net_wm_strut = XInternAtom(dpy, "_NET_WM_STRUT", False);
118 	net_wm_state_sticky = XInternAtom(dpy, "_NET_WM_STATE_STICKY", False);
119 
120 	//win = XCreateSimpleWindow
121 	//	(dpy, DefaultRootWindow (dpy), 0, 0, 100, 25, 0,
122 	//	 BlackPixel (dpy, DefaultScreen (dpy)),
123 	//	 WhitePixel (dpy, DefaultScreen (dpy)));
124 
125 	XSetWindowAttributes attr;
126 
127 	attr.background_pixel = WhitePixel (dpy, DefaultScreen (dpy));
128 	attr.event_mask = ButtonPressMask   |
129 			  ButtonReleaseMask |
130 			  ExposureMask      |
131 			  EnterWindowMask   |
132 			  LeaveWindowMask   ;
133 
134 	win = XCreateWindow(dpy,
135 			    root,
136 			    0,
137 			    0,
138 			    100,
139 			    25,
140 			    0,
141 			    CopyFromParent,
142 			    InputOutput,
143 			    CopyFromParent,
144 			    CWBackPixel | CWEventMask,
145 			    &attr);
146 
147 	//XSelectInput (dpy, win, ExposureMask    	|
148 	//                        ButtonPressMask 	|
149 	//			ButtonReleaseMask 	|
150 	//			EnterWindowMask 	|
151 	//			LeaveWindowMask);
152 
153 	gnome_win_normal_hints = WIN_HINTS_SKIP_FOCUS   |
154 		          	 WIN_HINTS_SKIP_TASKBAR |
155 		          	 WIN_HINTS_SKIP_WINLIST |
156 			  	 WIN_HINTS_DO_NOT_COVER ;
157 
158 	gnome_win_hints_no_on_top = WIN_HINTS_SKIP_FOCUS   |
159 		          	    WIN_HINTS_SKIP_TASKBAR |
160 		          	    WIN_HINTS_SKIP_WINLIST ;
161 
162     	set_gnome_hint(win, WIN_STATE, WIN_STATE_STICKY);
163 	set_gnome_hint(win, WIN_HINTS, gnome_win_normal_hints);
164     	set_gnome_hint(win, WIN_LAYER, 0);
165 
166     	mwm_hints.flags=MWM_DECORATIONS;
167 	mwm_hints.decorations=0;
168     	set_mwm_hints(win, &mwm_hints);
169 
170 	screen_width  = WidthOfScreen(ScreenOfDisplay(dpy, screen));
171 	screen_height = HeightOfScreen(ScreenOfDisplay(dpy, screen));
172 
173 	image_control = new BImageControl(dpy, depth, root, screen, visual);
174 
175 	// Default color theme style
176 	unsigned long style=0;
177 	style = BImage_Flat | BImage_Gradient | BImage_Diagonal | BImage_Bevel1;
178 	//style = BImage_Flat | BImage_Solid | BImage_Bevel1;
179 
180 	win_pix = None;
181 
182 	gc = XCreateGC (dpy, win, 0, NULL);
183 
184 	XColor xcl;
185 	unsigned int i, j;
186 
187 	i = j = 0;
188 	do
189 	{
190 		xcl.red = cols[i];
191 		i++;
192 		xcl.green = cols[i];
193 		i++;
194 		xcl.blue = cols[i];
195 		i++;
196 		XAllocColor (dpy, DefaultColormap (dpy, screen), &xcl);
197 		palette[j] = xcl.pixel;
198 		j++;
199 	}
200 	while (j < PALETTE_COUNT);
201 
202 	iconList = new std::list<Icon *>;
203 
204 	std::string appbar_rc_file = (std::string) filename; // APPBAR_RC_FILE;
205 
206 	std::cout << "Appbar is using rc file: " << appbar_rc_file << std::endl;
207 
208 	appbarConfig = new Scanner((char*) appbar_rc_file.c_str());
209 	parseAppbarConfig(appbarConfig);
210 
211 	if(iconList->empty())
212 	{
213 		std::cerr << "appbar.rc contains no icons, using defaults." << std::endl;
214 
215 		Icon *t = new Icon(dpy, "images/terminal.xpm", win);
216 		t->setExecuteCommand("xterm");
217 		iconList->push_back(t);
218 	}
219 
220 	if(placement==HORIZONTAL)
221 		horizontalBarIconPlacement();
222 
223 	if(placement==VERTICAL)
224 		verticalBarIconPlacement();
225 
226 	win_pix = image_control->renderImage(
227 		window_width,
228 		window_height,
229 		style,
230 	       	to,
231 	      	from);
232 
233 	XSetWindowBackgroundPixmap(dpy, win, win_pix);
234 
235 	XResizeWindow(dpy,win, window_width , window_height);
236 
237  	appbarSizeHints.flags = PPosition | PSize;
238         appbarSizeHints.x = 0;
239         appbarSizeHints.y = 0;
240 	appbarSizeHints.width = window_width;
241 	appbarSizeHints.height = window_height;
242 
243 	//XSetNormalHints(dpy, win, &appbarSizeHints);
244 
245 	XChangeProperty (dpy, win, XA_WM_NORMAL_HINTS,
246 			XA_WM_SIZE_HINTS, 32, PropModeReplace,
247 		(unsigned char *) &appbarSizeHints, sizeof (XSizeHints) / 4);
248 
249 	appbarScreenPlacement();  // Move to right place before map?
250 
251 	XMapWindow(dpy,win);
252 
253     	data[0] = NormalState;
254     	data[1] = None; /* Icon? We don't need no steenking icon. */
255 
256     	XChangeProperty(dpy, win, atom_wm_state, atom_wm_state,
257         	32, PropModeReplace, (unsigned char *)data, 2);
258 
259 	doEventLoop();
260 }
261 
~Appbar()262 Appbar::~Appbar()
263 {
264 	quit();
265 }
266 
267 // This function takes care of determing the position of the appbar
268 // and whether it's shaded or not.
appbarScreenPlacement()269 void Appbar::appbarScreenPlacement()
270 {
271 	int new_x=0, new_y=0;
272 
273 	switch (screen_placement)
274 	{
275 		case NORTHEAST:
276 		{
277 			if(placement==HORIZONTAL)
278 			{
279 				if(hidden)
280 				{
281 					new_x = screen_width - window_width;
282 					new_y = 0;
283 					hidden=false;
284 
285 					setTopStrut();
286 				}
287 				else
288 				{
289 					new_x = screen_width - 10;
290 					new_y = 0;
291 					hidden=true;
292 
293 					turnOffStrut();
294 				}
295 			}
296 
297 			if(placement==VERTICAL)
298 			{
299 				if(hidden)
300 				{
301 					new_x = screen_width - window_width;
302 					new_y = 0;
303 
304 					hidden=false;
305 
306 					setRightStrut();
307 				}
308 				else
309 				{
310 					new_x = screen_width - window_width;
311 					new_y = -(window_height-9);
312 
313 					hidden=true;
314 
315 					turnOffStrut();
316 				}
317 			}
318 		}
319 		break;
320 
321 		case NORTHWEST:
322 			if(placement==HORIZONTAL)
323 			{
324 				if(hidden)
325 				{
326 					new_x=0;
327 					new_y=0;
328 					hidden=false;
329 
330 					setTopStrut();
331 				}
332 				else
333 				{
334 					new_x = -(window_width-9);
335 					new_y = 0;
336 					hidden=true;
337 
338 					turnOffStrut();
339 				}
340 			}
341 			else
342 			if(placement==VERTICAL)
343 			{
344 				if(hidden)
345 				{
346 					new_x=0;
347 					new_y=0;
348 
349 					hidden=false;
350 
351 					setLeftStrut();
352 				}
353 				else
354 				{
355 					new_x = 0;
356 					new_y = -(window_height-9);
357 
358 					hidden=true;
359 
360 					turnOffStrut();
361 				}
362 			}
363 		break;
364 
365 		case SOUTHEAST:
366 			if(placement==HORIZONTAL)
367 			{
368 				if(hidden)
369 				{
370 					new_x = screen_width - window_width;
371 					new_y = screen_height - window_height;
372 					hidden=false;
373 
374 					setBottomStrut();
375 				}
376 				else
377 				{
378 					new_x = screen_width - 10;
379 					new_y = screen_height - window_height;
380 					hidden=true;
381 
382 					turnOffStrut();
383 				}
384 			}
385 			else
386 			if(placement==VERTICAL)
387 			{
388 				if(hidden)
389 				{
390 					new_x = screen_width - window_width;
391 					new_y = screen_height - window_height;
392 					hidden=false;
393 
394 					setRightStrut();
395 				}
396 				else
397 				{
398 					new_x = screen_width - window_width;
399 					new_y = (screen_height - 10);
400 					hidden=true;
401 
402 					turnOffStrut();
403 				}
404 			}
405 		break;
406 
407 		case SOUTHWEST:
408 			if(placement==HORIZONTAL)
409 			{
410 				if(hidden)
411 				{
412 					new_x = 0;
413 					new_y = screen_height - window_height;
414 					hidden=false;
415 
416 					setBottomStrut();
417 				}
418 				else
419 				{
420 					new_x = -(window_width-10);
421 					new_y = screen_height - window_height;
422 					hidden=true;
423 
424 					turnOffStrut();
425 				}
426 			}
427 			else
428 			if(placement==VERTICAL)
429 			{
430 				if(hidden)
431 				{
432 					new_x = 0;
433 					new_y = screen_height - window_height;
434 					hidden=false;
435 
436 					setLeftStrut();
437 				}
438 				else
439 				{
440 					new_x = 0;
441 					new_y = (screen_height - 10);
442 					hidden=true;
443 
444 					turnOffStrut();
445 				}
446 			}
447 		break;
448 	}
449 
450 	XMoveWindow(dpy,win, new_x, new_y);
451 }
452 
453 // Positions icons horizontally on the appbar and resizes
454 // it accordingly.
horizontalBarIconPlacement()455 void Appbar::horizontalBarIconPlacement()
456 {
457 	std::list<Icon *>::iterator it;
458 	window_width = 1;
459 	window_width= 5;
460 
461 	if ( (screen_placement == NORTHWEST) || (screen_placement == SOUTHWEST) )
462 		window_width=5;
463 
464 	if ( (screen_placement == NORTHEAST) || (screen_placement == SOUTHEAST) )
465 		window_width=13;
466 
467 	for(it = iconList->begin(); it != iconList->end(); it++)
468 	{
469 		XMapWindow(dpy, (*it)->getIconWindow());
470 		XMoveWindow(dpy, (*it)->getIconWindow(), window_width, 5);
471 		if (window_height < (int) ((*it)->getHeight() +12))
472 			window_height = (*it)->getHeight() +12;
473 		window_width+=(*it)->getWidth() + 6;
474 	}
475 	window_width += 15;
476 }
477 
478 // Positions icons vertically on the appbar and resizes
479 // it accordingly.
480 //
481 // This function can be written better, its still not very
482 // well thought out. Icon wrapping is not really how I'd
483 // like it to be.
verticalBarIconPlacement()484 void Appbar::verticalBarIconPlacement()
485 {
486 	std::list<Icon *>::iterator it;
487 	window_width = 1;
488 	window_height= 5;
489 
490 	if ( (screen_placement == NORTHWEST) || (screen_placement == NORTHEAST) )
491 		window_height=5;
492 
493 	if ( (screen_placement == SOUTHWEST) || (screen_placement == SOUTHEAST) )
494 		window_height=13;
495 
496 	for(it = iconList->begin(); it != iconList->end(); it++)
497 	{
498 		XMapWindow(dpy, (*it)->getIconWindow());
499 		XMoveWindow(dpy, (*it)->getIconWindow(), 5, window_height);
500 		if (window_width < (int) ((*it)->getWidth() +12))
501 			window_width = (*it)->getWidth() +12;
502 		window_height+=(*it)->getHeight() + 6;
503 	}
504 	window_height += 15;
505 }
506 
doEventLoop()507 void Appbar::doEventLoop()
508 {
509 	XEvent ev;
510 
511 	for (;;)
512 	{
513 		XNextEvent(dpy, &ev);
514 
515 		Icon* ico=NULL;
516 
517 		switch(ev.type)
518 		{
519 			case ButtonPress:
520 				ico = findIconWindow(ev.xbutton.window);
521 
522 				if (ico)
523 				{
524 					ico->updateXYPos();
525 					draw3DRectSunken(win, ico->getX()-1,
526 					   	   ico->getY()-1,
527 						   ico->getWidth()+1,
528 						   ico->getHeight()+1
529 						);
530 
531 				}
532 
533 			break;
534 
535 			case ButtonRelease:
536 
537 				switch(ev.xbutton.button)
538 				{
539 					case Button1:
540 						ico = findIconWindow(ev.xbutton.window);
541 
542 						if (ico)
543 						{
544 							ico->updateXYPos();
545 							draw3DRectRaised(win, ico->getX()-1,
546 					   	   		ico->getY()-1,
547 						   		ico->getWidth()+1,
548 						   		ico->getHeight()+1
549 								);
550 
551 							ico->executeCommand();
552 						}
553 
554 						if (ev.xbutton.window == win)
555 						{
556 							if(placement==HORIZONTAL)
557 							{
558 								if ( (screen_placement == NORTHWEST) || (screen_placement == SOUTHWEST) )
559 									if(ev.xbutton.x >= window_width-10) appbarScreenPlacement();
560 
561 								if ( (screen_placement == NORTHEAST) || (screen_placement == SOUTHEAST) )
562 									if(ev.xbutton.x <= 10) appbarScreenPlacement();
563 							}
564 
565 							if(placement==VERTICAL)
566 							{
567 								if ( (screen_placement == NORTHWEST) || (screen_placement == NORTHEAST) )
568 									if(ev.xbutton.y >= window_height-10) appbarScreenPlacement();
569 
570 								if ( (screen_placement == SOUTHWEST) || (screen_placement == SOUTHEAST) )
571 									if(ev.xbutton.y <= 10) appbarScreenPlacement();
572 							}
573 						}
574 
575 					break;
576 
577 					case Button2:
578 						if (ev.xbutton.window == win)
579 						{
580 							if(placement==HORIZONTAL)
581 							{
582 								if ( (screen_placement == NORTHWEST) || (screen_placement == SOUTHWEST) )
583 									if(ev.xbutton.x >= window_width-10) quit();
584 
585 								if ( (screen_placement == NORTHEAST) || (screen_placement == SOUTHEAST) )
586 									if(ev.xbutton.x <= 10) quit();
587 							}
588 
589 							if(placement==VERTICAL)
590 							{
591 								if ( (screen_placement == NORTHWEST) || (screen_placement == NORTHEAST) )
592 									if(ev.xbutton.y >= window_height-10) quit();
593 
594 								if ( (screen_placement == SOUTHWEST) || (screen_placement == SOUTHEAST) )
595 									if(ev.xbutton.y <= 10) quit();
596 							}
597 						}
598 					break;
599 
600 					//case Button3:
601 					//
602 					// Possibly allow for arbitrary execution of something later
603 					// maybe for like a config tool to pop up. Anyway Mark wants it.
604 					//
605 					//break;
606 
607 					}
608 			if (one_click) quit();
609 			break;
610 
611 			//case DestroyNotify:
612 			//	quit();
613 			//break;
614 
615 			case ClientMessage:
616 				if (ev.xclient.message_type == atom_wm_protos)
617 				{
618 					if(ev.xclient.data.l[0]== (long) atom_wm_delete)
619 						delete this;
620 				}
621 			break;
622 
623 			case EnterNotify:
624 				ico = findIconWindow(ev.xcrossing.window);
625 
626 				if(ico)
627 				{
628 				   ico->updateXYPos();
629 				   draw3DRectRaised(win, ico->getX()-1,
630 					   	   ico->getY()-1,
631 						   ico->getWidth()+1,
632 						   ico->getHeight()+1
633 						);
634 				}
635 
636 			break;
637 
638 			case LeaveNotify:
639 				ico = findIconWindow(ev.xcrossing.window);
640 
641 				if (ico)
642 				{
643 					XClearWindow(dpy, win);
644 
645 					if(placement==HORIZONTAL)
646 						drawHorizontalBarGrill();
647 
648 					if(placement==VERTICAL)
649 						drawVerticalBarGrill();
650 				}
651 			break;
652 
653 			case Expose:
654 				if(placement==HORIZONTAL)
655 					drawHorizontalBarGrill();
656 
657 				if(placement==VERTICAL)
658 					drawVerticalBarGrill();
659 			break;
660 		}
661 	}
662 }
663 
set_gnome_hint(Window w,int a,long value)664 void Appbar::set_gnome_hint(Window w, int a, long value)
665 {
666   XChangeProperty(dpy, w, gnome[a], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&value, 1);
667 }
668 
set_mwm_hints(Window w,PropMwmHints * hints)669 void Appbar::set_mwm_hints(Window w, PropMwmHints *hints)
670 {
671   XChangeProperty(dpy, w, motif, motif, 32, PropModeReplace, (unsigned char *)hints, sizeof(*hints));
672 }
673 
set_foreground(int index)674 void Appbar::set_foreground (int index)
675 {
676 	XSetForeground (dpy, gc, palette[index]);
677 }
678 
draw_dot(Window win,int x,int y)679 void Appbar::draw_dot (Window win, int x, int y)
680 {
681 	set_foreground (4);
682 	XDrawPoint (dpy, win, gc, x, y);
683 	set_foreground (3);
684 	XDrawPoint (dpy, win, gc, x + 1, y + 1);
685 }
686 
draw3DLine(Window win,int style,int x1,int y1,int x2,int y2)687 void Appbar::draw3DLine(Window win, int style, int x1, int y1, int x2, int y2)
688 {
689 	set_foreground(3);
690 	XDrawLine(dpy, win, gc, x1, y1, x2, y2);
691 	set_foreground(4);
692 
693   	if (style==HORIZONTAL)
694   	 	XDrawLine(dpy, win, gc, x1, y1-1, x2, y2-1);
695 
696   	if (style==VERTICAL)
697     		XDrawLine(dpy, win, gc, x1-1, y1, x2-1, y2);
698 }
699 
draw3DRectSunken(Window win,int x,int y,int h,int w)700 void Appbar::draw3DRectSunken(Window win, int x, int y, int h, int w)
701 {
702  	set_foreground(4);
703   	XDrawLine(dpy, win, gc, x, y, x, y+h);
704   	XDrawLine(dpy, win, gc, x, y, x+w, y);
705 
706   	set_foreground(3);
707   	XDrawLine(dpy, win, gc,   x+w, y, x+w, y+h);
708   	XDrawLine(dpy, win, gc,   x, y+h, x+w, y+h);
709 }
710 
draw3DRectRaised(Window win,int x,int y,int h,int w)711 void Appbar::draw3DRectRaised(Window win, int x, int y, int h, int w)
712 {
713   	set_foreground(3);
714   	XDrawLine(dpy, win, gc, x, y, x, y+h);
715   	XDrawLine(dpy, win, gc, x, y, x+w, y);
716 
717   	set_foreground(4);
718   	XDrawLine(dpy, win, gc,   x+w, y, x+w, y+h);
719   	XDrawLine(dpy, win, gc,   x, y+h, x+w, y+h);
720 }
721 
drawHorizontalBarGrill()722 void Appbar::drawHorizontalBarGrill()
723 {
724 	if ( (screen_placement == NORTHWEST) || (screen_placement == SOUTHWEST) )
725 	{
726 		draw3DLine(win, VERTICAL,
727 			window_width-10,0,
728 			window_width-10, window_height);
729 
730 		drawVerticalGrill(win, window_width-10, window_height);
731 	}
732 
733 	if ( (screen_placement == NORTHEAST) || (screen_placement == SOUTHEAST) )
734 	{
735 		draw3DLine(win, VERTICAL,
736 			10, 0,
737 			10, window_height);
738 
739 		drawVerticalGrill(win, 0, window_height);
740 	}
741 }
742 
drawVerticalBarGrill()743 void Appbar::drawVerticalBarGrill()
744 {
745 	if ( (screen_placement == SOUTHWEST) || (screen_placement == SOUTHEAST) )
746 	{
747 		draw3DLine(win, HORIZONTAL,
748 		0, 10,
749 		window_width, 10);
750 
751 		drawHoriontalGrill(win, 0, window_width);
752 	}
753 
754 	if ( (screen_placement == NORTHEAST) || (screen_placement == NORTHWEST) )
755 	{
756 		draw3DLine(win, HORIZONTAL,
757 		0, window_height-10,
758 		window_width, window_height-10);
759 
760 		drawHoriontalGrill(win, window_height-10, window_width);
761 	}
762 }
763 
drawVerticalGrill(Window win,int x,int height)764 void Appbar::drawVerticalGrill (Window win, int x, int height)
765 {
766 	int y = 0;
767 	while (y < height - 5)
768 	{
769 		y += 3;
770 		draw_dot (win, x + 3, y);
771 		draw_dot (win, x + 6, y);
772 	}
773 }
774 
drawHoriontalGrill(Window win,int y,int width)775 void Appbar::drawHoriontalGrill(Window win, int y, int width)
776 {
777 	int x = 0;
778 	while (x < width - 5)
779 	{
780 		x += 3;
781 		draw_dot (win, x, y + 3);
782 		draw_dot (win, x, y + 6);
783 	}
784 }
785 
findIconWindow(Window win)786 Icon* Appbar::findIconWindow(Window win)
787 {
788 	std::list<Icon *>::iterator it;
789 	for(it = iconList->begin(); it != iconList->end() ; it++)
790 	{
791 		if((*it)->getIconWindow() == win)
792 			return ((*it));
793 	}
794 
795 	return NULL;
796 }
797 
imageKeyword(Scanner * s)798 bool Appbar::imageKeyword(Scanner *s)
799 {
800 	std::string t="image";
801 	std::string a="";
802 
803 	if ( s->match ( t ) )
804 	{
805 		t = "=";
806 
807 		if ( s->match ( t ) )
808 		{
809 			while (! s->match( ";" ) )
810 			{
811 				a += s->currentToken();
812 
813 				s->getNextToken();
814 			}
815 
816 			char *t = (char*) a.c_str();
817 			current_icon->loadPixmap(t);
818 
819 			return true;
820 		}
821 	}
822 
823 	return false;
824 }
825 
executeKeyword(Scanner * s)826 bool Appbar::executeKeyword(Scanner *s)
827 {
828 	std::string t="execute";
829 	std::string a="";
830 
831 	if ( s->match ( t ) )
832 	{
833 		t = "=";
834 
835 		if ( s->match ( t ) )
836 		{
837 			if(s->currentToken() == "}")
838 			{
839 				std::cerr << "parse error: cannot determine execute command, using default (xterm)." << std::endl;
840 				current_icon->setExecuteCommand("xterm");
841 				return true;
842 			}
843 
844 			while (! s->match( ";" ) )
845 			{
846 				a += s->currentToken();
847 				a += " "; // put whitespace back that may
848 					  // have gotten eaten by the scanner.
849 					  // This is probably not the best
850 					  // place to do it. The scanner should
851 					  // be smarter.
852 
853 				s->getNextToken();
854 			}
855 
856 			char *t = (char*)a.c_str();
857 			current_icon->setExecuteCommand(t);
858 
859 			return true;
860 		}
861 	}
862 
863 	return false;
864 }
865 
iconKeyword(Scanner * s)866 bool Appbar::iconKeyword(Scanner *s)
867 {
868 	std::string t="icon";
869 
870 	if ( s->match ( t ) )
871 	{
872 		t = "{";
873 
874 		if ( s->match ( t ) )
875 		{
876 			current_icon = new Icon(dpy, win);
877 
878 			imageKeyword(s);
879 			executeKeyword(s);
880 
881 			iconList->push_back(current_icon);
882 
883 			t = "}";
884 
885 			if ( s->match ( t ) )
886 			{
887 				return true;
888 			}
889 		}
890 
891 	}
892 
893 	return false;
894 }
895 
oneclickKeyword(Scanner * s)896 bool Appbar::oneclickKeyword(Scanner *s)
897 {
898 	std::string t="one_click";
899 
900 	if ( s->match ( t ) )
901 	{
902 		one_click=true;
903 		return true;
904 	}
905 
906 	return false;
907 }
908 
northeastKeyword(Scanner * s)909 bool Appbar::northeastKeyword(Scanner *s)
910 {
911 	std::string t="northeast_placement";
912 
913 	if ( s->match ( t ) )
914 	{
915 		screen_placement=NORTHEAST;
916 		return true;
917 	}
918 
919 	return false;
920 }
921 
northwestKeyword(Scanner * s)922 bool Appbar::northwestKeyword(Scanner *s)
923 {
924 	std::string t="northwest_placement";
925 
926 	if ( s->match ( t ) )
927 	{
928 		screen_placement=NORTHWEST;
929 		return true;
930 	}
931 
932 	return false;
933 }
934 
southeastKeyword(Scanner * s)935 bool Appbar::southeastKeyword(Scanner *s)
936 {
937 	std::string t="southeast_placement";
938 
939 	if ( s->match ( t ) )
940 	{
941 		screen_placement=SOUTHEAST;
942 		return true;
943 	}
944 
945 	return false;
946 }
947 
southwestKeyword(Scanner * s)948 bool Appbar::southwestKeyword(Scanner *s)
949 {
950 	std::string t="southwest_placement";
951 
952 	if ( s->match ( t ) )
953 	{
954 		screen_placement=SOUTHWEST;
955 		return true;
956 	}
957 
958 	return false;
959 }
960 
horizontalKeyword(Scanner * s)961 bool Appbar::horizontalKeyword(Scanner *s)
962 {
963 	std::string t="horizontal_placement";
964 
965 	if ( s->match ( t ) )
966 	{
967 		placement=HORIZONTAL;
968 		return true;
969 	}
970 
971 	return false;
972 }
973 
verticalKeyword(Scanner * s)974 bool Appbar::verticalKeyword(Scanner *s)
975 {
976 	std::string t="vertical_placement";
977 
978 	if ( s->match ( t ) )
979 	{
980 		placement=VERTICAL;
981 		return true;
982 	}
983 
984 	return false;
985 }
986 
rgbKeywords(Scanner * s)987 bool Appbar::rgbKeywords(Scanner *s)
988 {
989 	std::string t="";
990 	std::string a="";
991 
992 	if ( s->match ( "red" ) || s->match ( "green" ) || s->match ( "blue" ) )
993 	{
994 		t = "=";
995 
996 		if ( s->match ( t ) )
997 		{
998 			while (! s->match( ";" ) )
999 			{
1000 				a += s->currentToken();
1001 
1002 				s->getNextToken();
1003 			}
1004 
1005 			temp_color = strtol(a.c_str(),0,16);
1006 
1007 			return true;
1008 		}
1009 	}
1010 
1011 	return false;
1012 }
1013 
fromKeyword(Scanner * s)1014 bool Appbar::fromKeyword(Scanner *s)
1015 {
1016 	std::string t="";
1017 
1018 	if ( s->match ( "appbar_color_from" ) )
1019 	{
1020 		t = "{";
1021 
1022 		if ( s->match ( t ) )
1023 		{
1024 			//cout << s->currentToken() << endl;
1025 
1026 			rgbKeywords(s);
1027 			from.red = temp_color;
1028 
1029 			rgbKeywords(s);
1030 			from.green = temp_color;
1031 
1032 			rgbKeywords(s);
1033 			from.blue = temp_color;
1034 
1035 			t = "}";
1036 
1037 			if ( s->match ( t ) )
1038 			{
1039 				return true;
1040 			}
1041 		}
1042 
1043 	}
1044 
1045 	return false;
1046 }
1047 
toKeyword(Scanner * s)1048 bool Appbar::toKeyword(Scanner *s)
1049 {
1050 	std::string t="";
1051 
1052 	if ( s->match ( "appbar_color_to" ) )
1053 	{
1054 		t = "{";
1055 
1056 		if ( s->match ( t ) )
1057 		{
1058 			//cout << s->currentToken() << endl;
1059 
1060 			rgbKeywords(s);
1061 			to.red = temp_color;
1062 
1063 			rgbKeywords(s);
1064 			to.green = temp_color;
1065 
1066 			rgbKeywords(s);
1067 			to.blue = temp_color;
1068 
1069 			t = "}";
1070 
1071 			if ( s->match ( t ) )
1072 			{
1073 				return true;
1074 			}
1075 		}
1076 
1077 	}
1078 
1079 	return false;
1080 }
1081 
parseAppbarConfig(Scanner * s)1082 void Appbar::parseAppbarConfig(Scanner* s)
1083 {
1084 	while(! s->eof())
1085 	{
1086 		s->getNextToken();
1087 
1088 		while ( iconKeyword(s) 	     ||
1089 			verticalKeyword(s)   ||
1090 			horizontalKeyword(s) ||
1091 			oneclickKeyword(s) ||
1092 			northeastKeyword(s)  ||
1093 			northwestKeyword(s)  ||
1094 			southeastKeyword(s)  ||
1095 			southwestKeyword(s)  ||
1096 			toKeyword(s)	     ||
1097 			fromKeyword(s)
1098 		) {
1099 			if(s->eof()) return;
1100 		}
1101 
1102 	}
1103 }
1104 
quit()1105 void Appbar::quit()
1106 {
1107 	std::cerr << "Performing Appbar cleanup!" << std::endl;
1108 
1109 	iconList->clear();
1110 	delete iconList;
1111 
1112 	image_control->removeImage( win_pix );
1113 	delete image_control;
1114 
1115 	delete current_icon;
1116 	delete appbarConfig;
1117 
1118 	XFreeGC(dpy, gc);
1119 	XDestroyWindow (dpy, win);
1120 	XCloseDisplay(dpy);
1121 
1122 	exit(0);
1123 }
1124 
turnOffStrut()1125 void Appbar::turnOffStrut()
1126 {
1127   	XDeleteProperty(dpy, win, net_wm_strut);
1128 
1129 	// This time we don't want always on top hint set.
1130 	set_gnome_hint(win, WIN_HINTS, gnome_win_hints_no_on_top);
1131 }
1132 
setLeftStrut()1133 void Appbar::setLeftStrut()
1134 {
1135 	CARD32 strut[] = { window_width+2,0,0,0 };
1136 	XChangeProperty (dpy, win, net_wm_strut, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &strut, 4);
1137 
1138 	set_gnome_hint(win, WIN_HINTS, gnome_win_normal_hints);
1139 }
1140 
setRightStrut()1141 void Appbar::setRightStrut()
1142 {
1143 	CARD32 strut[] = { 0,window_width+3,0,0 };
1144 	XChangeProperty (dpy, win, net_wm_strut, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &strut, 4);
1145 
1146 	set_gnome_hint(win, WIN_HINTS, gnome_win_normal_hints);
1147 }
1148 
setTopStrut()1149 void Appbar::setTopStrut()
1150 {
1151 	CARD32 strut[] = { 0,0,window_height+2,0 };
1152 	XChangeProperty (dpy, win, net_wm_strut, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &strut, 4);
1153 
1154 	set_gnome_hint(win, WIN_HINTS, gnome_win_normal_hints);
1155 }
1156 
setBottomStrut()1157 void Appbar::setBottomStrut()
1158 {
1159 	CARD32 strut[] = { 0,0,0,window_height+2 };
1160 	XChangeProperty (dpy, win, net_wm_strut, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &strut, 4);
1161 
1162 	set_gnome_hint(win, WIN_HINTS, gnome_win_normal_hints);
1163 }
1164