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 */
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"
35 extern Window Root
, win
;
36 extern FlocaleFont
*FButtonFont
, *FSelButtonFont
;
37 extern ModuleArgs
*module
;
38 extern char *ImagePath
;
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
,
53 *StartIconName
= NULL
;
55 StartAndLaunchButtonItem
*First_Start_Button
= NULL
;
56 StartAndLaunchButtonItem
*Last_Start_Button
= NULL
;
58 static char *startopts
[] =
64 "NoDefaultStartButton",
66 "WindowButtonsLeftMargin",
67 "WindowButtonsRightMargin",
68 "StartButtonRightMargin",
72 Bool
StartButtonParseConfig(char *tline
)
77 int titleRecorded
= 0, iconRecorded
= 0;
78 char *tokens
[100]; /* This seems really big */
79 StartAndLaunchButtonItem
*tempPtr
;
83 option
= tline
+ module
->namelen
+1;
84 i
= GetTokenIndex(option
, startopts
, -1, &rest
);
85 while (*rest
&& *rest
!= '\n' && isspace(*rest
))
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
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 */
116 CopyString(&(First_Start_Button
->buttonCaption
), rest
);
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
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
));
145 /* declaring command twice, ignore */
148 CopyString(tmpStrPtr
, rest
);
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
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 */
175 CopyString(&(First_Start_Button
->buttonIconFileName
), rest
);
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
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
;
200 &(First_Start_Button
->buttonStartCommands
[mouseButton
-1]) :
201 &(First_Start_Button
->buttonStartCommand
));
204 /* declaring command twice, ignore */
207 CopyString(tmpStrPtr
, rest
);
209 case 4: /* NoDefaultStartButton */
210 NoDefaultStartButton
= True
;
213 if (Last_Start_Button
== NULL
)
215 First_Start_Button
= Last_Start_Button
=
216 (StartAndLaunchButtonItem
*)safemalloc(
217 sizeof(StartAndLaunchButtonItem
));
221 Last_Start_Button
->tail
=
222 (StartAndLaunchButtonItem
*) safemalloc(
223 sizeof(StartAndLaunchButtonItem
));
224 Last_Start_Button
= Last_Start_Button
->tail
;
227 StartAndLaunchButtonItemInit(Last_Start_Button
);
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);
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);
252 &(Last_Start_Button
->buttonCaption
),
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);
262 &(Last_Start_Button
->buttonIconFileName
),
266 else if (strncasecmp(tokens
[k
], "Action", 6)==0)
268 rest
= tokens
[k
] + ((sizeof(char))*6);
269 rest
= ParseButtonOptions(rest
, &mouseButton
);
274 &(Last_Start_Button
->
281 &(Last_Start_Button
->
286 /* don't let them set the same action
288 CopyString(tmpStrPtr
, tokens
[j
+1]);
292 if (titleRecorded
==0)
294 CopyString(&(Last_Start_Button
->buttonCaption
), "\0");
299 &(Last_Start_Button
->buttonIconFileName
),
304 case 6: /* WindowButtonsLeftMargin */
307 WindowButtonsLeftMargin
= atoi(rest
);
308 has_wb_left_margin
= 1;
311 case 7: /* WindowButtonsRightMargin */
314 WindowButtonsRightMargin
= atoi(rest
);
315 has_wb_right_margin
= 1;
318 case 8: /* StartButtonRightMargin */
321 StartButtonRightMargin
= atoi(rest
);
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
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
)
345 static char *buttonOptions
[] = {"Mouse", NULL
};
348 while (*pos
&& isspace(*pos
))
353 while (*pos
&& isspace(*pos
))
356 while (*pos
&& *pos
!= ')')
358 pos
= GetNextToken(pos
, &token
);
361 i
= GetTokenIndex(token
, buttonOptions
, 0, NULL
);
365 *mouseButton
= strtol(pos
, &rest
, 10);
367 if (*mouseButton
< 1 || *mouseButton
> NUMBER_OF_EXTENDED_MOUSE_BUTTONS
)
369 fprintf(stderr
,"%s: Invalid mouse button %d", module
->name
,
376 fprintf(stderr
,"%s: Invalid taskbar button option '%s'", module
->name
,
379 while (*pos
&& *pos
!= ',' && *pos
!= ')')
383 while (*pos
&& *pos
!= ',' && *pos
!= ')')
391 while (*pos
&& isspace(*pos
))
396 void StartButtonInit(int height
)
398 FvwmPicture
*p
= NULL
;
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");
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
)
427 dpy
, win
, ImagePath
, tempPtr
->buttonIconFileName
, fpa
);
428 if (p
!= NULL
&& strlen(tempPtr
->buttonCaption
) != 0)
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
;
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
;
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
)
488 StartAndLaunchButtonItem
*tempPtr
= First_Start_Button
;
491 ConsoleMessage("Updating StartTitle not supported yet...\n");
494 for(i
=0; i
<index
; i
++)
495 tempPtr
= tempPtr
->tail
;
496 ButtonUpdate(tempPtr
->buttonItem
, title
, state
);
499 while(tempPtr
!= NULL
)
501 ButtonUpdate(tempPtr
->buttonItem
, title
, state
);
502 tempPtr
= tempPtr
->tail
;
507 if (!First_Start_Button
)
514 for(i
=0; i
<index
; i
++)
515 tempPtr
= tempPtr
->tail
;
516 ButtonUpdate(tempPtr
->buttonItem
, title
, state
);
519 while(tempPtr
!= NULL
)
521 ButtonUpdate(tempPtr
->buttonItem
, title
, state
);
522 tempPtr
= tempPtr
->tail
;
526 tempPtr
= First_Start_Button
;
527 while(tempPtr
!= NULL
)
529 if (tempPtr
->buttonItem
->needsupdate
)
531 tempPtr
= tempPtr
->tail
;
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
)
548 while(tempPtr
!= NULL
)
550 if(tempPtr
->buttonItem
->needsupdate
|| force
)
554 tempPtr2
= First_Start_Button
;
555 while((tempPtr2
!= NULL
) && (j
<i
))
557 tempsum
+=tempPtr2
->width
;
558 tempPtr2
= tempPtr2
->tail
;
561 if (!(tempPtr
->isStartButton
))
564 tempsum
+StartButtonRightMargin
, 0,
566 First_Start_Button
->height
, evp
);
570 tempsum
, 0, tempPtr
->width
,
571 First_Start_Button
->height
, evp
);
573 tempPtr
= tempPtr
->tail
;
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
)
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
)
598 if(tempPtr
->isStartButton
)
599 *startButtonPressed
= True
;
602 tempsum
+= tempPtr
->width
;
603 tempPtr
= tempPtr
->tail
;
610 void getButtonCommand(int whichButton
, char *tmp
, int mouseButton
)
613 StartAndLaunchButtonItem
*tempPtr
= First_Start_Button
;
615 if (!First_Start_Button
)
620 for(i
=0; i
<whichButton
; i
++)
621 tempPtr
= tempPtr
->tail
;
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");
642 void StartAndLaunchButtonItemInit(StartAndLaunchButtonItem
*item
)
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
;