2 /* FvwmTaskBar Module for Fvwm.
4 * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or
6 * Copyright 1995, Pekka Pietik{inen (pp@netppl.fi)
8 * The functions in this source file that are the original work of Mike Finger.
9 * This source file has been modified for use with fvwm95look by
10 * Pekka Pietik{inen, David Barth, Hector Peraza, etc, etc...
12 * No guarantees or warantees or anything are provided or implied in any way
13 * whatsoever. Use this program at your own risk. Permission to use this
14 * program for any purpose is given, as long as the copyright is kept intact.
18 /* This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #include "libs/fvwmlib.h"
39 #include "libs/Colorset.h"
40 #include "libs/Flocale.h"
41 #include "libs/Picture.h"
42 #include "libs/PictureGraphics.h"
43 #include "libs/Rectangles.h"
45 #include "ButtonArray.h"
48 extern FlocaleFont
*FButtonFont
, *FSelButtonFont
;
51 extern GC shadow
, hilite
, graph
, whitegc
, blackgc
, checkered
, icongraph
,
52 iconhilite
, iconshadow
, focusgraph
, focushilite
, focusshadow
;
53 extern GC iconbackgraph
;
54 extern GC focusbackgraph
;
55 extern FlocaleWinString
*FwinString
;
57 extern int button_width
;
58 extern int iconcolorset
;
59 extern int focuscolorset
;
61 extern int NoBrightFocus
;
62 extern int ThreeDfvwm
;
63 extern char *FocusBackColor
;
64 extern Button
*StartButton
;
66 int w3p
; /* width of the string "..." in pixels */
68 extern int NRows
, RowHeight
;
70 #define MIN_BUTTON_SIZE 32 /*....*/
73 * Button handling functions and procedures
76 /* Draws a 3D rectangle */
78 Window wn
, int x
, int y
, int w
, int h
, XRectangle
*bounding
,
79 int state
, Bool iconified
)
81 colorset_t
*cset
= &Colorset
[0]; /* initialize to avoid warning */
94 r
.width
= bounding
->width
;
95 r
.height
= bounding
->height
;
104 XClearArea (dpy
, wn
, r
.x
, r
.y
, r
.width
, r
.height
, False
);
107 draw
= frect_get_intersection(
108 x
+ d
, y
+ d
, w
- 3, h
- 3,
109 r
.x
, r
.y
, r
.width
, r
.height
, &inter
);
110 if (iconcolorset
>= 0)
112 cset
= &Colorset
[iconcolorset
];
114 if (iconcolorset
>= 0 && (cset
->pixmap
|| cset
->shape_mask
)
117 /* we have a colorset background */
118 SetClippedRectangleBackground(
119 dpy
, win
, x
+ d
, y
+ d
, w
- 3, h
- 3, &inter
,
120 cset
, Pdepth
, icongraph
);
125 dpy
, wn
, iconbackgraph
,
126 inter
.x
, inter
.y
, inter
.width
, inter
.height
);
128 XDrawLine (dpy
, wn
, iconhilite
, x
, y
, x
+w
-2, y
);
129 XDrawLine (dpy
, wn
, iconhilite
, x
, y
, x
, y
+h
-2);
132 XDrawLine (dpy
, wn
, iconhilite
, x
, y
+1, x
+w
-2, y
+1);
133 XDrawLine (dpy
, wn
, iconhilite
, x
+1, y
, x
+1, y
+h
-2);
135 XDrawLine (dpy
, wn
, iconshadow
, x
+1, y
+h
-2, x
+w
-2, y
+h
-2);
136 XDrawLine (dpy
, wn
, iconshadow
, x
+w
-2, y
+h
-2, x
+w
-2, y
+1);
137 XDrawLine (dpy
, wn
, blackgc
, x
, y
+h
-1, x
+w
-1, y
+h
-1);
138 XDrawLine (dpy
, wn
, blackgc
, x
+w
-1, y
+h
-1, x
+w
-1, y
);
145 XDrawLine (dpy
, wn
, hilite
, x
, y
, x
+w
-2, y
);
146 XDrawLine (dpy
, wn
, hilite
, x
, y
, x
, y
+h
-2);
149 XDrawLine (dpy
, wn
, hilite
, x
, y
+1, x
+w
-2, y
+1);
150 XDrawLine (dpy
, wn
, hilite
, x
+1, y
, x
+1, y
+h
-2);
152 XDrawLine (dpy
, wn
, shadow
, x
+1, y
+h
-2, x
+w
-2, y
+h
-2);
153 XDrawLine (dpy
, wn
, shadow
, x
+w
-2, y
+h
-2, x
+w
-2, y
+1);
154 XDrawLine (dpy
, wn
, blackgc
, x
, y
+h
-1, x
+w
-1, y
+h
-1);
155 XDrawLine (dpy
, wn
, blackgc
, x
+w
-1, y
+h
-1, x
+w
-1, y
);
158 draw
= frect_get_intersection(
159 x
+ 2, y
+ 2, w
- 4 + (2 - d
), h
- 4 + (2 - d
),
160 r
.x
, r
.y
, r
.width
, r
.height
, &inter
);
161 if (focuscolorset
>= 0)
162 cset
= &Colorset
[focuscolorset
];
163 if (focuscolorset
>= 0 && (cset
->pixmap
|| cset
->shape_mask
) &&
166 /* we have a colorset background */
167 SetClippedRectangleBackground(
168 dpy
, win
, x
+ 2, y
+ 2, w
- 4 + (2 - d
),
169 h
- 4 + (2 - d
), &inter
, cset
, Pdepth
,
175 dpy
, wn
, focusbackgraph
, inter
.x
, inter
.y
,
176 inter
.width
, inter
.height
);
180 dpy
, wn
, checkered
, inter
.x
, inter
.y
,
181 inter
.width
, inter
.height
);
182 XDrawLine (dpy
, wn
, blackgc
, x
, y
, x
+w
-2, y
);
183 XDrawLine (dpy
, wn
, blackgc
, x
, y
, x
, y
+h
-2);
185 XDrawLine (dpy
, wn
, focusshadow
, x
, y
+1, x
+w
-2, y
+1);
186 XDrawLine (dpy
, wn
, focusshadow
, x
+1, y
, x
+1, y
+h
-2);
190 dpy
, wn
, focushilite
, x
+1, y
+h
-2, x
+w
-2, y
+h
-2);
192 dpy
, wn
, focushilite
, x
+w
-2, y
+h
-2, x
+w
-2, y
+1);
194 XDrawLine (dpy
, wn
, focushilite
, x
, y
+h
-1, x
+w
-1, y
+h
-1);
195 XDrawLine (dpy
, wn
, focushilite
, x
+w
-1, y
+h
-1, x
+w
-1, y
);
198 XDrawLine (dpy
, wn
, blackgc
, x
, y
, x
+w
-2, y
);
199 XDrawLine (dpy
, wn
, blackgc
, x
, y
, x
, y
+h
-2);
201 XDrawLine (dpy
, wn
, shadow
, x
, y
+1, x
+w
-2, y
+1);
202 XDrawLine (dpy
, wn
, shadow
, x
+1, y
, x
+1, y
+h
-2);
205 XDrawLine (dpy
, wn
, hilite
, x
+1, y
+h
-2, x
+w
-2, y
+h
-2);
206 XDrawLine (dpy
, wn
, hilite
, x
+w
-2, y
+h
-2, x
+w
-2, y
+1);
208 XDrawLine (dpy
, wn
, hilite
, x
, y
+h
-1, x
+w
-1, y
+h
-1);
209 XDrawLine (dpy
, wn
, hilite
, x
+w
-1, y
+h
-1, x
+w
-1, y
);
215 /* -------------------------------------------------------------------------
216 ButtonNew - Allocates and fills a new button structure
217 ------------------------------------------------------------------------- */
218 Button
*ButtonNew(const char *title
, FvwmPicture
*p
, int state
, int count
)
224 new = (Button
*)safemalloc(sizeof(Button
));
225 new->title
= safemalloc(strlen(title
)+1);
226 strcpy(new->title
, title
);
228 new->p
.picture
= p
->picture
;
229 new->p
.mask
= p
->mask
;
230 new->p
.alpha
= p
->alpha
;
231 new->p
.width
= p
->width
;
232 new->p
.height
= p
->height
;
233 new->p
.depth
= p
->depth
;
241 new->needsupdate
= 1;
247 /* -------------------------------------------------------------------------
248 ButtonDraw - Draws the specified button
249 ------------------------------------------------------------------------- */
250 void ButtonDraw(Button
*button
, int x
, int y
, int w
, int h
, XEvent
*evp
)
253 int state
, x3p
, newx
;
260 XRectangle rect
,inter
;
273 if (!frect_get_intersection(
275 evp
->xexpose
.x
, evp
->xexpose
.y
,
276 evp
->xexpose
.width
, evp
->xexpose
.height
,
289 button
->needsupdate
= 0;
290 state
= button
->state
;
292 win
, x
, y
, w
, h
, &rect
, state
, !!(button
->iconified
));
293 if (button
->iconified
)
298 else if (state
== BUTTON_BRIGHT
)
300 drawgc
= &focusgraph
;
309 if (state
!= BUTTON_UP
) { x
++; y
++; }
311 if (state
== BUTTON_BRIGHT
|| button
== StartButton
)
313 Ffont
= FSelButtonFont
;
320 if (Ffont
->font
!= NULL
)
323 gcv
.font
= Ffont
->font
->fid
;
324 XChangeGC(dpy
, *drawgc
, gcm
, &gcv
);
328 w3p
= FlocaleTextWidth(Ffont
, t3p
, 3);
330 if (button
->p
.picture
!= 0)
332 /* clip pixmap to fit inside button */
333 int pheight
= min(button
->p
.height
, h
-2);
334 int offset
= (button
->p
.height
> h
) ?
335 0 : ((h
- button
->p
.height
) >> 1);
336 int pwidth
= min(button
->p
.width
, w
-5);
337 FvwmRenderAttributes fra
;
339 fra
.mask
= FRAM_DEST_IS_A_WINDOW
;
342 fra
.mask
|= FRAM_HAVE_ICON_CSET
;
343 fra
.colorset
= &Colorset
[cs
];
345 if (frect_get_intersection(
346 rect
.x
, rect
.y
, rect
.width
, rect
.height
,
347 x
+3, y
+offset
, pwidth
, pheight
, &inter
))
349 PGraphicsRenderPicture(
350 dpy
, win
, &(button
->p
), &fra
, win
,
352 (inter
.x
> (x
+3))? inter
.x
- (x
+3):0,
353 (inter
.y
> (y
+offset
))? inter
.y
- (y
+offset
):0,
354 inter
.width
, inter
.height
,
355 inter
.x
/*x+3*/, inter
.y
/*y+offset*/,
356 inter
.width
, inter
.height
, False
);
361 if (button
->title
== NULL
)
366 t_region
= XCreateRegion();
367 XUnionRectWithRegion (&rect
, t_region
, t_region
);
368 /* see if we have the place for "...", if not for "..", if not for "."
370 if ((newx
+ w3p
+ 2) >= w
)
373 w3p
= FlocaleTextWidth(Ffont
, t3p
, 2);
374 if ((newx
+ w3p
+ 2) >= w
)
377 w3p
= FlocaleTextWidth(Ffont
, t3p
, 1);
378 if ((newx
+ w3p
+ 2) >= w
)
380 XDestroyRegion(t_region
);
386 search_len
= strlen(button
->title
);
387 FwinString
->win
= win
;
388 FwinString
->y
= y
+ Ffont
->ascent
+ (RowHeight
- Ffont
->height
)/2;
389 FwinString
->gc
= *drawgc
;
390 FwinString
->flags
.has_colorset
= False
;
391 FwinString
->flags
.has_clip_region
= True
;
392 FwinString
->clip_region
= t_region
;
395 FwinString
->colorset
= &Colorset
[cs
];
396 FwinString
->flags
.has_colorset
= True
;
398 button
->truncate
= False
;
400 if (FlocaleTextWidth(Ffont
, button
->title
, search_len
) > w
-newx
-3)
403 while (search_len
>= 0
404 && ((x3p
= newx
+ FlocaleTextWidth(
405 Ffont
, button
->title
, search_len
))
410 FwinString
->str
= t3p
;
411 FwinString
->x
= x
+ x3p
;
412 FlocaleDrawString(dpy
, Ffont
, FwinString
, 0);
413 button
->truncate
= True
;
416 /* Only print as much of the title as will fit. */
419 FwinString
->str
= button
->title
;
420 FwinString
->x
= x
+ newx
;
421 FwinString
->len
= search_len
;
422 FlocaleDrawString(dpy
, Ffont
, FwinString
, FWS_HAVE_LENGTH
);
424 FwinString
->flags
.has_clip_region
= False
;
425 XDestroyRegion(t_region
);
429 /* -------------------------------------------------------------------------
430 ButtonUpdate - Change the name/state of a button
431 ------------------------------------------------------------------------- */
432 int ButtonUpdate(Button
*button
, const char *title
, int state
)
434 if (button
== NULL
) return -1;
436 if ((title
!= NULL
) && (button
->title
!= title
)) {
437 button
->title
= (char *)saferealloc(button
->title
,strlen(title
)+1);
438 strcpy(button
->title
,title
);
439 button
->needsupdate
= 1;
442 if (state
!= DONT_CARE
) {
443 if (state
!= button
->state
) {
444 button
->state
= state
;
445 button
->needsupdate
= 1;
452 /* -------------------------------------------------------------------------
453 ButtonDelete - Free space allocated to a button
454 ------------------------------------------------------------------------- */
455 void ButtonDelete(Button
*ptr
)
458 if (ptr
->title
!= NULL
) free(ptr
->title
);
463 /* -------------------------------------------------------------------------
464 ButtonName - Return the name of the button
465 ------------------------------------------------------------------------- */
466 char *ButtonName(Button
*button
)
468 if (button
== NULL
) return NULL
;
469 else return button
->title
;
474 * ButtonArray handling functions and procedures
477 /* -------------------------------------------------------------------------
478 InitArray - Initialize the arrary of buttons
479 ------------------------------------------------------------------------- */
480 void InitArray(ButtonArray
*array
, int x
, int y
, int w
, int h
, int tw
)
483 array
->head
= array
->tail
= NULL
;
491 /* -------------------------------------------------------------------------
492 UpdateArray - Update the array specifics. x,y, width, height
493 ------------------------------------------------------------------------- */
494 void UpdateArray(ButtonArray
*array
,int x
,int y
,int w
, int h
, int tw
)
508 for(temp
=array
->head
; temp
!=NULL
; temp
=temp
->next
)
509 temp
->needsupdate
= 1;
512 /* -------------------------------------------------------------------------
513 AddButton - Allocate space for and add the button to the list
514 ------------------------------------------------------------------------- */
515 void AddButton(ButtonArray
*array
, const char *title
, FvwmPicture
*p
, int state
,
516 int count
, int iconified
)
520 new = ButtonNew(title
, p
, state
, count
);
525 if (array
->head
== NULL
)
529 for (temp
= array
->head
; temp
->next
; temp
= temp
->next
)
535 ArrangeButtonArray(array
);
538 /* -------------------------------------------------------------------------
539 ArrangeButtonArray - Rearrange the button size (called from AddButton,
540 RemoveButton, AdjustWindow)
541 ------------------------------------------------------------------------- */
543 void ArrangeButtonArray (ButtonArray
*array
)
551 tw
= array
->w
/ array
->count
;
553 tw
= array
->w
/ ((array
->count
/ NRows
)+1);
555 if (tw
> button_width
)
557 if (tw
< MIN_BUTTON_SIZE
)
558 tw
= MIN_BUTTON_SIZE
;
560 if (tw
!= array
->tw
) /* update needed */
563 for(temp
= array
->head
; temp
!= NULL
; temp
= temp
->next
)
564 temp
->needsupdate
= 1;
568 /* -------------------------------------------------------------------------
569 UpdateButton - Change the name/state of a button
570 ------------------------------------------------------------------------- */
571 int UpdateButton(ButtonArray
*array
, int butnum
, const char *title
, int state
)
575 for (temp
= array
->head
; temp
; temp
= temp
->next
)
576 if (temp
->count
== butnum
)
579 return ButtonUpdate(temp
, title
, state
);
582 /* -------------------------------------------------------------------------
583 UpdateButtonPicture - Change the picture of a button
584 ------------------------------------------------------------------------- */
585 int UpdateButtonPicture(ButtonArray
*array
, int butnum
, FvwmPicture
*p
)
589 for (temp
=array
->head
; temp
; temp
=temp
->next
)
590 if (temp
->count
== butnum
)
593 if (temp
== NULL
) return -1;
594 if (temp
->p
.picture
!= p
->picture
|| temp
->p
.mask
!= p
->mask
) {
595 temp
->p
.picture
= p
->picture
;
596 temp
->p
.mask
= p
->mask
;
597 temp
->p
.alpha
= p
->alpha
;
598 temp
->p
.width
= p
->width
;
599 temp
->p
.height
= p
->height
;
600 temp
->p
.depth
= p
->depth
;
601 temp
->needsupdate
= 1;
606 /* -------------------------------------------------------------------------
607 RemoveButton - Delete a button from the list
608 ------------------------------------------------------------------------- */
609 void RemoveButton(ButtonArray
*array
, int butnum
)
611 Button
*temp
, *to_die
;
613 if (array
->head
== NULL
)
616 if (array
->head
->count
== butnum
)
618 to_die
= array
->head
;
619 array
->head
= array
->head
->next
;
623 for (temp
= array
->head
, to_die
= array
->head
->next
; to_die
!= NULL
;
624 to_die
= to_die
->next
, temp
= temp
->next
)
626 if (to_die
->count
== butnum
)
631 temp
->next
= to_die
->next
;
634 ButtonDelete(to_die
);
635 if (array
->count
> 0)
637 for (temp
= array
->head
; temp
; temp
= temp
->next
)
638 temp
->needsupdate
= 1;
640 ArrangeButtonArray(array
);
643 /* -------------------------------------------------------------------------
644 find_n - Find the nth button in the list (Use internally)
645 ------------------------------------------------------------------------- */
646 Button
*find_n(ButtonArray
*array
, int n
)
653 for ( ; temp
&& n
!= temp
->count
; temp
=temp
->next
)
658 /* -------------------------------------------------------------------------
659 FreeAllButtons - Free the whole array of buttons
660 ------------------------------------------------------------------------- */
661 void FreeAllButtons(ButtonArray
*array
)
663 Button
*temp
, *temp2
;
665 for(temp
=array
->head
; temp
!=NULL
; ) {
674 /* ------------------------------------------------------------------------
675 DrawButtonArray - Draw the whole array (all=1), or only those that need.
676 ------------------------------------------------------------------------ */
677 void DrawButtonArray(ButtonArray
*array
, int all
, XEvent
*evp
)
681 static Bool exposed
= False
;
694 for(temp
=array
->head
; temp
!=NULL
; temp
=temp
->next
)
696 if ((x
+ array
->tw
> array
->w
) && (n
< NRows
))
702 if (temp
->needsupdate
|| all
)
704 temp
, x
+ array
->x
, y
, array
->tw
-pad
, array
->h
,
705 (temp
->needsupdate
)? NULL
:evp
);
710 /* -------------------------------------------------------------------------
711 RadioButton - Enable button i and verify all others are disabled
712 ------------------------------------------------------------------------- */
713 void RadioButton(ButtonArray
*array
, int butnum
, int state
)
717 for(button
=array
->head
; button
!=NULL
; button
=button
->next
) {
718 if (button
->count
== butnum
) {
719 button
->state
= state
;
720 button
->needsupdate
= 1;
722 if (button
->state
!= BUTTON_UP
) {
723 button
->state
= BUTTON_UP
;
724 button
->needsupdate
= 1;
729 /* -------------------------------------------------------------------------
731 ------------------------------------------------------------------------- */
732 Bool
CheckRootTransparentButtons(ButtonArray
*array
)
737 if (!CSET_IS_TRANSPARENT_ROOT(iconcolorset
) &&
738 !CSET_IS_TRANSPARENT_ROOT(focuscolorset
))
742 for(button
=array
->head
; button
!=NULL
; button
=button
->next
)
744 if ((button
->iconified
&&
745 CSET_IS_TRANSPARENT_ROOT(iconcolorset
)) ||
746 (button
->state
== BUTTON_BRIGHT
&&
747 CSET_IS_TRANSPARENT_ROOT(focuscolorset
)))
750 button
->needsupdate
= 1;
756 /* -------------------------------------------------------------------------
757 WhichButton - Based on x,y which button was pressed
758 ------------------------------------------------------------------------- */
759 int WhichButton(ButtonArray
*array
, int xp
, int yp
)
761 int junkx
, junky
, junkz
;
764 return LocateButton(array
, xp
, yp
, &junkx
, &junky
, &junkt
, &junkz
);
767 int LocateButton(ButtonArray
*array
, int xp
, int yp
, int *xb
, int *yb
,
768 char **name
, int *trunc
)
773 if (xp
< array
->x
|| xp
> array
->x
+array
->w
) return -1;
778 for(temp
=array
->head
, num
=0; temp
!=NULL
; temp
=temp
->next
, num
++) {
779 if((x
+ array
->tw
> array
->w
) && (n
< NRows
))
780 { x
= 0; y
+= RowHeight
+2; ++n
; }
781 if( xp
>= x
+array
->x
&& xp
<= x
+array
->x
+array
->tw
-3 &&
782 yp
>= y
&& yp
<= y
+array
->h
) break;
786 if (num
<0 || num
>array
->count
-1) num
= -1;
792 *trunc
= temp
->truncate
;
797 return (num
== -1) ? num
: temp
->count
;
800 /* -------------------------------------------------------------------------
801 ButtonCoordinates - Compute the coordinates of a button (animation)
802 ------------------------------------------------------------------------- */
803 extern int StartAndLaunchButtonsWidth
;
804 void ButtonCoordinates(ButtonArray
*array
, int numbut
, int *xc
, int *yc
)
811 for(temp
=array
->head
; temp
->count
!= numbut
; temp
=temp
->next
)
813 if((x
+ 2*array
->tw
> array
->w
) && (r
< NRows
))
825 *xc
= x
+ StartAndLaunchButtonsWidth
+3;
829 void ButtonDimensions(ButtonArray
*array
, int *width
, int *height
)
832 *height
= RowHeight
+2;