2 /* FvwmTaskBar Module for Fvwm.
4 * (Much reworked version of FvwmWinList)
5 * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or
8 * Two little hacks by DYB: 1) make size of a strip in hidden state tunable
9 * (with *FvwmTaskBar: AutoHide <pixels>); 2) make process of TaskBar
10 * hiding/unhiding more smooth.
12 * Minor hack by TKP to enable autohide to work with pages (leaves 2 pixels
13 * visible so that the 1 pixel panframes don't get in the way)
15 * Merciless hack by RBW for the Great Style Flag Rewrite - 04/20/1999.
16 * Now the GSFR is used and there are no other flags (olicha may 19, 2000).
18 * The author makes not guarantees or warantees, either express or
19 * implied. Feel free to use any code contained here for any purpose, as long
20 * and this and any other applicable copyrights are kept intact.
22 * The functions in this source file that are based on part of the FvwmIdent
23 * module for Fvwm are noted by a small copyright atop that function, all others
24 * are copyrighted by Mike Finger. For those functions modified/used, here is
25 * the full, original copyright:
27 * Copyright 1994, Robert Nation and Nobutaka Suzuki.
28 * No guarantees or warantees or anything
29 * are provided or implied in any way whatsoever. Use this program at your
30 * own risk. Permission to use this program for any purpose is given,
31 * as long as the copyright is kept intact. */
33 /* This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License as published by
35 * the Free Software Foundation; either version 2 of the License, or
36 * (at your option) any later version.
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
43 * You should have received a copy of the GNU General Public License
44 * along with this program; if not, write to the Free Software
45 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54 #include "libs/ftime.h"
62 #ifdef HAVE_SYS_BSDTYPES_H
63 #include <sys/bsdtypes.h> /* Saul */
66 #include "libs/Module.h"
67 #include "libs/fvwmlib.h" /* for pixmaps routines */
68 #include "libs/FScreen.h"
69 #include "libs/FShape.h"
70 #include "libs/fvwmsignal.h"
71 #include "libs/Colorset.h"
72 #include "libs/Flocale.h"
73 #include "libs/gravity.h"
74 #include "libs/FRender.h"
75 #include "libs/FRenderInit.h"
76 #include "libs/FGettext.h"
77 #include "libs/ColorUtils.h"
78 #include "libs/Graphics.h"
79 #include "libs/Parse.h"
80 #include "libs/Strings.h"
81 #include "libs/XError.h"
83 #include "FvwmTaskBar.h"
84 #include "ButtonArray.h"
90 #define MAX_NO_ICON_ACTION_LENGTH (MAX_MODULE_INPUT_TEXT_LEN - 100)
92 #define GRAB_EVENTS (ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|EnterWindowMask|LeaveWindowMask)
93 #define SomeButtonDown(a) ((a) & DEFAULT_ALL_BUTTONS_MASK)
95 #define DEFAULT_CLICK1 "Iconify -1, Raise, Focus"
96 #define DEFAULT_CLICK2 "Iconify +1, Lower"
97 #define DEFAULT_CLICK3 "Nop"
98 #define DEFAULT_CLICK_N "Nop"
101 #define gray_height 8
102 unsigned char gray_bits
[] = { 0xaa, 0x55, 0xaa, 0x55,
103 0xaa, 0x55, 0xaa, 0x55 };
105 #define DEFAULT_VISIBLE_PIXELS 3
107 /* File type information */
111 /* X related things */
117 static Pixel iconfore
;
118 static Pixel iconback
;
119 static Pixel focusfore
;
120 static Pixel focusback
;
122 GC iconbackgraph
= None
;
123 GC focusgraph
= None
;
124 GC focusbackgraph
= None
;
128 GC iconshadow
= None
;
129 GC iconhilite
= None
;
130 GC focusshadow
= None
;
131 GC focushilite
= None
;
137 int iconcolorset
= -1;
138 int focuscolorset
= -1;
139 FlocaleFont
*FButtonFont
, *FSelButtonFont
;
140 FlocaleWinString
*FwinString
;
142 static Atom wm_del_win
;
144 static Bool is_dead_pipe
= False
;
146 /* Module related information */
156 win_title_height
= 0,
158 button_width
= DEFAULT_BTN_WIDTH
,
162 WindowState
= -2, /* -2 unmaped, 1 not hidden, -1 hidden,
163 * 0 hidden -> not hidden (for the events loop) */
164 FocusInWin
= 0; /* 1 if the Taskbar has the focus */
165 direction_t win_shade_direction
= 0;
166 static int auto_stick_y
= 0;
168 static volatile sig_atomic_t AlarmSet
= NOT_SET
;
169 static volatile sig_atomic_t tip_window_alarm
= False
;
170 static volatile sig_atomic_t hide_taskbar_alarm
= False
;
171 static volatile sig_atomic_t stick_taskbar_alarm
= False
;
174 int UpdateInterval
= 30;
176 int whichButton
= -1;
177 Bool startButtonPressed
= False
;
182 char *ClickAction
[max(NUMBER_OF_EXTENDED_MOUSE_BUTTONS
, 3)] =
189 *BackColor
= "white",
190 *ForeColor
= "black",
191 *IconBackColor
= "white",
192 *IconForeColor
= "black",
193 *FocusBackColor
= NULL
,
194 *FocusForeColor
= NULL
,
197 *selfont_string
= NULL
;
199 static char *AnimCommand
= NULL
;
201 int UseSkipList
= False
,
202 UseIconNames
= False
,
203 ShowTransients
= False
,
208 HighlightFocus
= False
,
212 NoBrightFocus
= False
,
216 int VisiblePixels
= DEFAULT_VISIBLE_PIXELS
;
217 /* This macro should be used when calculating geometry */
218 #define VISIBLE_PIXELS() (VisiblePixels < win_height? VisiblePixels:win_height)
221 rectangle global_scr_g
;
223 int NRows
, RowHeight
, Midline
;
226 #define COUNT_LIMIT 10000
227 long DeskNumber
; /* Added by Balaji R */
231 /* Imported from Goodies */
232 extern int stwin_width
, goodies_width
, goodies_fontheight
;
233 extern TipStruct Tip
;
235 /* Imported from Start */
236 extern int StartAndLaunchButtonsWidth
, StartAndLaunchButtonsHeight
;
237 extern StartAndLaunchButtonItem
*First_Start_Button
;
238 extern StartAndLaunchButtonItem
*Last_Start_Button
;
239 extern int WindowButtonsLeftMargin
;
240 extern int WindowButtonsRightMargin
;
241 char *ImagePath
= NULL
;
242 char *XineramaConfig
= NULL
;
243 static int fscreen
= 0;
245 static void ParseConfig( void );
246 static void ParseConfigLine(char *tline
);
247 static void ShutMeDown(void);
248 static RETSIGTYPE
TerminateHandler(int sig
);
249 static RETSIGTYPE
Alarm(int sig
);
250 static void SetAlarm(tb_alarm_t event
);
251 static void ClearAlarm(tb_alarm_t event
);
252 static void DoAlarmAction(void);
253 static int ErrorHandler(Display
*, XErrorEvent
*);
254 static Bool
change_colorset(int cset
, Bool force
);
255 static void WarpTaskBar(int y
);
256 int IsItemIndexIconSuppressed(List
*list
, int i
);
259 Main - Setup the XConnection,request the window list and loop forever
260 Based on main() from FvwmIdent:
261 Copyright 1994, Robert Nation and Nobutaka Suzuki.
263 int main(int argc
, char **argv
)
267 FlocaleInit(LC_CTYPE
, "", "", "FvwmTaskBar");
268 setlocale(LC_TIME
, "");
269 FGettextInit("FvwmTaskBar", LOCALEDIR
, "FvwmTaskBar");
271 for (i
= 3; i
< NUMBER_OF_EXTENDED_MOUSE_BUTTONS
; i
++)
273 ClickAction
[i
] = DEFAULT_CLICK_N
;
276 module
= ParseModuleArgs(argc
,argv
,1); /* use alias if provided */
280 "FvwmTaskBar Version %s should only be executed by fvwm!\n",
285 /* setup fvwm pipes */
286 Fvwm_fd
[0] = module
->to_fvwm
;
287 Fvwm_fd
[1] = module
->from_fvwm
;
289 #ifdef HAVE_SIGACTION
291 struct sigaction sigact
;
293 sigemptyset(&sigact
.sa_mask
);
295 sigact
.sa_flags
= SA_RESTART
;
299 sigact
.sa_handler
= Alarm
;
300 sigaction(SIGALRM
, &sigact
, NULL
);
303 sigact
.sa_flags
= SA_INTERRUPT
;
307 sigaddset(&sigact
.sa_mask
, SIGPIPE
);
308 sigaddset(&sigact
.sa_mask
, SIGTERM
);
309 sigaddset(&sigact
.sa_mask
, SIGINT
);
310 sigact
.sa_handler
= TerminateHandler
;
311 sigaction(SIGPIPE
, &sigact
, NULL
);
312 sigaction(SIGTERM
, &sigact
, NULL
);
313 sigaction(SIGINT
, &sigact
, NULL
);
316 #ifdef USE_BSD_SIGNALS
317 fvwmSetSignalMask( sigmask(SIGTERM
) | sigmask(SIGPIPE
) | sigmask(SIGINT
) );
319 signal (SIGPIPE
, TerminateHandler
);
320 signal (SIGTERM
, TerminateHandler
);
321 signal (SIGINT
, TerminateHandler
);
322 signal (SIGALRM
, Alarm
);
323 #ifdef HAVE_SIGINTERRUPT
324 siginterrupt(SIGPIPE
, 1);
325 siginterrupt(SIGTERM
, 1);
326 siginterrupt(SIGINT
, 1);
330 SetMessageMask(Fvwm_fd
,M_ADD_WINDOW
| M_CONFIGURE_WINDOW
| M_DESTROY_WINDOW
|
331 M_VISIBLE_NAME
| M_RES_NAME
|
332 M_DEICONIFY
| M_ICONIFY
| M_END_WINDOWLIST
| M_FOCUS_CHANGE
|
333 M_CONFIG_INFO
| M_END_CONFIG_INFO
| M_NEW_DESK
| M_SENDCONFIG
336 /* extended messages */
337 SetMessageMask(Fvwm_fd
, MX_VISIBLE_ICON_NAME
| MX_PROPERTY_CHANGE
);
339 /* Parse the config file */
342 /* Setup the XConnection */
344 XSetErrorHandler(ErrorHandler
);
346 StartButtonInit(RowHeight
);
348 /* init the array of buttons */
349 InitArray(&buttons
, StartAndLaunchButtonsWidth
+ WindowButtonsLeftMargin
, 0,
350 win_width
- stwin_width
- StartAndLaunchButtonsWidth
- WindowButtonsLeftMargin
351 - WindowButtonsRightMargin
, RowHeight
, button_width
);
354 /* Request a list of all windows,
355 * wait for ConfigureWindow packets */
356 SendText(Fvwm_fd
, "Send_WindowList",0);
358 /* tell fvwm we're running */
359 SendFinishedStartupNotification(Fvwm_fd
);
361 /* Lock on send only for iconify and deiconify (for NoIconAction) */
362 if (AnimCommand
&& (AnimCommand
[0] != 0)) {
363 SetSyncMask(Fvwm_fd
, M_DEICONIFY
| M_ICONIFY
);
364 SetNoGrabMask(Fvwm_fd
, M_DEICONIFY
| M_ICONIFY
);
366 /* Receive all messages from Fvwm */
368 #ifdef FVWM_DEBUG_MSGS
371 fprintf(stderr
, "%s: Received signal: exiting...\n", module
->name
);
379 EndLessLoop - Read and redraw until we get killed, blocking when can't read
381 void EndLessLoop(void)
384 fd_set_size_t fd_width
;
388 if (Fvwm_fd
[1] > fd_width
)
389 fd_width
= Fvwm_fd
[1];
392 while ( !isTerminated
)
395 FD_SET(Fvwm_fd
[1], &readset
);
396 FD_SET(x_fd
, &readset
);
398 tv
.tv_sec
= UpdateInterval
;
402 if ( fvwmSelect(fd_width
, &readset
, NULL
, NULL
, &tv
) > 0 )
405 if (FD_ISSET(x_fd
, &readset
) || FPending(dpy
))
408 if (FD_ISSET(Fvwm_fd
[1], &readset
))
421 ReadFvwmPipe - Read a single message from the pipe from Fvwm
422 Originally Loop() from FvwmIdent:
423 Copyright 1994, Robert Nation and Nobutaka Suzuki.
425 void ReadFvwmPipe(void)
427 FvwmPacket
* packet
= ReadFvwmPacket(Fvwm_fd
[1]);
428 if ( packet
== NULL
)
431 ProcessMessage( packet
->type
, packet
->body
);
435 ProcessMessage - Process the message coming from Fvwm
436 Skeleton based on processmessage() from FvwmIdent:
437 Copyright 1994, Robert Nation and Nobutaka Suzuki.
439 void ProcessMessage(unsigned long type
,unsigned long *body
)
446 struct ConfigWinPacket
*cfgpacket
;
453 i
= FindItem(&windows
, body
[0]);
456 /* This case is handled in LoopOnEvents() */
457 if (IsItemIconified(&windows
, body
[0]))
459 RadioButton(&buttons
, i
, BUTTON_BRIGHT
);
469 case M_CONFIGURE_WINDOW
:
470 cfgpacket
= (ConfigWinPacket
*) body
;
471 new_g
.x
= cfgpacket
->frame_x
;
472 new_g
.y
= cfgpacket
->frame_y
;
473 new_g
.width
= cfgpacket
->frame_width
;
474 new_g
.height
= cfgpacket
->frame_height
;
475 if (!ShowTransients
&& (IS_TRANSIENT(cfgpacket
)))
477 /* Notes: users cannot modify the win_width of the taskbar (see
478 the hints in StartMeUp; it is a good idea). So "we have to" modify
479 the win_width here by modifying the WMNormalHints. Moreover, 1. we want
480 that the TaskBar width with its border is execately the screen width
481 2. be carful with dynamic style change */
482 if (cfgpacket
->w
== win
)
491 nb
= (short)cfgpacket
->border_width
;
492 nw
= screen_g
.width
- (win_border
<<1);
493 nh
= (int)cfgpacket
->frame_height
- (win_border
<<1);
494 nht
= HAS_TITLE(cfgpacket
);
495 ntd
= GET_TITLE_DIR(cfgpacket
);
496 nth
= (int)cfgpacket
->title_height
;
497 if (ntd
== DIR_S
|| ntd
== DIR_N
)
505 if (nb
!= win_border
|| nw
!= win_width
|| nh
!= win_height
||
506 nht
!= win_has_title
|| ntd
!= win_title_dir
||
507 nth
!= win_title_height
)
516 win_title_height
= nth
;
519 win_x
= screen_g
.x
+ win_border
;
524 win_y
= screen_g
.height
-
527 win_title_height
* HAS_TITLE_DIR(cfgpacket
, DIR_S
) :
528 win_height
+ win_border
);
534 win_title_height
* HAS_TITLE_DIR(cfgpacket
, DIR_S
) -
535 win_height
: win_border
+ win_title_height
;
542 win_y
= screen_g
.height
- win_border
-
543 HAS_TITLE_DIR(cfgpacket
, DIR_S
) * win_height
;
547 win_y
= win_title_height
+ win_border
-
548 HAS_TITLE_DIR(cfgpacket
, DIR_S
) * win_height
;
554 XGetWMNormalHints(dpy
,win
,&hints
,&dumy
);
555 hints
.min_width
= win_width
;
556 hints
.base_width
= win_width
;
557 hints
.max_width
= win_width
;
559 /* hack to prevent mapping on wrong screen with StartsOnScreen */
560 FScreenMangleScreenIntoUSPosHints(fscreen
, &hints
);
561 XSetWMNormalHints(dpy
,win
,&hints
);
565 XMoveResizeWindow(dpy
, win
, win_x
, win_y
, win_width
, win_height
);
567 else if (!IS_SHADED(cfgpacket
))
569 XResizeWindow(dpy
, win
, win_width
, win_height
);
571 UpdateArray(&buttons
, -1, -1,
572 win_width
- stwin_width
- StartAndLaunchButtonsWidth
573 - WindowButtonsLeftMargin
- WindowButtonsRightMargin
,
575 ArrangeButtonArray (&buttons
);
576 AdjustWindow(win_width
, win_height
);
579 if (AutoStick
&& win_is_shaded
!= IS_SHADED(cfgpacket
))
581 win_is_shaded
= IS_SHADED(cfgpacket
);
586 win_y
= screen_g
.height
- win_border
-
587 (win_title_dir
== DIR_S
) * win_height
;
591 win_y
= win_title_height
+ win_border
-
592 (win_title_dir
== DIR_S
) * win_height
;
599 win_y
= screen_g
.height
- win_border
- win_height
;
603 win_y
= win_title_height
+ win_border
;
608 SetAlarm(HIDE_TASK_BAR
);
612 XMoveWindow(dpy
, win
, win_x
, win_y
);
614 win_is_shaded
= IS_SHADED(cfgpacket
);
615 win_shade_direction
= SHADED_DIR(cfgpacket
);
619 if ((i
=FindItem(&windows
, body
[0])) != -1)
625 Bool is_on_desk
= True
;
626 Bool is_changing_desk
= False
;
627 Bool is_on_page
= True
;
628 Bool is_changing_page
= False
;
629 Bool is_on_screen
= True
;
630 Bool is_changing_screen
= False
;
633 if (!GetItemGeometry(&windows
, i
, &pold_g
))
638 if (DeskOnly
&& GetDeskNumber(&windows
,i
,&Desk
))
640 if (IsItemIndexSticky(&windows
,i
))
643 is_changing_desk
= False
;
647 is_on_desk
= (DeskNumber
== cfgpacket
->desk
);
648 is_changing_desk
= (Desk
!= cfgpacket
->desk
);
650 UpdateItemIndexDesk(&windows
, i
, cfgpacket
->desk
);
654 is_on_page
= fvwmrect_do_rectangles_intersect(&new_g
, &global_scr_g
);
656 (fvwmrect_do_rectangles_intersect(pold_g
, &global_scr_g
) !=
661 is_on_screen
= fvwmrect_do_rectangles_intersect(&new_g
, &screen_g
);
663 (fvwmrect_do_rectangles_intersect(pold_g
, &screen_g
) !=
666 UpdateItemIndexGeometry(&windows
, i
, &new_g
);
668 is_managed
= (is_on_desk
&& is_on_page
&& is_on_screen
);
669 if (is_changing_desk
|| is_changing_page
|| is_changing_screen
)
673 /* window entering managed area of the virtual desktop */
678 /* window leaving managed area of the virtual desktop */
683 if (UseSkipList
&& is_managed
)
685 skiplist
= IsItemIndexSkipWindowList(&windows
,i
);
686 if (DO_SKIP_WINDOW_LIST(cfgpacket
) && !skiplist
)
691 if (!DO_SKIP_WINDOW_LIST(cfgpacket
) && skiplist
) {
697 UpdateItemGSFRFlags(&windows
, cfgpacket
);
700 RemoveButton(&buttons
, i
);
705 AddButton(&buttons
, ItemName(&windows
,i
),
706 GetItemPicture(&windows
,i
), BUTTON_UP
, i
,
707 IsItemIndexIconified(&windows
, i
));
711 else if (!UseSkipList
|| !DO_SKIP_WINDOW_LIST(cfgpacket
))
713 AddItem(&windows
, cfgpacket
->w
,
714 cfgpacket
, cfgpacket
->desk
, Count
++);
715 if (Count
> COUNT_LIMIT
)
717 i
= FindItem(&windows
, cfgpacket
->w
);
718 UpdateItemIndexGeometry(&windows
, i
, &new_g
);
722 Button
*temp
= find_n(&buttons
, i
);
723 if (temp
&& IS_ICONIFIED(cfgpacket
))
728 case M_DESTROY_WINDOW
:
729 if ((i
= FindItem(&windows
, body
[0])) == -1)
731 DeleteItem(&windows
, body
[0]);
732 RemoveButton(&buttons
, i
);
737 if (!FMiniIconsSupported
|| (i
= FindItem(&windows
, body
[0])) == -1)
740 MiniIconPacket
*mip
= (MiniIconPacket
*) body
;
741 p
.picture
= mip
->picture
;
743 p
.alpha
= mip
->alpha
;
744 p
.width
= mip
->width
;
745 p
.height
= mip
->height
;
746 p
.depth
= mip
->depth
;
748 UpdateItemPicture(&windows
, i
, &p
);
749 if (UpdateButton(&buttons
, i
, NULL
, DONT_CARE
) != -1) {
750 UpdateButtonPicture(&buttons
, i
, &p
);
756 case MX_VISIBLE_ICON_NAME
:
757 if ((type
== MX_VISIBLE_ICON_NAME
&& !UseIconNames
) ||
758 (type
== M_VISIBLE_NAME
&& UseIconNames
)) break;
759 string
= (char *) &body
[3];
760 if ((i
= UpdateItemName(&windows
, body
[0], (char *)&body
[3])) == -1)
762 if (UpdateButton(&buttons
, i
, string
, DONT_CARE
) == -1)
766 if (GetDeskNumber(&windows
, i
, &Desk
) == 0)
768 if (DeskOnly
&& Desk
!= DeskNumber
)
770 if (!GetItemGeometry(&windows
, i
, &pold_g
))
772 if (PageOnly
&& !fvwmrect_do_rectangles_intersect(pold_g
, &global_scr_g
))
774 if (ScreenOnly
&& !fvwmrect_do_rectangles_intersect(pold_g
, &screen_g
))
776 if (UseSkipList
&& IsItemIndexSkipWindowList(&windows
, i
))
778 AddButton(&buttons
, string
, NULL
, BUTTON_UP
, i
,
779 IsItemIndexIconified(&windows
, i
));
788 /* fwvm will wait for an Unlock message before continuing
789 * be careful when changing this construct, make sure unlock happens
790 * if AnimCommand && AnimCommand[0] != 0 */
791 iconified
= IsItemIconified(&windows
, body
[0]);
792 if (((i
= FindItem(&windows
, body
[0])) == -1)
793 || (type
== M_DEICONIFY
&& !iconified
)
794 || (type
== M_ICONIFY
&& iconified
))
796 if (AnimCommand
&& AnimCommand
[0] != 0)
797 SendUnlockNotification(Fvwm_fd
);
801 iconified
= !iconified
;
802 UpdateItemIconifiedFlag(&windows
, body
[0], iconified
);
804 Button
*temp
= find_n(&buttons
, i
);
807 Bool do_reshade
= False
;
808 direction_t shade_dir
= win_shade_direction
;
809 char buff
[MAX_MODULE_INPUT_TEXT_LEN
];
811 if (AnimCommand
&& (AnimCommand
[0] != 0)
812 && IsItemIndexIconSuppressed(&windows
,i
))
820 SendText(Fvwm_fd
, "WindowShade Off", win
);
823 ButtonCoordinates(&buttons
, i
, &x
, &y
);
824 XTranslateCoordinates(dpy
, win
, Root
, x
, y
,
825 &abs_x
, &abs_y
, &child
);
826 if (type
== M_DEICONIFY
) {
827 sprintf(buff
, "%s %d %d %d %d %d %d %d %d", AnimCommand
,
828 abs_x
, abs_y
, buttons
.tw
-2, RowHeight
,
829 (int)body
[7], (int)body
[8], (int)body
[9],
832 sprintf(buff
, "%s %d %d %d %d %d %d %d %d", AnimCommand
,
833 (int)body
[7], (int)body
[8], (int)body
[9], (int)body
[10],
834 abs_x
, abs_y
, buttons
.tw
-2, RowHeight
);
836 SendText(Fvwm_fd
, buff
, 0);
838 temp
->needsupdate
= 1;
839 temp
->iconified
= iconified
;
840 DrawButtonArray(&buttons
, 0, NULL
);
844 buff
,"WindowShade %s",
845 gravity_dir_to_string(shade_dir
,""));
846 SendText(Fvwm_fd
, buff
, win
);
849 if (AnimCommand
&& AnimCommand
[0] != 0)
850 SendUnlockNotification(Fvwm_fd
);
852 if (type
== M_ICONIFY
&& i
== ButReleased
) {
853 RadioButton(&buttons
, -1, BUTTON_UP
);
854 ButReleased
= ButPressed
= -1;
859 case M_END_WINDOWLIST
:
860 AdjustWindow(win_width
, win_height
);
861 XMapRaised(dpy
, win
);
869 DeskNumber
= body
[0];
870 if (!First
&& DeskOnly
)
879 case MX_PROPERTY_CHANGE
:
880 if (body
[0] == MX_PROPERTY_CHANGE_BACKGROUND
&& body
[2] == 0 &&
881 CSET_IS_TRANSPARENT_PR(colorset
))
884 dpy
, win
, win_width
, win_height
,
886 Pdepth
, graph
, True
);
896 tline
= (char*)&(body
[3]);
897 if (strncasecmp(tline
, "Colorset", 8) == 0)
899 cset
= LoadColorset(tline
+ 8);
900 if (change_colorset(cset
, False
))
905 else if (strncasecmp(tline
, XINERAMA_CONFIG_STRING
,
906 sizeof(XINERAMA_CONFIG_STRING
) - 1) == 0)
908 FScreenConfigureModule(
909 tline
+ sizeof(XINERAMA_CONFIG_STRING
) - 1);
916 RedrawWindow(redraw
, NULL
);
919 void redraw_buttons(void)
923 FreeAllButtons(&buttons
);
925 for (item
=windows
.head
; item
; item
=item
->next
)
927 if ((DeskNumber
!= item
->Desk
&& !IS_STICKY_ACROSS_DESKS(item
) &&
928 (!IS_ICONIFIED(item
) || !IS_ICON_STICKY_ACROSS_DESKS(item
))))
932 if (DO_SKIP_WINDOW_LIST(item
) && UseSkipList
)
937 !fvwmrect_do_rectangles_intersect(&item
->win_g
, &global_scr_g
))
942 &buttons
, item
->name
, &(item
->p
), BUTTON_UP
, item
->count
,
946 RedrawWindow(1, NULL
);
951 Detected a broken pipe - time to exit
952 Based on DeadPipe() from FvwmIdent:
953 Copyright 1994, Robert Nation and Nobutaka Suzuki.
955 RETSIGTYPE
DeadPipe(int nonsense
)
963 Reentrant signal handler that will tell the application to quit.
964 It is not safe to just call "exit()" here; instead we will
965 just set a flag that will break the event-loop when the
969 TerminateHandler(int sig
)
971 fvwmSetTerminate(sig
);
977 WaitForExpose - Used to wait for expose event so we don't draw too early
979 void WaitForExpose(void)
984 FNextEvent(dpy
, &Event
);
985 if (Event
.type
== Expose
) {
986 if (Event
.xexpose
.count
== 0) break;
993 RedrawWindow - Update the needed lines and erase any old ones
995 void RedrawWindow(int force
, XEvent
*evp
)
1001 /* 98-11-21 13:45, Mohsin_Ahmed, mailto:mosh@sasi.com. */
1002 if( Tip
.type
>= 0 && AutoFocus
)
1005 Fvwm_fd
, "Iconify off, Raise, Focus",
1006 ItemID( &windows
, Tip
.type
) );
1015 dpy
, win
, evp
->xexpose
.x
, evp
->xexpose
.y
,
1016 evp
->xexpose
.width
, evp
->xexpose
.height
, False
);
1021 dpy
, win
, 0, 0, win_width
, win_height
, False
);
1025 DrawButtonArray(&buttons
, force
, evp
);
1026 StartButtonDraw(force
, evp
);
1027 if (FQLength(dpy
) && !force
)
1031 static char *configopts
[] =
1035 XINERAMA_CONFIG_STRING
,
1039 static char *moduleopts
[] =
1074 void ParseConfig(void)
1078 InitGetConfigLine(Fvwm_fd
,CatString3("*",module
->name
,0));
1079 while (GetConfigLine(Fvwm_fd
,&buf
), buf
!= NULL
)
1081 ParseConfigLine(buf
);
1082 } /* end config lines */
1083 } /* end function */
1085 static void ParseConfigLine(char *tline
)
1090 while (isspace((unsigned char)*tline
))
1093 if (strncasecmp(tline
, CatString3("*",module
->name
,0), module
->namelen
) != 0)
1095 /* Non module specific options */
1096 index
= GetTokenIndex(tline
, configopts
, -1, &rest
);
1097 while (*rest
&& *rest
!= '\n' && isspace(*rest
))
1101 case 0: /* imagepath */
1106 CopyString(&ImagePath
, rest
);
1108 case 1: /* colorset */
1111 case 2: /* XINERAMA_CONFIG_STRING */
1114 free(XineramaConfig
);
1116 CopyString(&XineramaConfig
, rest
);
1119 /* unknown option */
1125 /* options beginning with '*ModuleName' */
1126 rest
= tline
+ module
->namelen
+1;
1127 index
= GetTokenIndex(rest
, moduleopts
, -1, &rest
);
1128 while (*rest
&& *rest
!= '\n' && isspace(*rest
))
1133 CopyStringWithQuotes(&font_string
, rest
);
1135 case 1: /* SelFont */
1136 CopyStringWithQuotes(&selfont_string
, rest
);
1138 case 2: /* Geometry */
1139 while (isspace((unsigned char)*rest
) && *rest
!= '\n' && *rest
!= 0)
1141 UpdateString(&geometry
, PeekToken(rest
, NULL
));
1144 CopyString(&ForeColor
, rest
);
1148 CopyString(&BackColor
, rest
);
1151 case 5: /* Colorset */
1152 colorset
= atoi(rest
);
1157 AllocColorset(colorset
);
1159 case 6: /* IconFore */
1160 CopyString(&IconForeColor
, rest
);
1163 case 7: /* IconBack */
1164 CopyString(&IconBackColor
, rest
);
1167 case 8: /* IconColorset */
1168 iconcolorset
= atoi(rest
);
1169 if (iconcolorset
< 0)
1173 AllocColorset(iconcolorset
);
1175 case 9: /* Action */
1178 case 10: /* UseSkipList */
1181 case 11: /* AutoFocus */
1184 case 12: /* AutoStick */
1187 case 13: /* AutoHide */
1190 VisiblePixels
=atoi(rest
);
1191 if (VisiblePixels
< 1)
1193 VisiblePixels
= DEFAULT_VISIBLE_PIXELS
;
1196 case 14: /* UseIconNames */
1199 case 15: /* ShowTransients */
1200 ShowTransients
=True
;
1202 case 16: /* DeskOnly */
1205 case 17: /* UpdateInterval */
1206 UpdateInterval
= atoi(rest
);
1207 if (UpdateInterval
< 0)
1209 UpdateInterval
= 30;
1212 case 18: /* HighlightFocus */
1213 HighlightFocus
=True
;
1215 case 19: /* ButtonWidth */
1216 button_width
= atoi(rest
);
1217 if (button_width
< 0)
1219 button_width
= DEFAULT_BTN_WIDTH
;
1222 case 20: /* NoIconAction */
1223 CopyString(&AnimCommand
, rest
);
1224 if (strlen(AnimCommand
) > MAX_NO_ICON_ACTION_LENGTH
)
1225 AnimCommand
[MAX_NO_ICON_ACTION_LENGTH
] = 0;
1227 case 21: /* NoBrightFocus */
1228 NoBrightFocus
= True
;
1230 case 22: /* FocusFore */
1231 CopyString(&FocusForeColor
, rest
);
1234 case 23: /* FocusBack */
1235 CopyString(&FocusBackColor
, rest
);
1238 case 24: /* FocusColorset */
1239 focuscolorset
= atoi(rest
);
1240 if (focuscolorset
< 0)
1244 AllocColorset(focuscolorset
);
1246 case 25: /* 3DFvwm */
1250 RowsNumber
= atoi(rest
);
1251 if (!(1 <= RowsNumber
&& RowsNumber
<= 8))
1256 case 27: /* PageOnly */
1259 case 28: /* ScreenOnly */
1270 if (!GoodiesParseConfig(tline
) &&
1271 !StartButtonParseConfig(tline
))
1273 fprintf(stderr
,"%s: unknown configuration option %s",
1274 module
->name
, tline
);
1278 } /* else options */
1282 Alarm - Handle a SIGALRM - used to implement timeout events
1287 if (AlarmSet
& SHOW_TIP
)
1289 tip_window_alarm
= True
;
1291 if (AlarmSet
& HIDE_TASK_BAR
)
1293 hide_taskbar_alarm
= True
;
1295 if (AlarmSet
& STICK_TASK_BAR
)
1297 stick_taskbar_alarm
= True
;
1301 #if !defined(HAVE_SIGACTION) && !defined(USE_BSD_SIGNALS)
1302 signal (SIGALRM
, Alarm
);
1314 if (hide_taskbar_alarm
)
1316 hide_taskbar_alarm
= False
;
1319 if (stick_taskbar_alarm
)
1321 stick_taskbar_alarm
= False
;
1322 WarpTaskBar(auto_stick_y
);
1324 if (tip_window_alarm
)
1326 tip_window_alarm
= False
;
1327 if (AutoHide
&& WindowState
== 0)
1329 Window dummy_rt
, dummy_c
;
1330 int abs_x
, abs_y
, pos_x
, pos_y
;
1334 /* We are now "sure" that the TaskBar is not hidden for the
1335 Event loop. We send a motion notify for activating tips */
1337 if (FQueryPointer(dpy
, win
, &dummy_rt
,&dummy_c
, &abs_x
, &abs_y
,
1338 &pos_x
, &pos_y
, &dummy
) == False
)
1340 /* pointer is on a different screen */
1344 sevent
.xmotion
.x
= pos_x
;
1345 sevent
.xmotion
.y
= pos_y
;
1346 sevent
.xany
.type
= MotionNotify
;
1347 sevent
.xmotion
.state
= 0;
1348 FSendEvent(dpy
, win
, False
, EnterWindowMask
, &sevent
);
1357 CheckForTip - determine when to popup the tip window
1359 void CheckForTip(int x
, int y
)
1361 int num
, bx
, by
, trunc
;
1364 if (MouseInStartButton(x
, y
, &whichButton
, &startButtonPressed
, NULL
)) {
1365 if((!whichButton
) && (First_Start_Button
->isStartButton
))
1367 if (Tip
.type
!= START_TIP
) PopupTipWindow(3, 0, _("Click here to start"));
1368 Tip
.type
= START_TIP
;
1373 else if (MouseInMail(x
, y
)) {
1374 if (Tip
.type
!= MAIL_TIP
) CreateMailTipWindow();
1375 Tip
.type
= MAIL_TIP
;
1377 else if (MouseInClock(x
, y
)) {
1378 if (Tip
.type
!= DATE_TIP
) CreateDateWindow();
1379 Tip
.type
= DATE_TIP
;
1382 num
= LocateButton(&buttons
, x
, y
, &bx
, &by
, &name
, &trunc
);
1384 if ((Tip
.type
!= num
) ||
1385 (Tip
.text
== NULL
) || (!trunc
&& (strcmp(name
, Tip
.text
) != 0)))
1386 PopupTipWindow(bx
+3, by
, name
);
1393 if (Tip
.type
!= NO_TIP
) {
1394 if (AlarmSet
!= SHOW_TIP
&& !Tip
.open
)
1398 ClearAlarm(SHOW_TIP
);
1407 HandleButtonRelease - Process a ButtonRelease X event
1409 void HandleButtonRelease(
1410 XEvent
*evp
, Time
*NewTimestamp
, int *redraw
)
1416 *NewTimestamp
= evp
->xbutton
.time
;
1418 &buttons
, evp
->xbutton
.x
, evp
->xbutton
.y
);
1419 StartButtonUpdate(NULL
, -1, BUTTON_UP
);
1422 if (MouseInStartButton(
1423 evp
->xbutton
.x
, evp
->xbutton
.y
,
1424 &whichButton
, &startButtonPressed
, &tmp_x
))
1426 if (whichButton
== ButtonPressed
)
1432 r
.width
= StartAndLaunchButtonsWidth
;
1433 r
.height
= StartAndLaunchButtonsHeight
;
1434 XTranslateCoordinates(
1435 dpy
, win
, Root
, r
.x
, r
.y
,
1437 if ((First_Start_Button
->buttonStartCommand
1438 != NULL
) && (startButtonPressed
))
1440 tmp
= module_expand_action(
1442 First_Start_Button
->
1443 buttonStartCommand
, &r
,
1447 SendText(Fvwm_fd
, tmp
, 0);
1454 First_Start_Button
->
1455 buttonStartCommand
, 0);
1461 tmp
= (char *)safemalloc(
1462 100 * sizeof(char));
1467 evp
->xbutton
.button
);
1468 tmp2
= module_expand_action(
1469 dpy
, screen
, tmp
, &r
, NULL
,
1473 SendText(Fvwm_fd
, tmp2
, 0);
1478 SendText(Fvwm_fd
, tmp
, 0);
1487 ButReleased
= ButPressed
; /* Avoid race fvwm pipe */
1488 if (evp
->xbutton
.button
>= 1 &&
1489 evp
->xbutton
.button
<= NUMBER_OF_EXTENDED_MOUSE_BUTTONS
)
1494 ButtonCoordinates(&buttons
, num
, &r
.x
, &r
.y
);
1495 ButtonDimensions(&buttons
, &r
.width
, &r
.height
);
1496 XTranslateCoordinates(
1497 dpy
, win
, Root
, r
.x
, r
.y
, &r
.x
, &r
.y
, &tmpw
);
1498 tmp
= module_expand_action(
1499 dpy
, screen
, ClickAction
[evp
->xbutton
.button
-1],
1504 Fvwm_fd
, tmp
, ItemID(&windows
, num
));
1511 ClickAction
[evp
->xbutton
.button
-1],
1512 ItemID(&windows
, num
));
1517 if (MouseInStartButton(
1518 evp
->xbutton
.x
, evp
->xbutton
.y
, &whichButton
,
1519 &startButtonPressed
, NULL
))
1526 if (num
== ButPressed
)
1527 RadioButton(&buttons
, num
, BUTTON_DOWN
);
1530 Fvwm_fd
, "Focus 0", ItemID(&windows
, num
));
1537 HandleEvents - Process an X event
1540 XEvent
*evp
, Time
*NewTimestamp
, int *redraw
, int *expose_redraw
)
1545 int ex
=10000, ey
=10000, ex2
=0, ey2
=0;
1548 *expose_redraw
= False
;
1553 HandleButtonRelease(evp
, NewTimestamp
, redraw
);
1556 *NewTimestamp
= evp
->xbutton
.time
;
1557 RadioButton(&buttons
, -1, BUTTON_UP
); /* no windows focused
1559 if (MouseInStartButton(
1560 evp
->xbutton
.x
, evp
->xbutton
.y
, &whichButton
,
1561 &startButtonPressed
, NULL
))
1563 StartButtonUpdate(NULL
, whichButton
, BUTTON_DOWN
);
1564 ButtonPressed
= whichButton
;
1566 if (win_y
< Midline
)
1568 /* bar in top half of the screen */
1569 y
= win_y
+ RowHeight
;
1573 /* bar in bottom of the screen */
1574 y
= win_y
- screen_g
.height
;
1579 StartButtonUpdate(NULL
, whichButton
, BUTTON_UP
);
1580 if (MouseInMail(evp
->xbutton
.x
, evp
->xbutton
.y
))
1582 HandleMailClick(*evp
);
1587 &buttons
, evp
->xbutton
.x
,
1589 UpdateButton(&buttons
, num
, NULL
,
1590 (ButPressed
== num
) ?
1591 BUTTON_BRIGHT
: BUTTON_DOWN
);
1599 if (evp
->xexpose
.window
== Tip
.win
)
1601 while (FCheckTypedWindowEvent(
1602 dpy
, evp
->xexpose
.window
, Expose
, evp
));
1609 /* eat up excess Expose events. */
1610 ex
= evp
->xexpose
.x
;
1611 ey
= evp
->xexpose
.y
;
1612 ex2
= evp
->xexpose
.x
+ evp
->xexpose
.width
;
1613 ey2
= evp
->xexpose
.y
+ evp
->xexpose
.height
;
1614 while (FCheckTypedWindowEvent(dpy
, win
, Expose
, evp
))
1616 ex
= min(ex
, evp
->xexpose
.x
);
1617 ey
= min(ey
, evp
->xexpose
.y
);
1618 ex2
= max(ex2
, evp
->xexpose
.x
+ evp
->xexpose
.width
);
1619 ey2
= max(ey2
, evp
->xexpose
.y
+ evp
->xexpose
.height
);
1621 evp
->xexpose
.x
= ex
;
1622 evp
->xexpose
.y
= ey
;
1623 evp
->xexpose
.width
= ex2
- ex
;
1624 evp
->xexpose
.height
= ey2
- ey
;
1626 *expose_redraw
= True
;
1630 if ((evp
->xclient
.format
==32) &&
1631 (evp
->xclient
.data
.l
[0]==wm_del_win
))
1636 *NewTimestamp
= evp
->xcrossing
.time
;
1641 if (evp
->xcrossing
.mode
!= NotifyNormal
)
1644 &buttons
, evp
->xcrossing
.x
, evp
->xcrossing
.y
);
1645 if (!HighlightFocus
)
1647 if (SomeButtonDown(evp
->xcrossing
.state
))
1651 RadioButton(&buttons
, num
, BUTTON_DOWN
);
1663 if (num
!= -1 && num
!= ButPressed
)
1666 ItemID(&windows
, num
));
1669 CheckForTip(evp
->xcrossing
.x
, evp
->xcrossing
.y
);
1673 *NewTimestamp
= evp
->xcrossing
.time
;
1674 ClearAlarm(SHOW_TIP
);
1681 SetAlarm(HIDE_TASK_BAR
);
1683 if (evp
->xcrossing
.mode
!= NotifyNormal
)
1686 if (!HighlightFocus
)
1688 if (SomeButtonDown(evp
->xcrossing
.state
))
1690 if (ButPressed
!= -1)
1692 RadioButton(&buttons
, -1, BUTTON_UP
);
1699 if (ButReleased
!= -1)
1701 RadioButton(&buttons
, -1, BUTTON_UP
);
1710 *NewTimestamp
= evp
->xmotion
.time
;
1711 if (MouseInStartButton(
1712 evp
->xmotion
.x
, evp
->xbutton
.y
, &whichButton
,
1713 &startButtonPressed
, NULL
))
1715 CheckForTip(evp
->xmotion
.x
, evp
->xmotion
.y
);
1718 num
= WhichButton(&buttons
, evp
->xmotion
.x
, evp
->xmotion
.y
);
1719 if (!HighlightFocus
)
1721 if (SomeButtonDown(evp
->xmotion
.state
) &&
1726 RadioButton(&buttons
, num
, BUTTON_DOWN
);
1731 RadioButton(&buttons
, num
, BUTTON_UP
);
1737 else if (num
!= -1 && num
!= ButPressed
)
1738 SendText(Fvwm_fd
, "Focus 0", ItemID(&windows
, num
));
1740 CheckForTip(evp
->xmotion
.x
, evp
->xmotion
.y
);
1743 case ConfigureNotify
:
1746 int cx
= win_x
, cy
= win_y
;
1748 /* eat up excess ConfigureNotify events. */
1749 if (evp
->xconfigure
.send_event
)
1752 cx
= evp
->xconfigure
.x
;
1753 cy
= evp
->xconfigure
.y
;
1756 while (FCheckTypedWindowEvent(dpy
, win
, ConfigureNotify
, evp
))
1759 if (evp
->xconfigure
.send_event
)
1762 cx
= evp
->xconfigure
.x
;
1763 cy
= evp
->xconfigure
.y
;
1767 if (evp
->xconfigure
.height
!= win_height
)
1770 evp
->xconfigure
.width
, evp
->xconfigure
.height
);
1773 SetWindowBackground(
1774 dpy
, win
, win_width
, win_height
,
1775 &Colorset
[colorset
], Pdepth
, graph
,
1780 /* useful because of dynamic style change */
1785 else if (cx
!= win_x
|| cy
!= win_y
)
1787 if (CSET_IS_TRANSPARENT(colorset
))
1789 SetWindowBackground(
1790 dpy
, win
, win_width
, win_height
,
1791 &Colorset
[colorset
],
1792 Pdepth
, graph
, True
);
1795 else if (CheckRootTransparentButtons(&buttons
))
1801 SetAlarm(STICK_TASK_BAR
);
1802 auto_stick_y
= evp
->xconfigure
.y
;
1812 } /* switch evp->type */
1814 XSync(dpy
,0); /* needed (tips) */
1818 LoopOnEvents - Process all the X events we get
1820 void LoopOnEvents(void)
1823 int redraw
, expose_redraw
;
1824 static unsigned long lasttime
= 0L;
1825 Time NewTimestamp
= lasttime
;
1827 while(FPending(dpy
))
1830 expose_redraw
= False
,
1832 FNextEvent(dpy
, &Event
);
1833 NewTimestamp
= lasttime
;
1834 HandleEvents(&Event
, &NewTimestamp
, &redraw
, &expose_redraw
);
1837 RedrawWindow(redraw
, (expose_redraw
)? &Event
:NULL
);
1840 if (NewTimestamp
- lasttime
> UpdateInterval
*1000L)
1843 lasttime
= NewTimestamp
;
1850 AdjustWindow - Resize the window
1852 void AdjustWindow(int width
, int height
)
1854 NRows
= (height
+2)/RowHeight
;
1859 win_height
= height
;
1861 ArrangeButtonArray(&buttons
);
1862 change_colorset(0, False
);
1866 LinkAction - Link an response to a users action
1868 void LinkAction(const char *string
)
1870 const char *temp
=string
;
1871 while(isspace((unsigned char)*temp
)) temp
++;
1873 if(strncasecmp(temp
, "Click", 5)==0)
1879 i
= sscanf(temp
+ 5, "%d%n", &b
, &n
);
1880 if (i
> 0 && b
>=1 && b
<= NUMBER_OF_EXTENDED_MOUSE_BUTTONS
)
1882 CopyString(&ClickAction
[b
- 1], temp
+ 5 + n
);
1885 else if(strncasecmp(temp
, "Enter", 5)==0)
1886 CopyString(&EnterAction
,&temp
[5]);
1889 static void CreateOrUpdateGCs(void)
1892 unsigned long gcmask
;
1908 pfore
= Colorset
[colorset
].fg
;
1909 pback
= Colorset
[colorset
].bg
;
1910 philite
= Colorset
[colorset
].hilite
;
1911 pshadow
= Colorset
[colorset
].shadow
;
1917 philite
= GetHilite(back
);
1919 pshadow
= GetShadow(fore
);
1921 pshadow
= GetShadow(back
);
1923 if (iconcolorset
>= 0)
1925 piconfore
= Colorset
[iconcolorset
].fg
;
1926 piconback
= Colorset
[iconcolorset
].bg
;
1927 piconhilite
= Colorset
[iconcolorset
].hilite
;
1928 piconshadow
= Colorset
[iconcolorset
].shadow
;
1932 piconfore
= iconfore
;
1933 piconback
= iconback
;
1934 piconhilite
= GetHilite(iconback
);
1936 piconshadow
= GetShadow(iconfore
);
1938 piconshadow
= GetShadow(iconback
);
1940 if (focuscolorset
>= 0)
1942 pfocusfore
= Colorset
[focuscolorset
].fg
;
1943 pfocusback
= Colorset
[focuscolorset
].bg
;
1944 pfocushilite
= Colorset
[focuscolorset
].hilite
;
1945 pfocusshadow
= Colorset
[focuscolorset
].shadow
;
1949 pfocusshadow
= pshadow
;
1950 if (FocusForeColor
!= NULL
)
1952 pfocusfore
= focusfore
;
1954 pfocusshadow
= GetShadow(focusfore
);
1960 if (FocusBackColor
!= NULL
)
1962 pfocusback
= focusback
;
1963 pfocushilite
= GetHilite(focusback
);
1965 pfocusshadow
= GetShadow(focusback
);
1970 pfocushilite
= philite
;
1974 /* only the foreground changes for all GCs */
1975 gcval
.background
= pback
;
1976 gcval
.graphics_exposures
= False
;
1978 gcmask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
1980 if (FSelButtonFont
->font
!= NULL
)
1983 gcval
.font
= FSelButtonFont
->font
->fid
;
1986 gcval
.foreground
= pfore
;
1988 XChangeGC(dpy
,graph
,gcmask
,&gcval
);
1990 graph
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
1993 gcval
.foreground
= piconfore
;
1995 XChangeGC(dpy
,icongraph
,gcmask
,&gcval
);
1997 icongraph
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
1999 gcval
.foreground
= piconback
;
2001 XChangeGC(dpy
,iconbackgraph
,gcmask
,&gcval
);
2003 iconbackgraph
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2005 gcval
.foreground
= piconshadow
;
2007 XChangeGC(dpy
,iconshadow
,gcmask
,&gcval
);
2009 iconshadow
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2011 gcval
.foreground
= piconhilite
;
2013 XChangeGC(dpy
,iconhilite
,gcmask
,&gcval
);
2015 iconhilite
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2018 gcval
.foreground
= pfocusfore
;
2020 XChangeGC(dpy
,focusgraph
,gcmask
,&gcval
);
2022 focusgraph
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2024 gcval
.foreground
= pfocusback
;
2026 XChangeGC(dpy
,focusbackgraph
,gcmask
,&gcval
);
2028 focusbackgraph
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2030 gcval
.foreground
= pfocusshadow
;
2032 XChangeGC(dpy
,focusshadow
,gcmask
,&gcval
);
2034 focusshadow
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2036 gcval
.foreground
= pfocushilite
;
2038 XChangeGC(dpy
,focushilite
,gcmask
,&gcval
);
2040 focushilite
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2042 /* "normal" continued */
2043 gcmask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
2044 gcval
.foreground
= pshadow
;
2046 XChangeGC(dpy
,shadow
,gcmask
,&gcval
);
2048 shadow
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2050 gcval
.foreground
= philite
;
2052 XChangeGC(dpy
,hilite
,gcmask
,&gcval
);
2054 hilite
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2056 gcval
.foreground
= PictureWhitePixel();
2058 XChangeGC(dpy
,whitegc
,gcmask
,&gcval
);
2060 whitegc
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2062 gcval
.foreground
= PictureBlackPixel();
2064 XChangeGC(dpy
,blackgc
,gcmask
,&gcval
);
2066 blackgc
= fvwmlib_XCreateGC(dpy
,win
,gcmask
,&gcval
);
2069 gcmask
= GCForeground
| GCBackground
| GCTile
|
2070 GCFillStyle
| GCGraphicsExposures
;
2071 if (focuscolorset
>= 0 || FocusBackColor
!= NULL
)
2072 gcval
.foreground
= pfocusback
;
2074 gcval
.foreground
= philite
;
2075 gcval
.fill_style
= FillTiled
;
2076 gcval
.tile
= XCreatePixmapFromBitmapData(dpy
, win
, (char *)gray_bits
,
2077 gray_width
, gray_height
,
2079 gcval
.background
,Pdepth
);
2081 XChangeGC(dpy
, checkered
, gcmask
, &gcval
);
2083 checkered
= fvwmlib_XCreateGC(dpy
, win
, gcmask
, &gcval
);
2086 static Bool
change_colorset(int cset
, Bool force
)
2088 Bool do_redraw
= False
;
2092 if (force
|| cset
== colorset
|| cset
== iconcolorset
||
2093 cset
== focuscolorset
)
2095 CreateOrUpdateGCs();
2096 if (force
|| cset
== colorset
)
2098 SetWindowBackground(
2099 dpy
, win
, win_width
, win_height
, &Colorset
[colorset
],
2100 Pdepth
, graph
, True
);
2104 do_redraw
|= change_goody_colorset(cset
, force
);
2111 StartMeUp - Do X initialization things
2113 void StartMeUp(void)
2116 XClassHint classhints
;
2119 XSetWindowAttributes attr
;
2123 if (!(dpy
= XOpenDisplay(""))) {
2124 fprintf(stderr
,"%s: can't open display %s", module
->name
,
2128 flib_init_graphics(dpy
);
2131 FScreenConfigureModule(XineramaConfig
);
2132 free(XineramaConfig
);
2134 FlocaleAllocateWinString(&FwinString
);
2135 x_fd
= XConnectionNumber(dpy
);
2136 screen
= DefaultScreen(dpy
);
2137 Root
= RootWindow(dpy
, screen
);
2139 if (geometry
== NULL
)
2140 UpdateString(&geometry
, "+0-0");
2141 /* evaluate further down */
2142 ret
= FScreenParseGeometryWithScreen(
2143 geometry
, &wx
, &wy
, (unsigned int *)&hints
.width
,
2144 (unsigned int *)&hints
.height
, &fscreen
);
2147 &screen_g
.x
, &screen_g
.y
, &screen_g
.width
, &screen_g
.height
);
2149 NULL
, FSCREEN_GLOBAL
,
2150 &global_scr_g
.x
, &global_scr_g
.y
, &global_scr_g
.width
,
2151 &global_scr_g
.height
);
2152 Midline
= (screen_g
.height
>> 1) + screen_g
.y
;
2154 if (selfont_string
== NULL
)
2155 selfont_string
= font_string
;
2157 if ((FButtonFont
= FlocaleLoadFont(dpy
, font_string
,module
->name
)) == NULL
)
2159 fprintf(stderr
, "%s: Couldn't load font. Exiting!\n",module
->name
);
2162 if ((FSelButtonFont
= FlocaleLoadFont(dpy
, selfont_string
,module
->name
))
2165 fprintf(stderr
, "%s: Couldn't load font. Exiting!\n",module
->name
);
2170 fontheight
= (FButtonFont
->height
> FSelButtonFont
->height
)?
2171 FButtonFont
->height
: FSelButtonFont
->height
;
2172 if (goodies_fontheight
> fontheight
)
2173 fontheight
= goodies_fontheight
;
2176 RowHeight
= fontheight
+ 8;
2178 win_border
= 4; /* default border width */
2179 win_height
= RowHeight
+(RowsNumber
-1)*(RowHeight
+2);
2180 win_width
= screen_g
.width
- (win_border
* 2);
2182 /* now evaluate the geometry parsed above */
2183 if (ret
& YNegative
)
2188 wy
= screen_g
.height
- (AutoHide
? VISIBLE_PIXELS() : win_height
);
2190 wy
= AutoHide
? VISIBLE_PIXELS() - win_height
: 0;
2195 wy
+= screen_g
.height
- win_height
;
2201 wy
= AutoHide
? VISIBLE_PIXELS() - win_height
: 0;
2203 wy
= screen_g
.height
- (AutoHide
? VISIBLE_PIXELS() : win_height
);
2207 if (ret
& XNegative
)
2209 if (ret
& YNegative
)
2210 hints
.win_gravity
=SouthEastGravity
;
2212 hints
.win_gravity
=NorthEastGravity
;
2216 if (ret
& YNegative
)
2217 hints
.win_gravity
=SouthWestGravity
;
2219 hints
.win_gravity
=NorthWestGravity
;
2222 hints
.flags
=USPosition
|PPosition
|USSize
|PSize
|PResizeInc
|
2223 PWinGravity
|PMinSize
|PMaxSize
|PBaseSize
;
2225 hints
.width
= win_width
;
2226 hints
.height
= win_height
;
2227 hints
.width_inc
= 1;
2228 hints
.height_inc
= RowHeight
+2;
2229 hints
.min_width
= win_width
;
2230 hints
.min_height
= RowHeight
;
2231 hints
.max_width
= win_width
;
2232 hints
.max_height
= RowHeight
+7*(RowHeight
+2);
2233 hints
.base_width
= win_width
;
2234 hints
.base_height
= RowHeight
;
2236 win_x
= wx
+ win_border
;
2240 back
= PictureWhitePixel();
2241 fore
= PictureBlackPixel();
2242 iconback
= PictureWhitePixel();
2243 iconfore
= PictureBlackPixel();
2244 focusback
= PictureWhitePixel();
2245 focusfore
= PictureBlackPixel();
2247 back
= GetColor(BackColor
);
2248 fore
= GetColor(ForeColor
);
2249 iconback
= GetColor(IconBackColor
);
2250 iconfore
= GetColor(IconForeColor
);
2251 if (FocusBackColor
!= NULL
)
2252 focusback
= GetColor(FocusBackColor
);
2255 if (FocusForeColor
!= NULL
)
2256 focusfore
= GetColor(FocusForeColor
);
2261 attr
.background_pixel
=
2262 (colorset
>= 0) ? Colorset
[colorset
].bg
: back
;
2263 attr
.border_pixel
= 0;
2264 attr
.colormap
= Pcmap
;
2265 win
=XCreateWindow(dpy
,Root
,wx
,wy
,hints
.width
,hints
.height
,0,Pdepth
,
2266 InputOutput
,Pvisual
,CWBackPixel
|CWBorderPixel
|CWColormap
,
2269 wm_del_win
=XInternAtom(dpy
,"WM_DELETE_WINDOW",False
);
2270 XSetWMProtocols(dpy
,win
,&wm_del_win
,1);
2273 XTextProperty nametext
;
2274 char *list
[]={NULL
,NULL
};
2275 list
[0] = module
->name
;
2277 classhints
.res_name
= module
->name
;
2278 classhints
.res_class
= "FvwmTaskBar";
2280 if(!XStringListToTextProperty(list
,1,&nametext
))
2282 fprintf(stderr
,"%s: Failed to convert name to XText\n",module
->name
);
2285 /* hack to prevent mapping on wrong screen with StartsOnScreen */
2286 FScreenMangleScreenIntoUSPosHints(fscreen
, &hints
);
2287 XSetWMProperties(dpy
,win
,&nametext
,&nametext
,
2288 NULL
,0,&hints
,NULL
,&classhints
);
2289 XFree(nametext
.value
);
2292 for (i
= 1; i
<= NUMBER_OF_EXTENDED_MOUSE_BUTTONS
; i
++)
2294 XGrabButton(dpy
,i
,AnyModifier
,win
,True
,GRAB_EVENTS
,GrabModeAsync
,
2295 GrabModeAsync
,None
,None
);
2298 /* SetMwmHints(MWM_DECOR_ALL|MWM_DECOR_MAXIMIZE|MWM_DECOR_MINIMIZE,
2299 MWM_FUNC_ALL|MWM_FUNC_MAXIMIZE|MWM_FUNC_MINIMIZE,
2300 MWM_INPUT_MODELESS);
2303 CreateOrUpdateGCs();
2306 SetWindowBackground(
2307 dpy
, win
, win_width
, win_height
, &Colorset
[colorset
],
2308 Pdepth
, graph
, False
);
2311 XSelectInput(dpy
,win
,(ExposureMask
| KeyPressMask
| PointerMotionMask
|
2312 EnterWindowMask
| LeaveWindowMask
|
2313 StructureNotifyMask
));
2320 ShutMeDown - Do X client cleanup
2328 FreeAllButtons(&buttons
);
2330 XFreeGC(dpy
,icongraph
);
2331 XFreeGC(dpy
,focusgraph
);
2332 XDestroyWindow(dpy
, win
);
2339 ChangeWindowName - Self explanitory
2340 Original work from FvwmIdent:
2341 Copyright 1994, Robert Nation and Nobutaka Suzuki.
2343 void ChangeWindowName(char *str
)
2346 if (XStringListToTextProperty(&str
,1,&name
) == 0) {
2347 fprintf(stderr
,"%s: cannot allocate window name.\n",module
->name
);
2350 XSetWMName(dpy
,win
,&name
);
2351 XSetWMIconName(dpy
,win
,&name
);
2361 * Now, if we (hopefully) have MWW - compatible window manager ,
2362 * say, mwm, ncdwm, or else, we will set useful decoration style.
2363 * Never check for MWM_RUNNING property.May be considered bad.
2366 void SetMwmHints(unsigned int value
, unsigned int funcs
, unsigned int input
)
2372 MwmAtom
=XInternAtom(dpy
,"_MOTIF_WM_HINTS",False
);
2376 /* sh->mwm.decorations contains OR of the MWM_DECOR_XXXXX */
2378 MWM_HINTS_DECORATIONS
| MWM_HINTS_FUNCTIONS
|
2379 MWM_HINTS_INPUT_MODE
;
2380 prop
.props
[1] = funcs
;
2381 prop
.props
[2]= value
;
2382 prop
.props
[3] = input
;
2386 dpy
, win
, MwmAtom
, MwmAtom
, 32, PropModeReplace
,
2387 (unsigned char *)&(prop
.props
[0]),
2388 PROP_MWM_HINTS_ELEMENTS
);
2393 WarpTaskBar -- Enforce AutoStick feature
2395 static void WarpTaskBar(int y
)
2397 /* The tests on y are really useful ! */
2399 ((y
!= screen_g
.y
+ screen_g
.height
- win_height
- win_border
&&
2400 y
!= screen_g
.y
+ win_border
))) {
2403 win_y
= screen_g
.height
- win_height
- win_border
;
2407 win_y
= win_border
+ win_title_height
;
2409 win_y
+= screen_g
.y
;
2411 XMoveWindow(dpy
, win
, win_x
, win_y
);
2416 SetAlarm(HIDE_TASK_BAR
);
2417 ClearAlarm(STICK_TASK_BAR
);
2421 SleepALittle -- do a small delay in a fairly portable way
2422 Replace "#if 1" with "#if 0" to turn delay off
2424 static void SleepALittle(void)
2432 select(0, NULL
, NULL
, NULL
, &tv
);
2438 RevealTaskBar -- Make taskbar fully visible
2440 void RevealTaskBar(void)
2445 ClearAlarm(HIDE_TASK_BAR
);
2446 /* do not reveal if the taskbar is already revealed */
2447 if (WindowState
>= 0)
2450 /* Go faster with the number of rows */
2451 inc_y
+= (NRows
>= 3 ? 3 : 0) + (NRows
>= 5 ? 3 : 0);
2453 if (win_y
< Midline
)
2455 new_win_y
= screen_g
.y
+ win_border
+ win_title_height
;
2456 for (; win_y
<=new_win_y
; win_y
+=inc_y
)
2458 XMoveWindow(dpy
, win
, win_x
, win_y
);
2464 new_win_y
= screen_g
.y
+ screen_g
.height
- win_height
- win_border
;
2465 for (; win_y
>=new_win_y
; win_y
-=inc_y
)
2467 XMoveWindow(dpy
, win
, win_x
, win_y
);
2472 XMoveWindow(dpy
, win
, win_x
, win_y
);
2477 HideTaskbar -- Make taskbar partially visible
2479 void HideTaskBar(void)
2484 int d_x
, d_y
, wx
, wy
;
2487 ClearAlarm(HIDE_TASK_BAR
);
2488 /* do not hide if the taskbar is already hiden */
2489 if (WindowState
== -1 || win_is_shaded
)
2495 dpy
, win
, &d_rt
,&d_ch
, &d_x
, &d_y
, &wx
, &wy
, &mask
) == False
)
2497 /* pointer is on a different screen - that's okay here */
2499 if (wy
>= - (win_border
+ win_title_height
* (win_title_dir
!= DIR_S
)) &&
2500 wy
< win_height
+ win_border
+
2501 win_title_height
* (win_title_dir
== DIR_S
))
2503 if (wy
< 0 || wy
>= win_height
|| wx
< 0 || wx
>= win_width
)
2504 SetAlarm(HIDE_TASK_BAR
);
2509 /* Go faster with the number of rows */
2510 inc_y
+= (NRows
>= 3 ? 2 : 0) + (NRows
>= 5 ? 2 : 0);
2512 if (win_y
< Midline
)
2514 new_win_y
= screen_g
.y
+ VISIBLE_PIXELS() +
2515 win_title_height
* (win_title_dir
== DIR_S
) - win_height
;
2516 for (; win_y
>=new_win_y
; win_y
-=inc_y
)
2518 XMoveWindow(dpy
, win
, win_x
, win_y
);
2524 new_win_y
= screen_g
.y
+ screen_g
.height
- VISIBLE_PIXELS() +
2525 win_title_height
* (win_title_dir
== DIR_S
);
2526 for (; win_y
<=new_win_y
; win_y
+=inc_y
)
2528 XMoveWindow(dpy
, win
, win_x
, win_y
);
2533 XMoveWindow(dpy
, win
, win_x
, win_y
);
2538 SetAlarm -- Schedule a timeout event
2541 SetAlarm(tb_alarm_t event
)
2543 alarm(0); /* remove a race-condition */
2549 ClearAlarm -- Disable timeout events
2552 ClearAlarm(tb_alarm_t event
)
2565 ErrorHandler(Display
*d
, XErrorEvent
*event
)
2567 /* some errors are OK=ish */
2568 if (event
->error_code
== BadPixmap
)
2570 if (event
->error_code
== BadDrawable
)
2572 if (FRenderGetErrorCodeBase() + FRenderBadPicture
== event
->error_code
)
2575 PrintXErrorAndCoredump(d
, event
, module
->name
);