cvsimport
[fvwm.git] / modules / FvwmTaskBar / Start.c
blobd0ee52a1109f88abb22598093db3e4cfa85ff036
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 /* Start ;-) button handling */
19 #include "config.h"
21 #include <X11/Xlib.h>
22 #include <stdio.h>
24 #include "libs/fvwmlib.h"
25 #include "libs/Flocale.h"
26 #include "libs/Picture.h"
27 #include "libs/Module.h"
28 #include "libs/Parse.h"
29 #include "libs/Strings.h"
30 #include "ButtonArray.h"
31 #include "Mallocs.h"
32 #include "Start.h"
34 extern Display *dpy;
35 extern Window Root, win;
36 extern FlocaleFont *FButtonFont, *FSelButtonFont;
37 extern ModuleArgs *module;
38 extern char *ImagePath;
40 Button *StartButton;
41 Bool NoDefaultStartButton = False;
42 int StartAndLaunchButtonsWidth = 0;
43 int StartAndLaunchButtonsHeight = 0;
44 int WindowButtonsLeftMargin = 4; /* default value is 4 */
45 int WindowButtonsRightMargin = 2; /* default value is 2 */
46 int StartButtonRightMargin = 0; /* default value is 0 */
47 int has_wb_left_margin = 0;
48 int has_wb_right_margin = 0;
49 Bool StartButtonOpensAboveTaskBar = False;
50 char *StartName = NULL,
51 *StartCommand = NULL,
52 *StartPopup = NULL,
53 *StartIconName = NULL;
55 StartAndLaunchButtonItem *First_Start_Button = NULL;
56 StartAndLaunchButtonItem *Last_Start_Button = NULL;
58 static char *startopts[] =
60 "StartName",
61 "StartMenu",
62 "StartIcon",
63 "StartCommand",
64 "NoDefaultStartButton",
65 "Button",
66 "WindowButtonsLeftMargin",
67 "WindowButtonsRightMargin",
68 "StartButtonRightMargin",
69 NULL
72 Bool StartButtonParseConfig(char *tline)
74 char *rest;
75 char *option;
76 int i, j, k;
77 int titleRecorded = 0, iconRecorded = 0;
78 char *tokens[100]; /* This seems really big */
79 StartAndLaunchButtonItem *tempPtr;
80 int mouseButton;
81 char **tmpStrPtr;
83 option = tline + module->namelen+1;
84 i = GetTokenIndex(option, startopts, -1, &rest);
85 while (*rest && *rest != '\n' && isspace(*rest))
87 rest++;
89 switch(i)
91 case 0: /* StartName */
92 if (First_Start_Button == NULL)
94 First_Start_Button = Last_Start_Button =
95 (StartAndLaunchButtonItem*)safemalloc(
96 sizeof(StartAndLaunchButtonItem));
97 StartAndLaunchButtonItemInit(First_Start_Button);
98 First_Start_Button->isStartButton = True;
100 else if (First_Start_Button->isStartButton == False)
102 /* shortcut button has been declared before start
103 * button */
104 tempPtr = (StartAndLaunchButtonItem*)safemalloc(
105 sizeof(StartAndLaunchButtonItem));
106 StartAndLaunchButtonItemInit(tempPtr);
107 tempPtr->tail = First_Start_Button;
108 First_Start_Button = tempPtr;
109 First_Start_Button->isStartButton = True;
111 else if (First_Start_Button->buttonCaption != NULL)
113 /* declarin caption twice, ignore */
114 break;
116 CopyString(&(First_Start_Button->buttonCaption), rest);
117 break;
118 case 1: /* StartMenu */
119 rest = ParseButtonOptions(rest, &mouseButton);
120 if (First_Start_Button == NULL)
122 First_Start_Button = Last_Start_Button =
123 (StartAndLaunchButtonItem*)safemalloc(
124 sizeof(StartAndLaunchButtonItem));
125 StartAndLaunchButtonItemInit(First_Start_Button);
126 First_Start_Button->isStartButton = True;
128 else if (First_Start_Button->isStartButton == False)
130 /* shortcut button has been declared before start
131 * button */
132 tempPtr = (StartAndLaunchButtonItem*) safemalloc(
133 sizeof(StartAndLaunchButtonItem));
134 StartAndLaunchButtonItemInit(tempPtr);
135 tempPtr->tail = First_Start_Button;
136 First_Start_Button = tempPtr;
137 First_Start_Button->isStartButton = True;
139 tmpStrPtr = (mouseButton ?
140 &(First_Start_Button->buttonCommands[mouseButton-1])
142 &(First_Start_Button->buttonCommand));
143 if (*tmpStrPtr)
145 /* declaring command twice, ignore */
146 break;
148 CopyString(tmpStrPtr, rest);
149 break;
150 case 2: /* StartIcon */
151 if (First_Start_Button == NULL)
153 First_Start_Button = Last_Start_Button =
154 (StartAndLaunchButtonItem*)safemalloc(
155 sizeof(StartAndLaunchButtonItem));
156 StartAndLaunchButtonItemInit(First_Start_Button);
157 First_Start_Button->isStartButton = True;
159 else if (First_Start_Button->isStartButton == False)
161 /* shortcut button has been declared before start
162 * button */
163 tempPtr = (StartAndLaunchButtonItem*) safemalloc(
164 sizeof(StartAndLaunchButtonItem));
165 StartAndLaunchButtonItemInit(tempPtr);
166 tempPtr->tail = First_Start_Button;
167 First_Start_Button = tempPtr;
168 First_Start_Button->isStartButton = True;
170 else if (First_Start_Button->buttonIconFileName != NULL)
172 /* declaring icon twice, ignore */
173 break;
175 CopyString(&(First_Start_Button->buttonIconFileName), rest);
176 break;
177 case 3: /* StartCommand */
178 rest = ParseButtonOptions(rest, &mouseButton);
179 if (First_Start_Button == NULL)
181 First_Start_Button = Last_Start_Button =
182 (StartAndLaunchButtonItem*)safemalloc(
183 sizeof(StartAndLaunchButtonItem));
184 StartAndLaunchButtonItemInit(First_Start_Button);
185 First_Start_Button->isStartButton = True;
187 else if (First_Start_Button->isStartButton == False)
189 /* shortcut button has been declared before start
190 * button */
191 tempPtr = (StartAndLaunchButtonItem*)safemalloc(
192 sizeof(StartAndLaunchButtonItem));
193 StartAndLaunchButtonItemInit(tempPtr);
194 tempPtr->tail = First_Start_Button;
195 First_Start_Button = tempPtr;
196 First_Start_Button->isStartButton = True;
198 tmpStrPtr =
199 (mouseButton ?
200 &(First_Start_Button->buttonStartCommands[mouseButton-1]) :
201 &(First_Start_Button->buttonStartCommand));
202 if (*tmpStrPtr)
204 /* declaring command twice, ignore */
205 break;
207 CopyString(tmpStrPtr, rest);
208 break;
209 case 4: /* NoDefaultStartButton */
210 NoDefaultStartButton = True;
211 break;
212 case 5: /* Button */
213 if (Last_Start_Button == NULL)
215 First_Start_Button = Last_Start_Button =
216 (StartAndLaunchButtonItem*)safemalloc(
217 sizeof(StartAndLaunchButtonItem));
219 else
221 Last_Start_Button->tail =
222 (StartAndLaunchButtonItem*) safemalloc(
223 sizeof(StartAndLaunchButtonItem));
224 Last_Start_Button = Last_Start_Button->tail;
227 StartAndLaunchButtonItemInit(Last_Start_Button);
228 j=0;
229 titleRecorded = iconRecorded = 0;
231 char *strtok_ptr = 0;
233 tokens[j++] = strtok_r(rest, ",", &strtok_ptr);
234 while((tokens[j++] = strtok_r(NULL, ",", &strtok_ptr)))
236 while(isspace(*(tokens[j-1])))
238 tokens[j-1]+=sizeof(char);
242 j--;
244 for(k=0;k<j;k++)
246 if (strncasecmp(tokens[k], "Title", 5)==0)
248 tokens[j+1] = tokens[k] + ((sizeof(char))*5);
249 while(*(tokens[j+1])==' ')
250 tokens[j+1]+=sizeof(char);
251 CopyString(
252 &(Last_Start_Button->buttonCaption),
253 tokens[j+1]);
254 titleRecorded=1;
256 else if (strncasecmp(tokens[k], "Icon", 4)==0)
258 tokens[j+1] = tokens[k] + ((sizeof(char))*4);
259 while(*(tokens[j+1])==' ')
260 tokens[j+1]+=sizeof(char);
261 CopyString(
262 &(Last_Start_Button->buttonIconFileName),
263 tokens[j+1] );
264 iconRecorded = 1;
266 else if (strncasecmp(tokens[k], "Action", 6)==0)
268 rest = tokens[k] + ((sizeof(char))*6);
269 rest = ParseButtonOptions(rest, &mouseButton);
270 tokens[j+1] = rest;
271 if (mouseButton)
273 tmpStrPtr =
274 &(Last_Start_Button->
275 buttonStartCommands
276 [mouseButton-1]);
278 else
280 tmpStrPtr =
281 &(Last_Start_Button->
282 buttonStartCommand);
284 if (!(*tmpStrPtr))
286 /* don't let them set the same action
287 * twice */
288 CopyString(tmpStrPtr, tokens[j+1]);
292 if (titleRecorded==0)
294 CopyString(&(Last_Start_Button->buttonCaption), "\0");
296 if (iconRecorded==0)
298 CopyString(
299 &(Last_Start_Button->buttonIconFileName),
300 "\0");
302 break;
304 case 6: /* WindowButtonsLeftMargin */
305 if(atoi(rest)>=0)
307 WindowButtonsLeftMargin = atoi(rest);
308 has_wb_left_margin = 1;
310 break;
311 case 7: /* WindowButtonsRightMargin */
312 if(atoi(rest)>=0)
314 WindowButtonsRightMargin = atoi(rest);
315 has_wb_right_margin = 1;
317 break;
318 case 8: /* StartButtonRightMargin */
319 if(atoi(rest)>=0)
321 StartButtonRightMargin = atoi(rest);
323 break;
324 default:
325 /* unknown option */
326 return False;
327 } /* switch */
329 return True;
332 /* Parse and set options for this taskbar button (start or launcher). This
333 * will check for a string of the form (<opt1>,<opt2>...), similar to options
334 * for an FvwmButtons button. The return value is a pointer to the rest of the
335 * config line.
337 * Currently this sets just one option, mouseButton. If no "Mouse <n>" option
338 * is found, mouseButton will be set to 0.
340 char *ParseButtonOptions(char *pos, int *mouseButton)
342 char *token = NULL;
343 char *rest;
344 int i;
345 static char *buttonOptions[] = {"Mouse", NULL};
347 *mouseButton = 0;
348 while (*pos && isspace(*pos))
349 pos++;
350 if (*pos != '(')
351 return pos;
352 pos++;
353 while (*pos && isspace(*pos))
354 pos++;
356 while (*pos && *pos != ')')
358 pos = GetNextToken(pos, &token);
359 if (!token)
360 break;
361 i = GetTokenIndex(token, buttonOptions, 0, NULL);
362 switch (i)
364 case 0: /* Mouse */
365 *mouseButton = strtol(pos, &rest, 10);
366 pos = rest;
367 if (*mouseButton < 1 || *mouseButton > NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
369 fprintf(stderr,"%s: Invalid mouse button %d", module->name,
370 *mouseButton);
371 *mouseButton = 0;
373 break;
375 default:
376 fprintf(stderr,"%s: Invalid taskbar button option '%s'", module->name,
377 token);
379 while (*pos && *pos != ',' && *pos != ')')
380 pos++;
381 if (*pos == ',') {
382 pos++;
383 while (*pos && *pos != ',' && *pos != ')')
384 pos++;
386 free(token);
389 if (*pos)
390 pos++;
391 while (*pos && isspace(*pos))
392 pos++;
393 return pos;
396 void StartButtonInit(int height)
398 FvwmPicture *p = NULL;
399 int pw;
400 FvwmPictureAttributes fpa;
401 StartAndLaunchButtonItem *tempPtr;
403 fpa.mask = FPAM_NO_ALLOC_PIXELS;
405 /* if no start button params were specified, trick the program into
406 * thinking that they were */
407 if (First_Start_Button == NULL && !NoDefaultStartButton)
409 StartButtonParseConfig("*FvwmTaskBarStartName Start");
410 StartButtonParseConfig("*FvwmTaskBarStartMenu RootMenu");
411 StartButtonParseConfig("*FvwmTaskBarStartIcon mini.start.xpm");
413 /* some defaults */
414 if (First_Start_Button && First_Start_Button->isStartButton == True)
416 if (First_Start_Button->buttonCaption == NULL)
417 UpdateString(&(First_Start_Button->buttonCaption), "Start");
418 if (First_Start_Button->buttonIconFileName == NULL)
419 UpdateString(&(First_Start_Button->buttonIconFileName), "mini-start.xpm");
422 tempPtr = First_Start_Button;
424 while(tempPtr != NULL)
426 p = PGetFvwmPicture(
427 dpy, win, ImagePath, tempPtr->buttonIconFileName, fpa);
428 if (p != NULL && strlen(tempPtr->buttonCaption) != 0)
430 /* icon and title */
431 pw = p->width + 12;
433 else if (p != NULL)
435 /* just icon */
436 pw = p->width + 8;
438 else
440 /* just title */
441 pw = 10;
444 tempPtr->buttonItem = (Button *)ButtonNew(
445 tempPtr->buttonCaption, p, BUTTON_UP,0);
446 if (tempPtr->isStartButton)
448 StartButton = tempPtr->buttonItem;
449 tempPtr->width = FlocaleTextWidth(
450 FSelButtonFont, tempPtr->buttonCaption,
451 strlen(tempPtr->buttonCaption)) + pw;
453 else
455 tempPtr->width = FlocaleTextWidth(
456 FButtonFont, tempPtr->buttonCaption,
457 strlen(tempPtr->buttonCaption)) + pw;
459 tempPtr->height = height;
460 StartAndLaunchButtonsWidth += tempPtr->width;
461 tempPtr=tempPtr->tail;
462 PFreeFvwmPictureData(p); /* should not destroy of course */
464 if (First_Start_Button)
466 StartAndLaunchButtonsWidth += StartButtonRightMargin;
467 First_Start_Button->height = height;
468 StartAndLaunchButtonsHeight = First_Start_Button->height;
470 else
472 StartAndLaunchButtonsWidth = 0;
473 StartButtonRightMargin = 0;
474 if (has_wb_left_margin == 0)
476 WindowButtonsLeftMargin = 0;
478 if (has_wb_right_margin == 0)
480 WindowButtonsRightMargin = 0;
485 int StartButtonUpdate(const char *title, int index, int state)
487 int i=0;
488 StartAndLaunchButtonItem *tempPtr = First_Start_Button;
489 #if 0
490 if (title != NULL)
491 ConsoleMessage("Updating StartTitle not supported yet...\n");
492 if(index != -1)
494 for(i=0; i<index; i++)
495 tempPtr = tempPtr->tail;
496 ButtonUpdate(tempPtr->buttonItem, title, state);
498 else
499 while(tempPtr != NULL)
501 ButtonUpdate(tempPtr->buttonItem, title, state);
502 tempPtr = tempPtr->tail;
505 #else
507 if (!First_Start_Button)
509 return 0;
512 if(index != -1)
514 for(i=0; i<index; i++)
515 tempPtr = tempPtr->tail;
516 ButtonUpdate(tempPtr->buttonItem, title, state);
518 else
519 while(tempPtr != NULL)
521 ButtonUpdate(tempPtr->buttonItem, title, state);
522 tempPtr = tempPtr->tail;
525 #endif
526 tempPtr = First_Start_Button;
527 while(tempPtr != NULL)
529 if (tempPtr->buttonItem->needsupdate)
530 return 1;
531 tempPtr = tempPtr->tail;
533 return 0;
537 void StartButtonDraw(int force, XEvent *evp)
539 int tempsum, j, i = 0;
540 StartAndLaunchButtonItem *tempPtr = First_Start_Button;
541 StartAndLaunchButtonItem *tempPtr2 = First_Start_Button;
543 if (!First_Start_Button)
545 return;
548 while(tempPtr != NULL)
550 if(tempPtr->buttonItem->needsupdate || force)
552 tempsum = 0;
553 j=0;
554 tempPtr2 = First_Start_Button;
555 while((tempPtr2 != NULL) && (j<i))
557 tempsum+=tempPtr2->width;
558 tempPtr2 = tempPtr2->tail;
559 j++;
561 if (!(tempPtr->isStartButton))
562 ButtonDraw(
563 tempPtr->buttonItem,
564 tempsum+StartButtonRightMargin, 0,
565 tempPtr->width,
566 First_Start_Button->height, evp);
567 else
568 ButtonDraw(
569 tempPtr->buttonItem,
570 tempsum, 0, tempPtr->width,
571 First_Start_Button->height, evp);
573 tempPtr = tempPtr->tail;
574 i++;
578 /* Returns 1 if in the start or a minibutton, 0 if not; index of button
579 * pressed put in startButtonPressed */
580 int MouseInStartButton(int x, int y, int *whichButton,
581 Bool *startButtonPressed, int *button_x)
583 int i = 0;
584 int tempsum = 0;
586 StartAndLaunchButtonItem *tempPtr = First_Start_Button;
587 *startButtonPressed = False;
589 while(tempPtr != NULL)
591 if (x >= tempsum && x < tempsum+tempPtr->width && y > 0 && y < First_Start_Button->height)
593 *whichButton = i;
594 if (button_x)
596 *button_x = tempsum;
598 if(tempPtr->isStartButton)
599 *startButtonPressed = True;
600 return 1;
602 tempsum += tempPtr->width;
603 tempPtr = tempPtr->tail;
604 i++;
606 *whichButton = -1;
607 return 0;
610 void getButtonCommand(int whichButton, char *tmp, int mouseButton)
612 int i=0;
613 StartAndLaunchButtonItem *tempPtr = First_Start_Button;
615 if (!First_Start_Button)
617 return;
620 for(i=0; i<whichButton; i++)
621 tempPtr = tempPtr->tail;
622 mouseButton--;
624 if (mouseButton < NUMBER_OF_EXTENDED_MOUSE_BUTTONS &&
625 tempPtr->buttonCommands[mouseButton])
626 sprintf(tmp, "Popup %s rectangle $widthx$height+$left+$top 0 -100m",
627 tempPtr->buttonCommands[mouseButton]);
628 else if (mouseButton < NUMBER_OF_EXTENDED_MOUSE_BUTTONS &&
629 tempPtr->buttonStartCommands[mouseButton])
630 sprintf(tmp, "%s", tempPtr->buttonStartCommands[mouseButton]);
631 else if (tempPtr->buttonCommand)
632 sprintf(tmp, "Popup %s rectangle $widthx$height+$left+$top 0 -100m",
633 tempPtr->buttonCommand);
634 else if (tempPtr->buttonStartCommand)
635 sprintf(tmp, "%s", tempPtr->buttonStartCommand);
636 else if (tempPtr->isStartButton)
637 sprintf(tmp, "Popup StartMenu");
638 else
639 sprintf(tmp, "Nop");
642 void StartAndLaunchButtonItemInit(StartAndLaunchButtonItem *item)
644 int i;
646 item->head = NULL;
647 item->tail = NULL;
648 item->index = 0;
649 item->width = 0;
650 item->height = 0;
651 item->isStartButton = False;
652 item->buttonItem = NULL;
653 item->buttonCommand = NULL;
654 item->buttonStartCommand = NULL;
655 item->buttonCaption = NULL;
656 item->buttonIconFileName = NULL;
657 item->buttonToolTip = NULL;
658 for (i=0; i < NUMBER_OF_EXTENDED_MOUSE_BUTTONS; i++)
660 item->buttonCommands[i] = NULL;
661 item->buttonStartCommands[i] = NULL;