Apply window-jump fix (D. Fries).
[fvwm.git] / modules / FvwmTaskBar / FvwmTaskBar.c
blob93be2f01481bc9d0b2f96f609f4a9bc9079da678
1 /* -*-c-*- */
2 /* FvwmTaskBar Module for Fvwm.
4 * (Much reworked version of FvwmWinList)
5 * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or
6 * Mike_Finger@atk.com)
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
48 #include "config.h"
50 #include <stdio.h>
51 #include <signal.h>
52 #include <fcntl.h>
53 #include <sys/wait.h>
54 #include "libs/ftime.h"
55 #include <sys/stat.h>
56 #include <stdarg.h>
57 #include <locale.h>
59 #include <unistd.h>
60 #include <ctype.h>
62 #ifdef HAVE_SYS_BSDTYPES_H
63 #include <sys/bsdtypes.h> /* Saul */
64 #endif /* 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"
85 #include "List.h"
86 #include "Mallocs.h"
87 #include "Goodies.h"
88 #include "Start.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"
100 #define gray_width 8
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 */
108 int Fvwm_fd[2];
109 int x_fd;
111 /* X related things */
112 Display *dpy;
113 Window Root, win;
114 int screen;
115 Pixel back;
116 Pixel fore;
117 static Pixel iconfore;
118 static Pixel iconback;
119 static Pixel focusfore;
120 static Pixel focusback;
121 GC icongraph = None;
122 GC iconbackgraph = None;
123 GC focusgraph = None;
124 GC focusbackgraph = None;
125 GC graph = None;
126 GC shadow = None;
127 GC hilite = None;
128 GC iconshadow = None;
129 GC iconhilite = None;
130 GC focusshadow = None;
131 GC focushilite = None;
132 GC blackgc = None;
133 GC whitegc = None;
134 GC checkered = None;
135 int pad = 3;
136 int colorset = -1;
137 int iconcolorset = -1;
138 int focuscolorset = -1;
139 FlocaleFont *FButtonFont, *FSelButtonFont;
140 FlocaleWinString *FwinString;
141 int fontheight;
142 static Atom wm_del_win;
143 Atom MwmAtom = None;
144 static Bool is_dead_pipe = False;
146 /* Module related information */
147 ModuleArgs *module;
148 int win_width = 5,
149 win_height = 5,
150 win_grav,
151 win_x,
152 win_y,
153 win_border = 4,
154 win_has_title = 0,
155 win_title_dir = 0,
156 win_title_height = 0,
157 win_is_shaded = 0,
158 button_width = DEFAULT_BTN_WIDTH,
159 ButPressed = -1,
160 ButReleased = -1,
161 Checked = 0,
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;
179 ButtonArray buttons;
180 List windows;
182 char *ClickAction[max(NUMBER_OF_EXTENDED_MOUSE_BUTTONS, 3)] =
184 DEFAULT_CLICK1,
185 DEFAULT_CLICK2,
186 DEFAULT_CLICK3
188 *EnterAction,
189 *BackColor = "white",
190 *ForeColor = "black",
191 *IconBackColor = "white",
192 *IconForeColor = "black",
193 *FocusBackColor = NULL,
194 *FocusForeColor = NULL,
195 *geometry = NULL,
196 *font_string = NULL,
197 *selfont_string = NULL;
199 static char *AnimCommand = NULL;
201 int UseSkipList = False,
202 UseIconNames = False,
203 ShowTransients = False,
204 adjust_flag = False,
205 AutoStick = False,
206 AutoHide = False,
207 AutoFocus = False,
208 HighlightFocus = False,
209 DeskOnly = False,
210 PageOnly = False,
211 ScreenOnly = False,
212 NoBrightFocus = False,
213 ThreeDfvwm = False,
214 RowsNumber = 1;
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)
220 rectangle screen_g;
221 rectangle global_scr_g;
223 int NRows, RowHeight, Midline;
224 int ButtonPressed;
226 #define COUNT_LIMIT 10000
227 long DeskNumber; /* Added by Balaji R */
228 int First = 1;
229 int Count = 0;
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)
265 int i;
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 */
277 if (module==NULL)
279 fprintf(stderr,
280 "FvwmTaskBar Version %s should only be executed by fvwm!\n",
281 VERSION);
282 exit(1);
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);
294 #ifdef SA_RESTART
295 sigact.sa_flags = SA_RESTART;
296 #else
297 sigact.sa_flags = 0;
298 #endif
299 sigact.sa_handler = Alarm;
300 sigaction(SIGALRM, &sigact, NULL);
302 #ifdef SA_INTERRUPT
303 sigact.sa_flags = SA_INTERRUPT;
304 #else
305 sigact.sa_flags = 0;
306 #endif
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);
315 #else
316 #ifdef USE_BSD_SIGNALS
317 fvwmSetSignalMask( sigmask(SIGTERM) | sigmask(SIGPIPE) | sigmask(SIGINT) );
318 #endif
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);
327 #endif
328 #endif
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
334 | M_MINI_ICON
336 /* extended messages */
337 SetMessageMask(Fvwm_fd, MX_VISIBLE_ICON_NAME | MX_PROPERTY_CHANGE);
339 /* Parse the config file */
340 ParseConfig();
342 /* Setup the XConnection */
343 StartMeUp();
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);
352 InitList(&windows);
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 */
367 EndLessLoop();
368 #ifdef FVWM_DEBUG_MSGS
369 if ( isTerminated )
371 fprintf(stderr, "%s: Received signal: exiting...\n", module->name);
373 #endif
374 return 0;
379 EndLessLoop - Read and redraw until we get killed, blocking when can't read
381 void EndLessLoop(void)
383 fd_set readset;
384 fd_set_size_t fd_width;
385 struct timeval tv;
387 fd_width = x_fd;
388 if (Fvwm_fd[1] > fd_width)
389 fd_width = Fvwm_fd[1];
390 ++fd_width;
392 while ( !isTerminated )
394 FD_ZERO(&readset);
395 FD_SET(Fvwm_fd[1], &readset);
396 FD_SET(x_fd, &readset);
398 tv.tv_sec = UpdateInterval;
399 tv.tv_usec = 0;
401 XFlush(dpy);
402 if ( fvwmSelect(fd_width, &readset, NULL, NULL, &tv) > 0 )
405 if (FD_ISSET(x_fd, &readset) || FPending(dpy))
406 LoopOnEvents();
408 if (FD_ISSET(Fvwm_fd[1], &readset))
410 ReadFvwmPipe();
413 DoAlarmAction();
415 DrawGoodies(NULL);
416 } /* while */
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 )
429 DeadPipe(0);
430 else
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)
441 int redraw=-1;
442 int i = -1;
443 char *string;
444 long Desk;
445 FvwmPicture p;
446 struct ConfigWinPacket *cfgpacket;
447 int iconified;
448 rectangle new_g;
450 switch(type)
452 case M_FOCUS_CHANGE:
453 i = FindItem(&windows, body[0]);
454 if (win != body[0])
456 /* This case is handled in LoopOnEvents() */
457 if (IsItemIconified(&windows, body[0]))
458 i = -1;
459 RadioButton(&buttons, i, BUTTON_BRIGHT);
460 ButPressed = i;
461 ButReleased = -1;
462 redraw = 0;
463 FocusInWin = 0;
464 } else
465 FocusInWin = 1;
466 break;
468 case M_ADD_WINDOW:
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)))
476 break;
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)
484 int nb;
485 int nh;
486 int nw;
487 int ntd;
488 int nht;
489 int nth;
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)
499 nh -= nth;
501 else
503 nw -= nth;
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)
509 XSizeHints hints;
510 long dumy;
512 win_border = nb;
513 win_width = nw;
514 win_has_title = nht;
515 win_title_dir = ntd;
516 win_title_height = nth;
517 if (AutoStick)
519 win_x = screen_g.x + win_border;
520 if (!win_is_shaded)
522 if (win_y > Midline)
524 win_y = screen_g.height -
525 (AutoHide ?
526 VISIBLE_PIXELS() -
527 win_title_height * HAS_TITLE_DIR(cfgpacket, DIR_S) :
528 win_height + win_border);
530 else
532 win_y = AutoHide ?
533 VISIBLE_PIXELS() +
534 win_title_height * HAS_TITLE_DIR(cfgpacket, DIR_S) -
535 win_height : win_border + win_title_height;
538 else
540 if (win_y > Midline)
542 win_y = screen_g.height - win_border -
543 HAS_TITLE_DIR(cfgpacket, DIR_S) * win_height;
545 else
547 win_y = win_title_height + win_border -
548 HAS_TITLE_DIR(cfgpacket, DIR_S) * win_height;
551 win_y += screen_g.y;
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);
563 if (AutoStick)
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,
574 -1, -1);
575 ArrangeButtonArray (&buttons);
576 AdjustWindow(win_width, win_height);
577 redraw = 1;
579 if (AutoStick && win_is_shaded != IS_SHADED(cfgpacket))
581 win_is_shaded = IS_SHADED(cfgpacket);
582 if (win_is_shaded)
584 if (win_y > Midline)
586 win_y = screen_g.height - win_border -
587 (win_title_dir == DIR_S) * win_height;
589 else
591 win_y = win_title_height + win_border -
592 (win_title_dir == DIR_S) * win_height;
595 else
597 if (win_y > Midline)
599 win_y = screen_g.height - win_border - win_height;
601 else
603 win_y = win_title_height + win_border;
605 if (AutoHide)
607 WindowState = 1;
608 SetAlarm(HIDE_TASK_BAR);
611 win_y += screen_g.y;
612 XMoveWindow(dpy, win, win_x, win_y);
614 win_is_shaded = IS_SHADED(cfgpacket);
615 win_shade_direction = SHADED_DIR(cfgpacket);
616 break;
619 if ((i=FindItem(&windows, body[0])) != -1)
621 int remove=0;
622 int add = 0;
623 int skiplist = 0;
624 rectangle *pold_g;
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;
631 Bool is_managed;
633 if (!GetItemGeometry(&windows, i, &pold_g))
635 pold_g = &new_g;
638 if (DeskOnly && GetDeskNumber(&windows,i,&Desk))
640 if (IsItemIndexSticky(&windows,i))
642 is_on_desk = True;
643 is_changing_desk = False;
645 else
647 is_on_desk = (DeskNumber == cfgpacket->desk);
648 is_changing_desk = (Desk != cfgpacket->desk);
650 UpdateItemIndexDesk(&windows, i, cfgpacket->desk);
652 if (PageOnly)
654 is_on_page = fvwmrect_do_rectangles_intersect(&new_g, &global_scr_g);
655 is_changing_page =
656 (fvwmrect_do_rectangles_intersect(pold_g, &global_scr_g) !=
657 is_on_page);
659 if (ScreenOnly)
661 is_on_screen = fvwmrect_do_rectangles_intersect(&new_g, &screen_g);
662 is_changing_screen =
663 (fvwmrect_do_rectangles_intersect(pold_g, &screen_g) !=
664 is_on_screen);
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)
671 if (is_managed)
673 /* window entering managed area of the virtual desktop */
674 add = 1;
676 else
678 /* window leaving managed area of the virtual desktop */
679 remove = 1;
683 if (UseSkipList && is_managed)
685 skiplist = IsItemIndexSkipWindowList(&windows,i);
686 if (DO_SKIP_WINDOW_LIST(cfgpacket) && !skiplist)
688 add = 0;
689 remove = 1;
691 if (!DO_SKIP_WINDOW_LIST(cfgpacket) && skiplist) {
692 add = 1;
693 remove = 0;
697 UpdateItemGSFRFlags(&windows, cfgpacket);
698 if (remove)
700 RemoveButton(&buttons, i);
701 redraw = 1;
703 else if (add)
705 AddButton(&buttons, ItemName(&windows,i),
706 GetItemPicture(&windows,i), BUTTON_UP, i,
707 IsItemIndexIconified(&windows, i));
708 redraw = 1;
711 else if (!UseSkipList || !DO_SKIP_WINDOW_LIST(cfgpacket))
713 AddItem(&windows, cfgpacket->w,
714 cfgpacket, cfgpacket->desk, Count++);
715 if (Count > COUNT_LIMIT)
716 Count = 0;
717 i = FindItem(&windows, cfgpacket->w);
718 UpdateItemIndexGeometry(&windows, i, &new_g);
720 if (i != -1)
722 Button *temp = find_n(&buttons, i);
723 if (temp && IS_ICONIFIED(cfgpacket))
724 temp->iconified = 1;
726 break;
728 case M_DESTROY_WINDOW:
729 if ((i = FindItem(&windows, body[0])) == -1)
730 break;
731 DeleteItem(&windows, body[0]);
732 RemoveButton(&buttons, i);
733 redraw = 1;
734 break;
736 case M_MINI_ICON:
737 if (!FMiniIconsSupported || (i = FindItem(&windows, body[0])) == -1)
738 break;
740 MiniIconPacket *mip = (MiniIconPacket *) body;
741 p.picture = mip->picture;
742 p.mask = mip->mask;
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);
751 redraw = 0;
753 break;
755 case M_VISIBLE_NAME:
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)
761 break;
762 if (UpdateButton(&buttons, i, string, DONT_CARE) == -1)
764 rectangle *pold_g;
766 if (GetDeskNumber(&windows, i, &Desk) == 0)
767 break;
768 if (DeskOnly && Desk != DeskNumber)
769 break;
770 if (!GetItemGeometry(&windows, i, &pold_g))
771 break;
772 if (PageOnly && !fvwmrect_do_rectangles_intersect(pold_g, &global_scr_g))
773 break;
774 if (ScreenOnly && !fvwmrect_do_rectangles_intersect(pold_g, &screen_g))
775 break;
776 if (UseSkipList && IsItemIndexSkipWindowList(&windows, i))
777 break;
778 AddButton(&buttons, string, NULL, BUTTON_UP, i,
779 IsItemIndexIconified(&windows, i));
780 redraw = 1;
782 else
783 redraw = 0;
784 break;
786 case M_DEICONIFY:
787 case M_ICONIFY:
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);
798 break;
801 iconified = !iconified;
802 UpdateItemIconifiedFlag(&windows, body[0], iconified);
804 Button *temp = find_n(&buttons, i);
805 if (temp)
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))
814 Window child;
815 int x, y;
816 int abs_x, abs_y;
818 if (win_is_shaded)
820 SendText(Fvwm_fd, "WindowShade Off", win);
821 do_reshade = True;
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],
830 (int)body[10]);
831 } else {
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);
841 if (do_reshade)
843 sprintf(
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;
855 redraw = 0;
857 break;
859 case M_END_WINDOWLIST:
860 AdjustWindow(win_width, win_height);
861 XMapRaised(dpy, win);
862 if (AutoHide)
863 WindowState = -1;
864 else
865 WindowState = 1;
866 break;
868 case M_NEW_DESK:
869 DeskNumber = body[0];
870 if (!First && DeskOnly)
871 redraw_buttons();
872 else
873 First = 0;
874 break;
876 case M_NEW_PAGE:
877 break;
879 case MX_PROPERTY_CHANGE:
880 if (body[0] == MX_PROPERTY_CHANGE_BACKGROUND && body[2] == 0 &&
881 CSET_IS_TRANSPARENT_PR(colorset))
883 SetWindowBackground(
884 dpy, win, win_width, win_height,
885 &Colorset[colorset],
886 Pdepth, graph, True);
887 redraw = 1;
889 break;
891 case M_CONFIG_INFO:
893 char *tline;
894 int cset;
896 tline = (char*)&(body[3]);
897 if (strncasecmp(tline, "Colorset", 8) == 0)
899 cset = LoadColorset(tline + 8);
900 if (change_colorset(cset, False))
902 redraw = 1;
905 else if (strncasecmp(tline, XINERAMA_CONFIG_STRING,
906 sizeof(XINERAMA_CONFIG_STRING) - 1) == 0)
908 FScreenConfigureModule(
909 tline + sizeof(XINERAMA_CONFIG_STRING) - 1);
912 break;
913 } /* switch */
915 if (redraw >= 0)
916 RedrawWindow(redraw, NULL);
919 void redraw_buttons(void)
921 Item *item;
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))))
930 continue;
932 if (DO_SKIP_WINDOW_LIST(item) && UseSkipList)
934 continue;
936 if (PageOnly &&
937 !fvwmrect_do_rectangles_intersect(&item->win_g, &global_scr_g))
939 continue;
941 AddButton(
942 &buttons, item->name, &(item->p), BUTTON_UP, item->count,
943 IS_ICONIFIED(item));
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)
957 is_dead_pipe = True;
958 exit(1);
959 SIGNAL_RETURN;
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
966 handler returns.
968 static RETSIGTYPE
969 TerminateHandler(int sig)
971 fvwmSetTerminate(sig);
972 SIGNAL_RETURN;
975 #if 0
977 WaitForExpose - Used to wait for expose event so we don't draw too early
979 void WaitForExpose(void)
981 XEvent Event;
983 while(1) {
984 FNextEvent(dpy, &Event);
985 if (Event.type == Expose) {
986 if (Event.xexpose.count == 0) break;
990 #endif
993 RedrawWindow - Update the needed lines and erase any old ones
995 void RedrawWindow(int force, XEvent *evp)
997 if (Tip.open)
999 RedrawTipWindow();
1001 /* 98-11-21 13:45, Mohsin_Ahmed, mailto:mosh@sasi.com. */
1002 if( Tip.type >= 0 && AutoFocus )
1004 SendFvwmPipe(
1005 Fvwm_fd, "Iconify off, Raise, Focus",
1006 ItemID( &windows, Tip.type ) );
1010 if (force)
1012 if (evp)
1014 XClearArea(
1015 dpy, win, evp->xexpose.x, evp->xexpose.y,
1016 evp->xexpose.width, evp->xexpose.height, False);
1018 else
1020 XClearArea(
1021 dpy, win, 0, 0, win_width, win_height, False);
1023 DrawGoodies(evp);
1025 DrawButtonArray(&buttons, force, evp);
1026 StartButtonDraw(force, evp);
1027 if (FQLength(dpy) && !force)
1028 LoopOnEvents();
1031 static char *configopts[] =
1033 "imagepath",
1034 "colorset",
1035 XINERAMA_CONFIG_STRING,
1036 NULL
1039 static char *moduleopts[] =
1041 "Font",
1042 "SelFont",
1043 "Geometry",
1044 "Fore",
1045 "Back",
1046 "Colorset",
1047 "IconFore",
1048 "IconBack",
1049 "IconColorset",
1050 "Action",
1051 "UseSkipList",
1052 "AutoFocus",
1053 "AutoStick",
1054 "AutoHide",
1055 "UseIconNames",
1056 "ShowTransients",
1057 "DeskOnly",
1058 "UpdateInterval",
1059 "HighlightFocus",
1060 "ButtonWidth",
1061 "NoIconAction",
1062 "NoBrightFocus",
1063 "FocusFore",
1064 "FocusBack",
1065 "FocusColorset",
1066 "3DFvwm",
1067 "Rows",
1068 "PageOnly",
1069 "ScreenOnly",
1070 "Pad",
1071 NULL
1074 void ParseConfig(void)
1076 char *buf;
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)
1087 char *rest;
1088 int index;
1090 while (isspace((unsigned char)*tline))
1091 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))
1098 rest++;
1099 switch(index)
1101 case 0: /* imagepath */
1102 if (ImagePath)
1104 free(ImagePath);
1106 CopyString(&ImagePath, rest);
1107 break;
1108 case 1: /* colorset */
1109 LoadColorset(rest);
1110 break;
1111 case 2: /* XINERAMA_CONFIG_STRING */
1112 if (XineramaConfig)
1114 free(XineramaConfig);
1116 CopyString(&XineramaConfig, rest);
1117 break;
1118 default:
1119 /* unknown option */
1120 break;
1122 } /* if options */
1123 else
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))
1129 rest++;
1130 switch(index)
1132 case 0: /* Font */
1133 CopyStringWithQuotes(&font_string, rest);
1134 break;
1135 case 1: /* SelFont */
1136 CopyStringWithQuotes(&selfont_string, rest);
1137 break;
1138 case 2: /* Geometry */
1139 while (isspace((unsigned char)*rest) && *rest != '\n' && *rest != 0)
1140 rest++;
1141 UpdateString(&geometry, PeekToken(rest, NULL));
1142 break;
1143 case 3: /* Fore */
1144 CopyString(&ForeColor, rest);
1145 colorset = -1;
1146 break;
1147 case 4: /* Back */
1148 CopyString(&BackColor, rest);
1149 colorset = -1;
1150 break;
1151 case 5: /* Colorset */
1152 colorset = atoi(rest);
1153 if (colorset < 0)
1155 colorset = -1;
1157 AllocColorset(colorset);
1158 break;
1159 case 6: /* IconFore */
1160 CopyString(&IconForeColor, rest);
1161 iconcolorset = -1;
1162 break;
1163 case 7: /* IconBack */
1164 CopyString(&IconBackColor, rest);
1165 iconcolorset = -1;
1166 break;
1167 case 8: /* IconColorset */
1168 iconcolorset = atoi(rest);
1169 if (iconcolorset < 0)
1171 iconcolorset = -1;
1173 AllocColorset(iconcolorset);
1174 break;
1175 case 9: /* Action */
1176 LinkAction(rest);
1177 break;
1178 case 10: /* UseSkipList */
1179 UseSkipList=True;
1180 break;
1181 case 11: /* AutoFocus */
1182 AutoFocus=True;
1183 break;
1184 case 12: /* AutoStick */
1185 AutoStick=True;
1186 break;
1187 case 13: /* AutoHide */
1188 AutoHide=True;
1189 AutoStick=True;
1190 VisiblePixels=atoi(rest);
1191 if (VisiblePixels < 1)
1193 VisiblePixels = DEFAULT_VISIBLE_PIXELS;
1195 break;
1196 case 14: /* UseIconNames */
1197 UseIconNames=True;
1198 break;
1199 case 15: /* ShowTransients */
1200 ShowTransients=True;
1201 break;
1202 case 16: /* DeskOnly */
1203 DeskOnly=True;
1204 break;
1205 case 17: /* UpdateInterval */
1206 UpdateInterval = atoi(rest);
1207 if (UpdateInterval < 0)
1209 UpdateInterval = 30;
1211 break;
1212 case 18: /* HighlightFocus */
1213 HighlightFocus=True;
1214 break;
1215 case 19: /* ButtonWidth */
1216 button_width = atoi(rest);
1217 if (button_width < 0)
1219 button_width = DEFAULT_BTN_WIDTH;
1221 break;
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;
1226 break;
1227 case 21: /* NoBrightFocus */
1228 NoBrightFocus = True;
1229 break;
1230 case 22: /* FocusFore */
1231 CopyString(&FocusForeColor, rest);
1232 focuscolorset = -1;
1233 break;
1234 case 23: /* FocusBack */
1235 CopyString(&FocusBackColor, rest);
1236 focuscolorset = -1;
1237 break;
1238 case 24: /* FocusColorset */
1239 focuscolorset = atoi(rest);
1240 if (focuscolorset < 0)
1242 focuscolorset = -1;
1244 AllocColorset(focuscolorset);
1245 break;
1246 case 25: /* 3DFvwm */
1247 ThreeDfvwm = True;
1248 break;
1249 case 26: /* Rows */
1250 RowsNumber = atoi(rest);
1251 if (!(1 <= RowsNumber && RowsNumber <= 8))
1253 RowsNumber = 1;
1255 break;
1256 case 27: /* PageOnly */
1257 PageOnly=True;
1258 break;
1259 case 28: /* ScreenOnly */
1260 ScreenOnly=True;
1261 break;
1262 case 29: /* Pad */
1263 pad = atoi(rest);
1264 if (pad < 0)
1266 pad = 3;
1268 break;
1269 default:
1270 if (!GoodiesParseConfig(tline) &&
1271 !StartButtonParseConfig(tline))
1273 fprintf(stderr,"%s: unknown configuration option %s",
1274 module->name, tline);
1276 break;
1277 } /* switch */
1278 } /* else options */
1282 Alarm - Handle a SIGALRM - used to implement timeout events
1284 static RETSIGTYPE
1285 Alarm(int nonsense)
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;
1300 AlarmSet = NOT_SET;
1301 #if !defined(HAVE_SIGACTION) && !defined(USE_BSD_SIGNALS)
1302 signal (SIGALRM, Alarm);
1303 #endif
1304 SIGNAL_RETURN;
1308 DoAlarmAction -
1310 void
1311 DoAlarmAction(void)
1314 if (hide_taskbar_alarm)
1316 hide_taskbar_alarm = False;
1317 HideTaskBar();
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;
1331 unsigned int dummy;
1332 XEvent sevent;
1334 /* We are now "sure" that the TaskBar is not hidden for the
1335 Event loop. We send a motion notify for activating tips */
1336 WindowState = 1;
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 */
1341 abs_x = 0;
1342 abs_y = 0;
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);
1349 Tip.type = NO_TIP;
1351 else
1352 ShowTipWindow(1);
1357 CheckForTip - determine when to popup the tip window
1359 void CheckForTip(int x, int y)
1361 int num, bx, by, trunc;
1362 char *name;
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;
1370 else
1371 Tip.type = NO_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;
1381 else {
1382 num = LocateButton(&buttons, x, y, &bx, &by, &name, &trunc);
1383 if (num != -1) {
1384 if ((Tip.type != num) ||
1385 (Tip.text == NULL) || (!trunc && (strcmp(name, Tip.text) != 0)))
1386 PopupTipWindow(bx+3, by, name);
1387 Tip.type = num;
1388 } else {
1389 Tip.type = NO_TIP;
1393 if (Tip.type != NO_TIP) {
1394 if (AlarmSet != SHOW_TIP && !Tip.open)
1395 SetAlarm(SHOW_TIP);
1397 else {
1398 ClearAlarm(SHOW_TIP);
1399 if (Tip.open)
1401 ShowTipWindow(0);
1407 HandleButtonRelease - Process a ButtonRelease X event
1409 void HandleButtonRelease(
1410 XEvent *evp, Time *NewTimestamp, int *redraw)
1412 int num = 0;
1413 int tmp_x;
1414 char *tmp;
1416 *NewTimestamp = evp->xbutton.time;
1417 num = WhichButton(
1418 &buttons, evp->xbutton.x, evp->xbutton.y);
1419 StartButtonUpdate(NULL, -1, BUTTON_UP);
1420 if (num == -1)
1422 if (MouseInStartButton(
1423 evp->xbutton.x, evp->xbutton.y,
1424 &whichButton, &startButtonPressed, &tmp_x))
1426 if (whichButton == ButtonPressed)
1428 rectangle r;
1429 Window tmpw;
1430 r.x = tmp_x;
1431 r.y = 0;
1432 r.width = StartAndLaunchButtonsWidth;
1433 r.height = StartAndLaunchButtonsHeight;
1434 XTranslateCoordinates(
1435 dpy, win, Root, r.x, r.y,
1436 &r.x, &r.y, &tmpw);
1437 if ((First_Start_Button->buttonStartCommand
1438 != NULL) && (startButtonPressed))
1440 tmp = module_expand_action(
1441 dpy, screen,
1442 First_Start_Button->
1443 buttonStartCommand, &r,
1444 NULL, NULL);
1445 if (tmp)
1447 SendText(Fvwm_fd, tmp, 0);
1448 free(tmp);
1450 else
1452 SendText(
1453 Fvwm_fd,
1454 First_Start_Button->
1455 buttonStartCommand, 0);
1458 else
1460 char *tmp2;
1461 tmp = (char *)safemalloc(
1462 100 * sizeof(char));
1463 *tmp = 0;
1465 getButtonCommand(
1466 whichButton, tmp,
1467 evp->xbutton.button);
1468 tmp2 = module_expand_action(
1469 dpy, screen, tmp, &r, NULL,
1470 NULL);
1471 if (tmp2)
1473 SendText(Fvwm_fd, tmp2, 0);
1474 free(tmp2);
1476 else if (*tmp != 0)
1478 SendText(Fvwm_fd, tmp, 0);
1480 free(tmp);
1485 else
1487 ButReleased = ButPressed; /* Avoid race fvwm pipe */
1488 if (evp->xbutton.button >= 1 &&
1489 evp->xbutton.button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
1491 rectangle r;
1492 Window tmpw;
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],
1500 &r, NULL, NULL);
1501 if (tmp)
1503 SendFvwmPipe(
1504 Fvwm_fd, tmp, ItemID(&windows, num));
1505 free(tmp);
1507 else
1509 SendFvwmPipe(
1510 Fvwm_fd,
1511 ClickAction[evp->xbutton.button-1],
1512 ItemID(&windows, num));
1517 if (MouseInStartButton(
1518 evp->xbutton.x, evp->xbutton.y, &whichButton,
1519 &startButtonPressed, NULL))
1521 *redraw = 0;
1522 usleep(50000);
1524 if (HighlightFocus)
1526 if (num == ButPressed)
1527 RadioButton(&buttons, num, BUTTON_DOWN);
1528 if (num != -1)
1529 SendText(
1530 Fvwm_fd, "Focus 0", ItemID(&windows, num));
1532 ButPressed = -1;
1533 *redraw = 0;
1537 HandleEvents - Process an X event
1539 void HandleEvents(
1540 XEvent *evp, Time *NewTimestamp, int *redraw, int *expose_redraw)
1542 int num = 0;
1543 XEvent *evp_save;
1544 int x, y;
1545 int ex=10000, ey=10000, ex2=0, ey2=0;
1547 *redraw = -1;
1548 *expose_redraw = False;
1550 switch(evp->type)
1552 case ButtonRelease:
1553 HandleButtonRelease(evp, NewTimestamp, redraw);
1554 break;
1555 case ButtonPress:
1556 *NewTimestamp = evp->xbutton.time;
1557 RadioButton(&buttons, -1, BUTTON_UP); /* no windows focused
1558 * anymore */
1559 if (MouseInStartButton(
1560 evp->xbutton.x, evp->xbutton.y, &whichButton,
1561 &startButtonPressed, NULL))
1563 StartButtonUpdate(NULL, whichButton, BUTTON_DOWN);
1564 ButtonPressed = whichButton;
1565 x = win_x;
1566 if (win_y < Midline)
1568 /* bar in top half of the screen */
1569 y = win_y + RowHeight;
1571 else
1573 /* bar in bottom of the screen */
1574 y = win_y - screen_g.height;
1577 else
1579 StartButtonUpdate(NULL, whichButton, BUTTON_UP);
1580 if (MouseInMail(evp->xbutton.x, evp->xbutton.y))
1582 HandleMailClick(*evp);
1584 else
1586 num = WhichButton(
1587 &buttons, evp->xbutton.x,
1588 evp->xbutton.y);
1589 UpdateButton(&buttons, num, NULL,
1590 (ButPressed == num) ?
1591 BUTTON_BRIGHT : BUTTON_DOWN);
1592 ButPressed = num;
1595 *redraw = 0;
1596 break;
1598 case Expose:
1599 if (evp->xexpose.window == Tip.win)
1601 while (FCheckTypedWindowEvent(
1602 dpy, evp->xexpose.window, Expose, evp));
1603 if (Tip.open)
1605 RedrawTipWindow();
1607 break;
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;
1625 *redraw = 1;
1626 *expose_redraw = True;
1627 break;
1629 case ClientMessage:
1630 if ((evp->xclient.format==32) &&
1631 (evp->xclient.data.l[0]==wm_del_win))
1632 exit(0);
1633 break;
1635 case EnterNotify:
1636 *NewTimestamp = evp->xcrossing.time;
1637 if (AutoHide)
1639 RevealTaskBar();
1641 if (evp->xcrossing.mode != NotifyNormal)
1642 break;
1643 num = WhichButton(
1644 &buttons, evp->xcrossing.x, evp->xcrossing.y);
1645 if (!HighlightFocus)
1647 if (SomeButtonDown(evp->xcrossing.state))
1649 if (num != -1)
1651 RadioButton(&buttons, num, BUTTON_DOWN);
1652 ButPressed = num;
1653 *redraw = 0;
1655 else
1657 ButPressed = -1;
1661 else
1663 if (num != -1 && num != ButPressed)
1664 SendText(
1665 Fvwm_fd, "Focus 0",
1666 ItemID(&windows, num));
1669 CheckForTip(evp->xcrossing.x, evp->xcrossing.y);
1670 break;
1672 case LeaveNotify:
1673 *NewTimestamp = evp->xcrossing.time;
1674 ClearAlarm(SHOW_TIP);
1675 if (Tip.open)
1677 ShowTipWindow(0);
1680 if (AutoHide)
1681 SetAlarm(HIDE_TASK_BAR);
1683 if (evp->xcrossing.mode != NotifyNormal)
1684 break;
1686 if (!HighlightFocus)
1688 if (SomeButtonDown(evp->xcrossing.state))
1690 if (ButPressed != -1)
1692 RadioButton(&buttons, -1, BUTTON_UP);
1693 ButPressed = -1;
1694 *redraw = 0;
1697 else
1699 if (ButReleased != -1)
1701 RadioButton(&buttons, -1, BUTTON_UP);
1702 ButReleased = -1;
1703 *redraw = 0;
1707 break;
1709 case MotionNotify:
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);
1716 break;
1718 num = WhichButton(&buttons, evp->xmotion.x, evp->xmotion.y);
1719 if (!HighlightFocus)
1721 if (SomeButtonDown(evp->xmotion.state) &&
1722 num != ButPressed)
1724 if (num != -1)
1726 RadioButton(&buttons, num, BUTTON_DOWN);
1727 ButPressed = num;
1729 else
1731 RadioButton(&buttons, num, BUTTON_UP);
1732 ButPressed = -1;
1734 *redraw = 0;
1737 else if (num != -1 && num != ButPressed)
1738 SendText(Fvwm_fd, "Focus 0", ItemID(&windows, num));
1740 CheckForTip(evp->xmotion.x, evp->xmotion.y);
1741 break;
1743 case ConfigureNotify:
1745 Bool moved = False;
1746 int cx = win_x, cy = win_y;
1748 /* eat up excess ConfigureNotify events. */
1749 if (evp->xconfigure.send_event)
1751 moved = True;
1752 cx = evp->xconfigure.x;
1753 cy = evp->xconfigure.y;
1755 evp_save = evp;
1756 while (FCheckTypedWindowEvent(dpy, win, ConfigureNotify, evp))
1758 evp_save = evp;
1759 if (evp->xconfigure.send_event)
1761 moved = True;
1762 cx = evp->xconfigure.x;
1763 cy = evp->xconfigure.y;
1766 evp = evp_save;
1767 if (evp->xconfigure.height != win_height)
1769 AdjustWindow(
1770 evp->xconfigure.width, evp->xconfigure.height);
1771 if (colorset >= 0)
1773 SetWindowBackground(
1774 dpy, win, win_width, win_height,
1775 &Colorset[colorset], Pdepth, graph,
1776 True);
1778 *redraw = 1;
1780 /* useful because of dynamic style change */
1781 if (!moved)
1783 break;
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);
1793 *redraw = 1;
1795 else if (CheckRootTransparentButtons(&buttons))
1797 *redraw = 0;
1799 if (AutoStick)
1801 SetAlarm(STICK_TASK_BAR);
1802 auto_stick_y = evp->xconfigure.y;
1804 else
1806 win_x = cx;
1807 win_y = cy;
1811 break;
1812 } /* switch evp->type */
1814 XSync(dpy,0); /* needed (tips) */
1818 LoopOnEvents - Process all the X events we get
1820 void LoopOnEvents(void)
1822 XEvent Event;
1823 int redraw, expose_redraw;
1824 static unsigned long lasttime = 0L;
1825 Time NewTimestamp = lasttime;
1827 while(FPending(dpy))
1829 redraw = -1;
1830 expose_redraw = False,
1832 FNextEvent(dpy, &Event);
1833 NewTimestamp = lasttime;
1834 HandleEvents(&Event, &NewTimestamp, &redraw, &expose_redraw);
1835 if (redraw >= 0)
1837 RedrawWindow(redraw, (expose_redraw)? &Event:NULL);
1839 DoAlarmAction();
1840 if (NewTimestamp - lasttime > UpdateInterval*1000L)
1842 DrawGoodies(NULL);
1843 lasttime = NewTimestamp;
1846 return;
1850 AdjustWindow - Resize the window
1852 void AdjustWindow(int width, int height)
1854 NRows = (height+2)/RowHeight;
1855 if (NRows <= 0)
1857 NRows = 1;
1859 win_height = height;
1860 win_width = width;
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)
1875 int n;
1876 int b;
1877 int i;
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)
1891 XGCValues gcval;
1892 unsigned long gcmask;
1893 Pixel pfore;
1894 Pixel pback;
1895 Pixel piconfore;
1896 Pixel piconback;
1897 Pixel piconhilite;
1898 Pixel piconshadow;
1899 Pixel pfocusfore;
1900 Pixel pfocusback;
1901 Pixel pfocushilite;
1902 Pixel pfocusshadow;
1903 Pixel philite;
1904 Pixel pshadow;
1906 if (colorset >= 0)
1908 pfore = Colorset[colorset].fg;
1909 pback = Colorset[colorset].bg;
1910 philite = Colorset[colorset].hilite;
1911 pshadow = Colorset[colorset].shadow;
1913 else
1915 pfore = fore;
1916 pback = back;
1917 philite = GetHilite(back);
1918 if(Pdepth < 2)
1919 pshadow = GetShadow(fore);
1920 else
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;
1930 else
1932 piconfore = iconfore;
1933 piconback = iconback;
1934 piconhilite = GetHilite(iconback);
1935 if(Pdepth < 2)
1936 piconshadow = GetShadow(iconfore);
1937 else
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;
1947 else
1949 pfocusshadow = pshadow;
1950 if (FocusForeColor != NULL)
1952 pfocusfore = focusfore;
1953 if(Pdepth < 2)
1954 pfocusshadow = GetShadow(focusfore);
1956 else
1958 pfocusfore = fore;
1960 if (FocusBackColor != NULL)
1962 pfocusback = focusback;
1963 pfocushilite = GetHilite(focusback);
1964 if(!(Pdepth < 2))
1965 pfocusshadow = GetShadow(focusback);
1967 else
1969 pfocusback = back;
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)
1982 gcmask |= GCFont;
1983 gcval.font = FSelButtonFont->font->fid;
1985 /* Normal */
1986 gcval.foreground = pfore;
1987 if (graph)
1988 XChangeGC(dpy,graph,gcmask,&gcval);
1989 else
1990 graph = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
1992 /* iconified */
1993 gcval.foreground = piconfore;
1994 if (iconbackgraph)
1995 XChangeGC(dpy,icongraph,gcmask,&gcval);
1996 else
1997 icongraph = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
1999 gcval.foreground = piconback;
2000 if (iconbackgraph)
2001 XChangeGC(dpy,iconbackgraph,gcmask,&gcval);
2002 else
2003 iconbackgraph = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2005 gcval.foreground = piconshadow;
2006 if (iconshadow)
2007 XChangeGC(dpy,iconshadow,gcmask,&gcval);
2008 else
2009 iconshadow = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2011 gcval.foreground = piconhilite;
2012 if (iconhilite)
2013 XChangeGC(dpy,iconhilite,gcmask,&gcval);
2014 else
2015 iconhilite = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2017 /* focused */
2018 gcval.foreground = pfocusfore;
2019 if (focusbackgraph)
2020 XChangeGC(dpy,focusgraph,gcmask,&gcval);
2021 else
2022 focusgraph = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2024 gcval.foreground = pfocusback;
2025 if (focusbackgraph)
2026 XChangeGC(dpy,focusbackgraph,gcmask,&gcval);
2027 else
2028 focusbackgraph = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2030 gcval.foreground = pfocusshadow;
2031 if (focusshadow)
2032 XChangeGC(dpy,focusshadow,gcmask,&gcval);
2033 else
2034 focusshadow = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2036 gcval.foreground = pfocushilite;
2037 if (focushilite)
2038 XChangeGC(dpy,focushilite,gcmask,&gcval);
2039 else
2040 focushilite = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2042 /* "normal" continued */
2043 gcmask = GCForeground | GCBackground | GCGraphicsExposures;
2044 gcval.foreground = pshadow;
2045 if (shadow)
2046 XChangeGC(dpy,shadow,gcmask,&gcval);
2047 else
2048 shadow = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2050 gcval.foreground = philite;
2051 if (hilite)
2052 XChangeGC(dpy,hilite,gcmask,&gcval);
2053 else
2054 hilite = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2056 gcval.foreground = PictureWhitePixel();
2057 if (whitegc)
2058 XChangeGC(dpy,whitegc,gcmask,&gcval);
2059 else
2060 whitegc = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2062 gcval.foreground = PictureBlackPixel();
2063 if (blackgc)
2064 XChangeGC(dpy,blackgc,gcmask,&gcval);
2065 else
2066 blackgc = fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
2068 /* brighting */
2069 gcmask = GCForeground | GCBackground | GCTile |
2070 GCFillStyle | GCGraphicsExposures;
2071 if (focuscolorset >= 0 || FocusBackColor != NULL)
2072 gcval.foreground = pfocusback;
2073 else
2074 gcval.foreground = philite;
2075 gcval.fill_style = FillTiled;
2076 gcval.tile = XCreatePixmapFromBitmapData(dpy, win, (char *)gray_bits,
2077 gray_width, gray_height,
2078 gcval.foreground,
2079 gcval.background,Pdepth);
2080 if (checkered)
2081 XChangeGC(dpy, checkered, gcmask, &gcval);
2082 else
2083 checkered = fvwmlib_XCreateGC(dpy, win, gcmask, &gcval);
2086 static Bool change_colorset(int cset, Bool force)
2088 Bool do_redraw = False;
2090 if (cset < 0)
2091 return 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);
2102 do_redraw = True;
2104 do_redraw |= change_goody_colorset(cset, force);
2106 return do_redraw;
2111 StartMeUp - Do X initialization things
2113 void StartMeUp(void)
2115 XSizeHints hints;
2116 XClassHint classhints;
2117 int ret;
2118 int i;
2119 XSetWindowAttributes attr;
2120 int wx;
2121 int wy;
2123 if (!(dpy = XOpenDisplay(""))) {
2124 fprintf(stderr,"%s: can't open display %s", module->name,
2125 XDisplayName(""));
2126 exit (1);
2128 flib_init_graphics(dpy);
2129 if (XineramaConfig)
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);
2145 FScreenGetScrRect(
2146 NULL, fscreen,
2147 &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height);
2148 FScreenGetScrRect(
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);
2160 exit(1);
2162 if ((FSelButtonFont = FlocaleLoadFont(dpy, selfont_string,module->name))
2163 == NULL)
2165 fprintf(stderr, "%s: Couldn't load font. Exiting!\n",module->name);
2166 exit(1);
2168 LoadGoodiesFont();
2170 fontheight = (FButtonFont->height > FSelButtonFont->height)?
2171 FButtonFont->height : FSelButtonFont->height;
2172 if (goodies_fontheight > fontheight)
2173 fontheight = goodies_fontheight;
2175 NRows = 1;
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)
2185 if (AutoStick)
2187 if (-wy < Midline)
2188 wy = screen_g.height - (AutoHide ? VISIBLE_PIXELS() : win_height);
2189 else
2190 wy = AutoHide ? VISIBLE_PIXELS() - win_height : 0;
2191 wy += screen_g.y;
2193 else
2195 wy += screen_g.height - win_height;
2198 else if (AutoStick)
2200 if (wy < Midline)
2201 wy = AutoHide ? VISIBLE_PIXELS() - win_height : 0;
2202 else
2203 wy = screen_g.height - (AutoHide ? VISIBLE_PIXELS() : win_height);
2204 wy += screen_g.y;
2207 if (ret & XNegative)
2209 if (ret & YNegative)
2210 hints.win_gravity=SouthEastGravity;
2211 else
2212 hints.win_gravity=NorthEastGravity;
2214 else
2216 if (ret & YNegative)
2217 hints.win_gravity=SouthWestGravity;
2218 else
2219 hints.win_gravity=NorthWestGravity;
2222 hints.flags=USPosition|PPosition|USSize|PSize|PResizeInc|
2223 PWinGravity|PMinSize|PMaxSize|PBaseSize;
2224 wx = screen_g.x;
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;
2237 win_y = wy;
2239 if(Pdepth < 2) {
2240 back = PictureWhitePixel();
2241 fore = PictureBlackPixel();
2242 iconback = PictureWhitePixel();
2243 iconfore = PictureBlackPixel();
2244 focusback = PictureWhitePixel();
2245 focusfore = PictureBlackPixel();
2246 } else {
2247 back = GetColor(BackColor);
2248 fore = GetColor(ForeColor);
2249 iconback = GetColor(IconBackColor);
2250 iconfore = GetColor(IconForeColor);
2251 if (FocusBackColor != NULL)
2252 focusback = GetColor(FocusBackColor);
2253 else
2254 focusback = back;
2255 if (FocusForeColor != NULL)
2256 focusfore = GetColor(FocusForeColor);
2257 else
2258 focusfore = fore;
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,
2267 &attr);
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);
2283 exit(1);
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();
2304 if (colorset >= 0)
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));
2315 InitGoodies();
2316 atexit(ShutMeDown);
2320 ShutMeDown - Do X client cleanup
2322 static void
2323 ShutMeDown(void)
2325 if (!is_dead_pipe)
2327 FreeList(&windows);
2328 FreeAllButtons(&buttons);
2329 XFreeGC(dpy,graph);
2330 XFreeGC(dpy,icongraph);
2331 XFreeGC(dpy,focusgraph);
2332 XDestroyWindow(dpy, win);
2333 XCloseDisplay(dpy);
2339 ChangeWindowName - Self explanitory
2340 Original work from FvwmIdent:
2341 Copyright 1994, Robert Nation and Nobutaka Suzuki.
2343 void ChangeWindowName(char *str)
2345 XTextProperty name;
2346 if (XStringListToTextProperty(&str,1,&name) == 0) {
2347 fprintf(stderr,"%s: cannot allocate window name.\n",module->name);
2348 return;
2350 XSetWMName(dpy,win,&name);
2351 XSetWMIconName(dpy,win,&name);
2352 XFree(name.value);
2357 * Sets mwm hints
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)
2368 PropMwmHints prop;
2370 if (MwmAtom==None)
2372 MwmAtom=XInternAtom(dpy,"_MOTIF_WM_HINTS",False);
2374 if (MwmAtom!=None)
2376 /* sh->mwm.decorations contains OR of the MWM_DECOR_XXXXX */
2377 prop.props[0] =
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;
2384 /* HOP - LA! */
2385 XChangeProperty(
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 ! */
2398 if (!AutoHide &&
2399 ((y != screen_g.y + screen_g.height - win_height - win_border &&
2400 y != screen_g.y + win_border))) {
2401 if (y > Midline)
2403 win_y = screen_g.height - win_height - win_border;
2405 else
2407 win_y = win_border + win_title_height;
2409 win_y += screen_g.y;
2410 XSync(dpy, 0);
2411 XMoveWindow(dpy, win, win_x, win_y);
2412 XSync(dpy, 0);
2415 if (AutoHide)
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)
2426 struct timeval tv;
2428 tv.tv_sec = 0;
2429 tv.tv_usec = 10000;
2430 #if 1
2431 XSync(dpy, 0);
2432 select(0, NULL, NULL, NULL, &tv);
2433 XSync(dpy, 0);
2434 #endif
2438 RevealTaskBar -- Make taskbar fully visible
2440 void RevealTaskBar(void)
2442 int new_win_y;
2443 int inc_y = 2;
2445 ClearAlarm(HIDE_TASK_BAR);
2446 /* do not reveal if the taskbar is already revealed */
2447 if (WindowState >= 0)
2448 return;
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);
2459 SleepALittle();
2462 else
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);
2468 SleepALittle();
2471 win_y = new_win_y;
2472 XMoveWindow(dpy, win, win_x, win_y);
2473 WindowState = 0;
2477 HideTaskbar -- Make taskbar partially visible
2479 void HideTaskBar(void)
2481 int new_win_y;
2482 int inc_y = 1;
2483 Window d_rt, d_ch;
2484 int d_x, d_y, wx, wy;
2485 unsigned int mask;
2487 ClearAlarm(HIDE_TASK_BAR);
2488 /* do not hide if the taskbar is already hiden */
2489 if (WindowState == -1 || win_is_shaded)
2490 return;
2492 if (1||FocusInWin)
2494 if (FQueryPointer(
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);
2505 return;
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);
2519 SleepALittle();
2522 else
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);
2529 SleepALittle();
2532 win_y = new_win_y;
2533 XMoveWindow(dpy, win, win_x, win_y);
2534 WindowState = -1;
2538 SetAlarm -- Schedule a timeout event
2540 static void
2541 SetAlarm(tb_alarm_t event)
2543 alarm(0); /* remove a race-condition */
2544 AlarmSet |= event;
2545 alarm(1);
2549 ClearAlarm -- Disable timeout events
2551 static void
2552 ClearAlarm(tb_alarm_t event)
2554 AlarmSet &= ~event;
2555 if (AlarmSet == 0)
2557 alarm(0);
2562 X Error Handler
2564 static int
2565 ErrorHandler(Display *d, XErrorEvent *event)
2567 /* some errors are OK=ish */
2568 if (event->error_code == BadPixmap)
2569 return 0;
2570 if (event->error_code == BadDrawable)
2571 return 0;
2572 if (FRenderGetErrorCodeBase() + FRenderBadPicture == event->error_code)
2573 return 0;
2575 PrintXErrorAndCoredump(d, event, module->name);
2576 return 0;