Fix segfault setting MenuFace pixmap style for menus.
[fvwm.git] / modules / FvwmWinList / FvwmWinList.c
blob8e57b5a4e69ed10c4697aed39752df5addfed186
1 /* -*-c-*- */
2 /* FvwmWinList Module for Fvwm.
4 * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or
5 * Mike_Finger@atk.com)
7 * The author makes not guarantees or warantees, either express or
8 * implied. Feel free to use any contained here for any purpose, as long
9 * and this and any other applicible copyrights are kept intact.
11 * The functions in this source file that are based on part of the FvwmIdent
12 * module for Fvwm are noted by a small copyright atop that function, all
13 * others are copyrighted by Mike Finger. For those functions modified/used,
14 * here is the full, origonal copyright:
16 * Copyright 1994, Robert Nation and Nobutaka Suzuki.
17 * No guarantees or warantees or anything
18 * are provided or implied in any way whatsoever. Use this program at your
19 * own risk. Permission to use this program for any purpose is given,
20 * as long as the copyright is kept intact.
22 * Modifications Done to Add Pixmaps, focus highlighting and Current Desk Only
23 * By Don Mahurin, 1996, Some of this Code was taken from FvwmTaskBar
26 /* This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 #ifndef NO_CONSOLE
42 #define NO_CONSOLE
43 #endif
45 #define YES "Yes"
46 #define NO "No"
48 #include "config.h"
50 #include <stdio.h>
51 #include <signal.h>
52 #include <fcntl.h>
53 #include "libs/ftime.h"
55 #ifdef HAVE_SYS_BSDTYPES_H
56 #include <sys/bsdtypes.h> /* Saul */
57 #endif
59 #include "libs/Module.h"
60 #include "libs/fvwmsignal.h"
61 #include "libs/fvwmlib.h"
62 #include "libs/FScreen.h"
63 #include "libs/FShape.h"
64 #include "libs/FRenderInit.h"
65 #include "libs/Flocale.h"
66 #include "libs/gravity.h"
67 #include "libs/FRender.h"
68 #include "libs/FRenderInterface.h"
69 #include "libs/ColorUtils.h"
70 #include "libs/Graphics.h"
71 #include "libs/Strings.h"
72 #include "libs/System.h"
73 #include "libs/XError.h"
75 #include "FvwmWinList.h"
76 #include "ButtonArray.h"
77 #include "List.h"
78 #include "Mallocs.h"
79 #include "libs/Colorset.h"
81 #define MAX_NO_ICON_ACTION_LENGTH (MAX_MODULE_INPUT_TEXT_LEN - 100)
83 #define GRAB_EVENTS (ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|EnterWindowMask|LeaveWindowMask)
85 #define COMPLEX_WINDOW_PLACEMENT
87 #define SomeButtonDown(a) ((a) & DEFAULT_ALL_BUTTONS_MASK)
89 /* File type information */
90 FILE *console;
91 fd_set_size_t fd_width;
92 int Fvwm_fd[2];
93 int x_fd;
95 /* X related things */
96 Display *dpy;
97 Window Root;
98 Window win;
99 int screen;
100 int fscreen;
101 rectangle screen_g;
102 Pixel back[MAX_COLOUR_SETS];
103 Pixel fore[MAX_COLOUR_SETS];
104 GC graph[MAX_COLOUR_SETS];
105 GC shadow[MAX_COLOUR_SETS];
106 GC hilite[MAX_COLOUR_SETS];
107 GC background[MAX_COLOUR_SETS];
108 Pixmap win_bg;
109 FlocaleFont *FButtonFont;
110 FlocaleWinString *FwinString;
111 int fontheight;
112 int buttonheight;
113 static Atom wm_del_win;
114 Atom MwmAtom = None;
116 /* Module related information */
117 char *Module;
118 int WindowState=0;
119 int win_width=5;
120 int win_height=5;
121 int win_grav;
122 int win_x;
123 int win_y;
124 int win_title;
125 #ifdef COMPLEX_WINDOW_PLACEMENT
126 int win_border_x=0;
127 int win_border_y=0;
128 #endif
129 int Clength;
130 int Transient=0;
131 int Pressed=0;
132 int ButPressed=-1;
133 int Checked=0;
134 int MinWidth=DEFMINWIDTH;
135 int MaxWidth=DEFMAXWIDTH;
136 ButtonArray buttons;
137 List windows;
138 char *ClickAction[NUMBER_OF_EXTENDED_MOUSE_BUTTONS] =
140 "Iconify -1,Raise",
141 "Iconify",
142 "Lower"
144 *EnterAction,
145 *BackColor[MAX_COLOUR_SETS] = { "white" },
146 *ForeColor[MAX_COLOUR_SETS] = { "black" },
147 *geometry="";
148 int colorset[MAX_COLOUR_SETS];
149 Pixmap pixmap[MAX_COLOUR_SETS];
150 char *font_string = NULL;
151 Bool UseSkipList = False;
152 Bool Anchor = True;
153 Bool UseIconNames = False;
154 Bool LeftJustify = False;
155 Bool TruncateLeft = False;
156 Bool ShowFocus = True;
157 Bool Follow = False;
158 int ReliefWidth = 2;
160 long CurrentDesk = 0;
161 int ShowCurrentDesk = 0;
163 struct
165 unsigned is_shaded : 1;
166 unsigned needs_resize_after_unshade : 1;
167 } flags = { 0, 0 };
169 rectangle cfg_g = { 0, 0, 0, 0 }; /* win geometry from M_CONFIGURE_WINDOW */
171 static RETSIGTYPE TerminateHandler(int sig);
173 static char *AnimCommand = NULL;
176 * TerminateHandler - reentrant signal handler that ends the main event loop
178 static RETSIGTYPE TerminateHandler(int sig)
181 * This function might not return - it could "long-jump"
182 * right out, so we need to do everything we need to do
183 * BEFORE we call it ...
185 fvwmSetTerminate(sig);
186 SIGNAL_RETURN;
189 static void window_shade(unsigned long *body, int do_shade)
191 Window w;
193 w = (Window)(body[0]);
194 if (w != win)
196 return;
198 if (do_shade)
200 flags.is_shaded = 1;
201 flags.needs_resize_after_unshade = 0;
203 else
205 flags.is_shaded = 0;
206 if (flags.needs_resize_after_unshade)
208 AdjustWindow(True);
209 flags.needs_resize_after_unshade = 0;
213 return;
217 Main - Setup the XConnection,request the window list and loop forever
218 Based on main() from FvwmIdent:
219 Copyright 1994, Robert Nation and Nobutaka Suzuki.
221 int main(int argc, char **argv)
223 char *temp, *s;
224 #ifdef HAVE_SIGACTION
225 struct sigaction sigact;
226 #endif
227 int i;
228 short opt_num;
230 for (i = 3; i < NUMBER_OF_EXTENDED_MOUSE_BUTTONS; i++)
232 ClickAction[i] = "Nop";
235 /* Save the program name for error messages and config parsing */
236 temp = argv[0];
237 s=strrchr(argv[0], '/');
238 if (s != NULL)
239 temp = s + 1;
241 /* Open the console for messages */
242 OpenConsole();
244 if((argc != 6)&&(argc != 7)&&(argc != 8)) {
245 fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",temp,
246 VERSION);
247 ConsoleMessage("%s Version %s should only be executed by fvwm!\n",temp,
248 VERSION);
249 exit(1);
252 opt_num = 6;
253 if (argc == 7 && (strcasecmp(argv[6],"Transient") == 0 ||
254 strcasecmp(argv[6],"-Transient") == 0))
256 Transient=1;
257 opt_num++;
260 /* Check for an alias */
261 if (argc >= opt_num + 1 && argv[opt_num] != NULL)
263 Module = safemalloc(strlen(argv[opt_num])+2);
264 strcpy(Module,"*");
265 strcat(Module, argv[opt_num]);
266 Clength = strlen(Module);
268 else
270 Module = safemalloc(strlen(temp)+2);
271 strcpy(Module,"*");
272 strcat(Module, temp);
273 Clength = strlen(Module);
276 FlocaleInit(LC_CTYPE, "", "", "FvwmWinList");
278 Fvwm_fd[0] = atoi(argv[1]);
279 Fvwm_fd[1] = atoi(argv[2]);
281 #ifdef HAVE_SIGACTION
282 #ifdef SA_INTERRUPT
283 sigact.sa_flags = SA_INTERRUPT;
284 #else
285 sigact.sa_flags = 0;
286 #endif
287 sigemptyset(&sigact.sa_mask);
288 sigaddset(&sigact.sa_mask, SIGTERM);
289 sigaddset(&sigact.sa_mask, SIGPIPE);
290 sigaddset(&sigact.sa_mask, SIGINT);
291 sigact.sa_handler = TerminateHandler;
292 sigaction(SIGPIPE, &sigact, NULL);
293 sigaction(SIGTERM, &sigact, NULL);
294 sigaction(SIGINT, &sigact, NULL);
295 #else
296 #ifdef USE_BSD_SIGNALS
297 fvwmSetSignalMask( sigmask(SIGPIPE) |
298 sigmask(SIGINT) |
299 sigmask(SIGTERM) );
300 #endif
301 signal(SIGPIPE, TerminateHandler);
302 signal(SIGTERM, TerminateHandler);
303 signal(SIGINT, TerminateHandler);
304 #ifdef HAVE_SIGINTERRUPT
305 siginterrupt(SIGPIPE, True);
306 siginterrupt(SIGTERM, True);
307 siginterrupt(SIGINT, True);
308 #endif
309 #endif
311 /* set default colorsets */
312 colorset[0] = colorset[1] = 0;
313 colorset[2] = colorset[3] = 1;
314 AllocColorset(1);
315 FlocaleAllocateWinString(&FwinString);
317 /* Setup the XConnection */
318 StartMeUp_I();
319 /* Parse the config file */
320 ParseConfig();
321 /* more initialisations */
322 StartMeUp_II();
323 XSetErrorHandler(ErrorHandler);
325 InitArray(&buttons,0,0,win_width, fontheight+2, ReliefWidth);
326 InitList(&windows);
328 fd_width = GetFdWidth();
330 /* Request a list of all windows,
331 * wait for ConfigureWindow packets */
332 SetMessageMask(Fvwm_fd,
333 M_MINI_ICON |
334 M_CONFIGURE_WINDOW | M_ADD_WINDOW | M_DESTROY_WINDOW |
335 M_VISIBLE_NAME | M_DEICONIFY |
336 M_ICONIFY | M_END_WINDOWLIST | M_NEW_DESK | M_FOCUS_CHANGE |
337 M_CONFIG_INFO | M_SENDCONFIG | M_WINDOWSHADE |
338 M_DEWINDOWSHADE);
339 /* extended messages */
340 SetMessageMask(Fvwm_fd, MX_VISIBLE_ICON_NAME | MX_PROPERTY_CHANGE);
342 SendText(Fvwm_fd, "Send_WindowList",0);
344 /* Recieve all messages from Fvwm */
345 atexit(ShutMeDown);
347 /* tell fvwm we're running */
348 SendFinishedStartupNotification(Fvwm_fd);
350 /* Lock on send only for iconify and deiconify (for NoIconAction) */
351 SetSyncMask(Fvwm_fd, M_DEICONIFY | M_ICONIFY);
352 SetNoGrabMask(Fvwm_fd, M_DEICONIFY | M_ICONIFY);
354 MainEventLoop();
355 return 0;
360 MainEventLoop - Read and redraw until we die, blocking when can't read
362 void MainEventLoop(void)
364 fd_set readset;
366 while( !isTerminated ) {
367 FD_ZERO(&readset);
368 FD_SET(Fvwm_fd[1],&readset);
369 FD_SET(x_fd,&readset);
371 /* This code restyled after FvwmIconMan, which is simpler.
372 * The biggest advantage over the original approach is
373 * having one fewer select statements
375 XFlush(dpy);
376 if (fvwmSelect(fd_width, &readset, NULL, NULL, NULL) > 0) {
378 if (FD_ISSET(x_fd,&readset) || FPending(dpy)) LoopOnEvents();
379 if (FD_ISSET(Fvwm_fd[1],&readset)) ReadFvwmPipe();
383 } /* while */
387 ReadFvwmPipe - Read a single message from the pipe from Fvwm
388 Originally Loop() from FvwmIdent:
389 Copyright 1994, Robert Nation and Nobutaka Suzuki.
391 void ReadFvwmPipe(void)
393 FvwmPacket* packet = ReadFvwmPacket(Fvwm_fd[1]);
394 if ( packet == NULL )
395 exit(0);
396 else
397 ProcessMessage( packet->type, packet->body );
401 ProcessMessage - Process the message coming from Fvwm
402 Skeleton based on processmessage() from FvwmIdent:
403 Copyright 1994, Robert Nation and Nobutaka Suzuki.
405 void ProcessMessage(unsigned long type,unsigned long *body)
407 int redraw=0,i,j;
408 Item *flagitem;
409 char *name,*string;
410 static int current_focus=-1;
411 struct ConfigWinPacket *cfgpacket;
412 FvwmPicture p;
414 switch(type)
416 case M_ADD_WINDOW:
417 case M_CONFIGURE_WINDOW:
418 cfgpacket = (void *) body;
419 /* We get the win_borders only when WinList map it self, this is ok
420 * since we need it only after an unmap */
421 if (cfgpacket->w == win)
423 cfg_g.x = cfgpacket->frame_x;
424 cfg_g.y = cfgpacket->frame_y;
425 cfg_g.width = cfgpacket->frame_width;
426 cfg_g.height = cfgpacket->frame_height;
427 #ifdef COMPLEX_WINDOW_PLACEMENT
428 win_border_x = win_border_y = cfgpacket->border_width;
429 if (((win_grav == NorthWestGravity || win_grav == NorthEastGravity)
430 && HAS_TITLE_DIR(cfgpacket, DIR_N)) ||
431 ((win_grav == SouthWestGravity || win_grav == SouthEastGravity)
432 && HAS_TITLE_DIR(cfgpacket, DIR_S)))
434 win_border_y += cfgpacket->title_height;
436 if (((win_grav == NorthWestGravity || win_grav == SouthWestGravity)
437 && HAS_TITLE_DIR(cfgpacket, DIR_W)) ||
438 ((win_grav == NorthEastGravity || win_grav == SouthEastGravity)
439 && HAS_TITLE_DIR(cfgpacket, DIR_E)))
441 win_border_x += cfgpacket->title_height;
443 #endif
445 if ((i = FindItem(&windows,cfgpacket->w))!=-1)
447 flagitem=ItemFlags(&windows,cfgpacket->w);
448 if(UpdateItemDesk(&windows, cfgpacket) > 0 ||
449 IS_STICKY_ACROSS_DESKS(cfgpacket) !=
450 IS_STICKY_ACROSS_DESKS(flagitem) ||
451 DO_SKIP_WINDOW_LIST(cfgpacket) != DO_SKIP_WINDOW_LIST(flagitem))
453 UpdateItemGSFRFlags(&windows, cfgpacket);
454 UpdateButtonDeskFlags(&buttons, i, cfgpacket->desk,
455 IS_STICKY_ACROSS_DESKS(cfgpacket),
456 DO_SKIP_WINDOW_LIST(cfgpacket));
457 AdjustWindow(False);
458 RedrawWindow(True, True, NULL);
460 else
461 UpdateItemGSFRFlags(&windows, cfgpacket);
462 break;
464 else
466 AddItem(&windows, cfgpacket);
467 /* Make sure the lists are synced in order
468 If windows are created during a Send_WindowList strange things might happen
470 AddButton(&buttons, NULL, NULL, 1);
471 i = FindItem(&windows,cfgpacket->w);
472 UpdateButtonDeskFlags(&buttons, i, cfgpacket->desk,
473 IS_STICKY_ACROSS_DESKS(cfgpacket),
474 DO_SKIP_WINDOW_LIST(cfgpacket));
476 break;
477 case M_DESTROY_WINDOW:
478 cfgpacket = (void *) body;
479 if ((i=DeleteItem(&windows,cfgpacket->w))==-1) break;
480 RemoveButton(&buttons,i);
481 if (WindowState)
482 AdjustWindow(False);
483 redraw=1;
484 break;
486 case M_MINI_ICON:
487 if (!FMiniIconsSupported || (i=FindItem(&windows,body[0]))==-1)
488 break;
489 if (UpdateButton(&buttons,i,NULL,-1)!=-1)
491 MiniIconPacket *mip = (MiniIconPacket *) body;
492 p.picture = mip->picture;
493 p.mask = mip->mask;
494 p.alpha = mip->alpha;
495 p.width = mip->width;
496 p.height = mip->height;
497 p.depth = mip->depth;
499 UpdateButtonPicture(&buttons, i, &p);
501 AdjustWindow(False);
502 redraw = 1;
504 break;
506 case M_VISIBLE_NAME:
507 case MX_VISIBLE_ICON_NAME:
508 if ((type == MX_VISIBLE_ICON_NAME) ^ UseIconNames)
509 break;
510 string=(char *)&body[3];
511 if ((i=UpdateItemName(&windows,body[0],string))==-1) break;
512 flagitem = ItemFlags(&windows,body[0]);
513 name=makename(string, (IS_ICONIFIED(flagitem)?True:False));
515 if (UpdateButton(&buttons,i,name,-1)==-1)
517 AddButton(&buttons, name, NULL, 1);
518 UpdateButtonSet(&buttons, i, (IS_ICONIFIED(flagitem)?1:0));
519 UpdateButtonDeskFlags(&buttons,i,ItemDesk(&windows, body[0]),
520 IS_STICKY_ACROSS_DESKS(flagitem),
521 DO_SKIP_WINDOW_LIST(flagitem));
523 free(name);
524 if (WindowState) AdjustWindow(False);
525 redraw=1;
526 break;
527 case M_DEICONIFY:
528 case M_ICONIFY:
529 /* fwvm will wait for an Unlock message before continuing
530 * be careful when changing this construct, make sure unlock happens */
531 if ((i = FindItem(&windows, body[0])) != -1)
533 flagitem = ItemFlags(&windows, body[0]);
534 if ((type == M_DEICONIFY && IS_ICONIFIED(flagitem))
535 || (type == M_ICONIFY && !IS_ICONIFIED(flagitem)))
537 if (IS_ICON_SUPPRESSED(flagitem) && IsItemIndexVisible(&windows,i)
538 && AnimCommand && WindowState && AnimCommand[0] != 0)
540 char buff[MAX_MODULE_INPUT_TEXT_LEN];
541 Window child;
542 int x, y, w, h;
544 /* find out where our button is */
545 j = FindItemVisible(&windows, body[0]);
546 XTranslateCoordinates(
547 dpy, win, Root, 0, j * buttonheight, &x, &y, &child);
548 w = win_width;
549 h = buttonheight;
550 if (flags.is_shaded)
552 if (w > cfg_g.width - win_border_x)
554 w = 1;
556 if (h > cfg_g.height - win_border_y)
558 h = 1;
560 if (x < cfg_g.x || x > cfg_g.x + cfg_g.width)
562 x = cfg_g.x + win_border_x;
564 if (y < cfg_g.y || y > cfg_g.y + cfg_g.height)
566 y = cfg_g.y + win_border_y;
570 /* tell FvwmAnimate to animate to our button */
571 if (IS_ICONIFIED(flagitem)) {
572 sprintf(buff, "%s %d %d %d %d %d %d %d %d", AnimCommand,
573 x, y, w, h, (int)body[7], (int)body[8],
574 (int)body[9], (int)body[10]);
575 } else {
576 sprintf(buff, "%s %d %d %d %d %d %d %d %d",
577 AnimCommand, (int)body[7], (int)body[8],
578 (int)body[9], (int)body[10],
579 x, y, w, h);
581 SendText(Fvwm_fd, buff, 0);
583 SET_ICONIFIED(flagitem, !IS_ICONIFIED(flagitem));
584 string = ItemName(&windows, i);
585 name = makename(string, IS_ICONIFIED(flagitem));
586 UpdateButtonIconified(&buttons, i, IS_ICONIFIED(flagitem));
587 if (UpdateButton(&buttons, i, name, -1) != -1) redraw = 1;
588 if (i != current_focus || (IS_ICONIFIED(flagitem)))
589 if (UpdateButtonSet(&buttons, i, (IS_ICONIFIED(flagitem)) ? 1 : 0)
590 != -1)
591 redraw = 1;
592 free(name);
595 SendUnlockNotification(Fvwm_fd);
596 break;
597 case M_FOCUS_CHANGE:
598 redraw = 1;
599 if ((i=FindItem(&windows,body[0]))!=-1)
601 RadioButton(&buttons,i,ButPressed);
602 if (Follow && i) { /* rearrange order */
603 ReorderList(&windows,i,body[2]);
604 if (WindowState) ReorderButtons(&buttons,i,body[2]);
607 else
608 RadioButton(&buttons,-1,ButPressed);
609 break;
610 case M_END_WINDOWLIST:
611 if (!WindowState)
612 MakeMeWindow();
613 redraw = 1;
614 break;
615 case M_NEW_DESK:
616 CurrentDesk = body[0];
617 if(ShowCurrentDesk)
619 AdjustWindow(False);
620 RedrawWindow(True, True, NULL);
622 break;
623 case M_WINDOWSHADE:
624 window_shade(body, 1);
625 break;
626 case M_DEWINDOWSHADE:
627 window_shade(body, 0);
628 break;
629 case MX_PROPERTY_CHANGE:
630 if (body[0] == MX_PROPERTY_CHANGE_BACKGROUND && body[2] == 0 &&
631 WindowState && win_bg == ParentRelative)
633 RedrawWindow(True, True, NULL);
635 break;
636 case M_CONFIG_INFO:
637 ParseConfigLine((char *)&body[3]);
638 break;
641 if (redraw && WindowState==1) RedrawWindow(False, True, NULL);
646 RedrawWindow - Update the needed lines and erase any old ones
648 void RedrawWindow(Bool force, Bool clear_bg, XEvent *evp)
650 DrawButtonArray(&buttons, force, clear_bg, evp);
651 XFlush(dpy); /** Put here for VMS; ifdef if causes performance problem **/
652 if (FQLength(dpy) && !force) LoopOnEvents();
656 ConsoleMessage - Print a message on the console. Works like printf.
658 void ConsoleMessage(const char *fmt, ...)
660 #ifndef NO_CONSOLE
661 va_list args;
662 FILE *filep;
664 if (console==NULL) filep=stderr;
665 else filep=console;
666 va_start(args,fmt);
667 vfprintf(filep,fmt,args);
668 va_end(args);
669 #endif
673 OpenConsole - Open the console as a way of sending messages
675 int OpenConsole(void)
677 #ifndef NO_CONSOLE
678 if ((console=fopen("/dev/console","w"))==NULL) {
679 fprintf(stderr,"%s: cannot open console\n",Module);
680 return 0;
682 #endif
683 return 1;
687 ParseConfig - Parse the configuration file fvwm to us to use
688 Based on part of main() from FvwmIdent:
689 Copyright 1994, Robert Nation and Nobutaka Suzuki.
691 void ParseConfig(void)
693 char *tline;
695 InitGetConfigLine(Fvwm_fd,Module);
696 GetConfigLine(Fvwm_fd,&tline);
697 while(tline != (char *)0)
699 ParseConfigLine(tline);
700 GetConfigLine(Fvwm_fd,&tline);
704 void
705 ParseConfigLine(char *tline)
707 static Bool has_icon_back = False;
708 static Bool has_icon_fore = False;
709 static Bool has_icon_cset = False;
711 if (!tline)
712 return;
714 if (strlen(tline) > 1) {
715 if (strncasecmp(tline, CatString3(Module, "Font", ""), Clength + 4) == 0)
716 CopyStringWithQuotes(&font_string, &tline[Clength + 4]);
717 else if (strncasecmp(tline, CatString3(Module, "Fore", ""), Clength + 4)
718 == 0) {
719 CopyString(&ForeColor[0], &tline[Clength + 4]);
720 colorset[0] = -1;
721 if (!has_icon_cset)
722 colorset[1] = -1;
723 if (!has_icon_fore)
724 CopyString(&ForeColor[1], &tline[Clength + 4]);
725 } else if (strncasecmp(tline, CatString3(Module, "IconFore", ""),
726 Clength + 8) == 0) {
727 CopyString(&ForeColor[1], &tline[Clength + 8]);
728 if (colorset[0] >= 0)
729 colorset[1] = colorset[0];
730 else
731 colorset[1] = -1;
732 has_icon_fore = True;
733 has_icon_cset = False;
734 } else if (strncasecmp(tline, CatString3(Module, "FocusFore", ""),
735 Clength + 9) == 0) {
736 CopyString(&ForeColor[2], &tline[Clength + 9]);
737 CopyString(&ForeColor[3], &tline[Clength + 9]);
738 colorset[2] = colorset[3] = -1;
739 } else if (strncasecmp(tline, CatString3(Module, "Geometry", ""),
740 Clength + 8) == 0)
741 CopyString(&geometry, &tline[Clength + 8]);
742 else if (strncasecmp(tline, CatString3(Module, "Back", ""), Clength + 4)
743 == 0) {
744 CopyString(&BackColor[0], &tline[Clength + 4]);
745 colorset[0] = -1;
746 if (!has_icon_cset)
747 colorset[1] = -1;
748 if (!has_icon_back)
749 CopyString(&BackColor[1], &tline[Clength + 4]);
750 } else if (strncasecmp(tline, CatString3(Module, "IconBack", ""),
751 Clength + 8) == 0) {
752 CopyString(&BackColor[1], &tline[Clength + 8]);
753 if (colorset[0] >= 0)
754 colorset[1] = colorset[0];
755 else
756 colorset[1] = -1;
757 has_icon_fore = True;
758 has_icon_cset = False;
759 } else if (strncasecmp(tline, CatString3(Module, "FocusBack", ""),
760 Clength + 9) == 0) {
761 CopyString(&BackColor[2], &tline[Clength + 9]);
762 CopyString(&BackColor[3], &tline[Clength + 9]);
763 colorset[2] = colorset[3] = -1;
764 } else if (strncasecmp(tline, CatString3(Module, "NoAnchor", ""),
765 Clength + 8) == 0)
766 Anchor = False;
767 else if (strncasecmp(tline, CatString3(Module, "Action", ""), Clength + 6)
768 == 0)
769 LinkAction(&tline[Clength + 6]);
770 else if (strncasecmp(tline, CatString3(Module, "UseSkipList", ""),
771 Clength + 11) == 0)
772 UseSkipList = True;
773 else if (strncasecmp(tline, CatString3(Module, "UseIconNames", ""),
774 Clength + 12) == 0)
775 UseIconNames = True;
776 else if (strncasecmp(tline, CatString3(Module, "ShowCurrentDesk", ""),
777 Clength + 15) == 0)
778 ShowCurrentDesk = 1;
779 else if (strncasecmp(tline, CatString3(Module, "LeftJustify", ""),
780 Clength + 11) == 0)
781 LeftJustify = True;
782 else if (strncasecmp(tline, CatString3(Module, "TruncateLeft", ""),
783 Clength + 12) == 0)
784 TruncateLeft = True;
785 else if (strncasecmp(tline, CatString3(Module, "MinWidth", ""),
786 Clength + 8) == 0)
787 MinWidth = atoi(&tline[Clength + 8]);
788 else if (strncasecmp(tline, CatString3(Module, "MaxWidth", ""),
789 Clength + 8) == 0)
790 MaxWidth = atoi(&tline[Clength + 8]);
791 else if (strncasecmp(tline, CatString3(Module, "DontDepressFocus", ""),
792 Clength + 16) == 0)
793 ShowFocus = False;
794 else if (strncasecmp(tline, CatString3(Module, "FollowWindowList", ""),
795 Clength + 16) == 0)
796 Follow = True;
797 else if (strncasecmp(tline, CatString3(Module, "ButtonFrameWidth", ""),
798 Clength + 16) == 0) {
799 ReliefWidth = atoi(&tline[Clength + 16]);
800 buttonheight = fontheight + 3 + 2 * ReliefWidth;
801 } else if (strncasecmp(tline, CatString3(Module, "NoIconAction", ""),
802 Clength + 12) == 0) {
803 CopyString(&AnimCommand, &tline[Clength + 12]);
804 if (strlen(AnimCommand) > MAX_NO_ICON_ACTION_LENGTH)
805 AnimCommand[MAX_NO_ICON_ACTION_LENGTH] = 0;
806 } else if (strncasecmp(tline, CatString3(Module, "Colorset", ""),
807 Clength + 8) == 0) {
808 colorset[0] = atoi(&tline[Clength + 8]);
809 AllocColorset(colorset[0]);
810 } else if (strncasecmp(tline, CatString3(Module, "IconColorset", ""),
811 Clength + 12) == 0)
813 colorset[1] = atoi(&tline[Clength + 12]);
814 AllocColorset(colorset[1]);
815 has_icon_cset = True;
817 else if (strncasecmp(tline, CatString3(Module, "FocusColorset", ""),
818 Clength + 13) == 0)
820 colorset[2] = colorset[3] = atoi(&tline[Clength + 13]);
821 AllocColorset(colorset[3]);
822 has_icon_cset = True;
824 else if (strncasecmp(tline, "Colorset", 8) == 0) {
825 int cset = LoadColorset(&tline[8]);
827 if (WindowState && (cset >= 0)) {
828 int i;
829 Pixmap old_win_bg = win_bg;
831 /* set the window background */
832 win_bg = None;
833 for (i = 0; i != MAX_COLOUR_SETS; i++)
835 if (CSET_IS_TRANSPARENT_PR(colorset[i]))
836 win_bg = ParentRelative;
838 if (old_win_bg != win_bg)
839 XSetWindowBackgroundPixmap(dpy, win, win_bg);
840 /* refresh if this colorset is used */
841 for (i = 0; i != MAX_COLOUR_SETS; i++) {
842 if (colorset[i] == cset) {
843 AdjustWindow(True);
844 RedrawWindow(True, True, NULL);
845 break;
850 else if (strncasecmp(tline, XINERAMA_CONFIG_STRING,
851 sizeof(XINERAMA_CONFIG_STRING) - 1) == 0) {
852 FScreenConfigureModule(
853 tline + sizeof(XINERAMA_CONFIG_STRING) - 1);
860 LoopOnEvents - Process all the X events we get
862 void LoopOnEvents(void)
864 int num;
865 char buffer[10];
866 XEvent Event;
867 #if 1
868 Window dummyroot,dummychild;
869 int x,xdummy,y,ydummy;
870 unsigned int dummy1;
872 if (Transient && !Checked)
874 if (Pressed)
876 if (FQueryPointer(
877 dpy, win, &dummyroot, &dummychild, &xdummy, &ydummy, &x, &y,
878 &dummy1) == False)
880 /* pointer is on a different screen - that's okay here */
882 num=WhichButton(&buttons,x,y);
883 if (num!=-1)
885 Pressed=1;
886 ButPressed=num;
887 UpdateButton(&buttons, num, NULL, 0);
889 else
891 Pressed=0;
894 Checked=1;
896 #endif
898 while(FPending(dpy))
900 FNextEvent(dpy,&Event);
902 switch(Event.type)
904 case ButtonRelease:
905 if (Pressed)
907 num=WhichButton(&buttons,Event.xbutton.x,Event.xbutton.y);
908 if (num!=-1 && Event.xbutton.button >= 1 &&
909 Event.xbutton.button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
911 SendFvwmPipe(Fvwm_fd,
912 ClickAction[Event.xbutton.button-1],
913 ItemID(&windows,num));
914 SwitchButton(&buttons,num);
917 if (Transient)
919 exit(0);
921 Pressed=0;
922 ButPressed=-1;
923 break;
924 case ButtonPress:
925 num=WhichButton(&buttons,Event.xbutton.x,Event.xbutton.y);
926 if (num != -1)
928 SwitchButton(&buttons,num);
929 ButPressed=num;
930 } else ButPressed=-1;
931 Pressed=1;
932 break;
933 case Expose:
935 int ex = Event.xexpose.x;
936 int ey = Event.xexpose.y;
937 int ex2 = Event.xexpose.x + Event.xexpose.width;
938 int ey2 = Event.xexpose.y + Event.xexpose.height;
939 while (FCheckTypedWindowEvent(dpy, win, Expose, &Event))
941 ex = min(ex, Event.xexpose.x);
942 ey = min(ey, Event.xexpose.y);
943 ex2 = max(ex2, Event.xexpose.x + Event.xexpose.width);
944 ey2 = max(ey2 , Event.xexpose.y + Event.xexpose.height);
946 Event.xexpose.x = ex;
947 Event.xexpose.y = ey;
948 Event.xexpose.width = ex2 - ex;
949 Event.xexpose.height = ey2 - ey;
950 RedrawWindow(True, True, &Event);
951 break;
953 case ConfigureNotify:
955 XEvent event;
957 /* Opaque moves cause lots of these to be sent which causes flickering
958 * It's better to miss out on intermediate steps than to do them all
959 * and take too long. Look down the event queue and do the last one */
960 while (FCheckTypedWindowEvent(dpy, win, ConfigureNotify, &event))
962 /* if send_event is true it means the user has moved the window or
963 * winlist has mapped itself, take note of the new position.
964 * If it is false it comes from the Xserver and is bogus */
965 if (!event.xconfigure.send_event)
966 continue;
967 Event.xconfigure.x = event.xconfigure.x;
968 Event.xconfigure.y = event.xconfigure.y;
969 Event.xconfigure.send_event = True;
971 if (Event.xconfigure.send_event &&
972 (win_x != Event.xconfigure.x ||
973 win_y != Event.xconfigure.y || win_bg == ParentRelative))
975 win_x = Event.xconfigure.x;
976 win_y = Event.xconfigure.y;
977 DrawTransparentButtonArray(&buttons);
980 break;
981 case KeyPress:
982 num=XLookupString(&Event.xkey,buffer,10,NULL,0);
983 if (num==1)
985 if (buffer[0]=='q' || buffer[0]=='Q') exit(0);
986 else if (buffer[0]=='i' || buffer[0]=='I') PrintList(&windows);
987 else if (buffer[0]=='b' || buffer[0]=='B') PrintButtons(&buttons);
989 break;
990 case ClientMessage:
991 if ((Event.xclient.format==32) && (Event.xclient.data.l[0]==wm_del_win))
992 exit(0);
993 case EnterNotify:
994 if (!SomeButtonDown(Event.xcrossing.state)) break;
995 num=WhichButton(&buttons,Event.xcrossing.x,Event.xcrossing.y);
996 if (num!=-1)
998 SwitchButton(&buttons,num);
999 ButPressed=num;
1000 } else ButPressed=-1;
1001 Pressed=1;
1002 break;
1003 case LeaveNotify:
1004 if (!SomeButtonDown(Event.xcrossing.state)) break;
1005 if (ButPressed!=-1) SwitchButton(&buttons,ButPressed);
1006 Pressed=0;
1007 break;
1008 case MotionNotify:
1009 if (!Pressed) break;
1010 num=WhichButton(&buttons,Event.xmotion.x,Event.xmotion.y);
1011 if (num==ButPressed) break;
1012 if (ButPressed!=-1) SwitchButton(&buttons,ButPressed);
1013 if (num!=-1)
1015 SwitchButton(&buttons,num);
1016 ButPressed=num;
1018 else ButPressed=-1;
1020 break;
1027 AdjustWindow - Resize the window according to maxwidth by number of buttons
1029 void AdjustWindow(Bool force)
1031 int new_width=0,new_height=0,tw,i,total,all;
1032 char *temp;
1033 int base_miw = 0;
1035 total = ItemCountVisible(&windows);
1036 all = ItemCount(&windows);
1037 if (!total)
1039 if (WindowState==1)
1041 XUnmapWindow(dpy,win);
1042 WindowState=2;
1044 return;
1047 if (FMiniIconsSupported)
1049 for(i=0; i<all; i++)
1051 if (IsButtonIndexVisible(&buttons,i) &&
1052 ButtonPicture(&buttons,i)->picture != None)
1054 if (ButtonPicture(&buttons,i)->width > base_miw)
1055 base_miw = ButtonPicture(&buttons,i)->width;
1056 break;
1059 base_miw += 2;
1061 for(i=0;i<all;i++)
1063 temp=ItemName(&windows,i);
1064 if(temp != NULL && IsItemIndexVisible(&windows,i))
1066 tw = 8 + FlocaleTextWidth(FButtonFont,temp,strlen(temp));
1067 tw += FlocaleTextWidth(FButtonFont,"()",2);
1068 if (FMiniIconsSupported)
1070 tw += base_miw;
1072 new_width=max(new_width,tw);
1075 new_width=max(new_width, MinWidth);
1076 new_width=min(new_width, MaxWidth);
1077 new_height=(total * buttonheight);
1079 if (WindowState && force) {
1080 for (i = 0; i != MAX_COLOUR_SETS; i++) {
1081 int cset = colorset[i];
1083 if (cset >= 0) {
1084 fore[i] = Colorset[cset].fg;
1085 back[i] = Colorset[cset].bg;
1086 XSetForeground(dpy, graph[i], fore[i]);
1087 XSetForeground(dpy, background[i], back[i]);
1088 XSetForeground(dpy, hilite[i], Colorset[cset].hilite);
1089 XSetForeground(dpy, shadow[i], Colorset[cset].shadow);
1093 /* change the pixmap if forced or if width changed (the height is fixed) */
1094 if (WindowState && (force || new_width != win_width)) {
1095 for (i = 0; i != MAX_COLOUR_SETS; i++) {
1096 int cset = colorset[i];
1098 if (cset >= 0) {
1099 if (pixmap[i])
1100 XFreePixmap(dpy, pixmap[i]);
1101 if (Colorset[cset].pixmap && !CSET_IS_TRANSPARENT_PR(cset)) {
1102 if (CSET_IS_TRANSPARENT_ROOT(cset))
1104 pixmap[i] = CreateBackgroundPixmap(
1105 dpy, win, new_width, win_height,
1106 &Colorset[cset], Pdepth,
1107 background[i], False);
1109 else
1111 pixmap[i] = CreateBackgroundPixmap(
1112 dpy, win, win_width, buttonheight,
1113 &Colorset[cset], Pdepth,
1114 background[i], False);
1116 XSetTile(dpy, background[i], pixmap[i]);
1117 XSetFillStyle(dpy, background[i], FillTiled);
1118 } else {
1119 pixmap[i] = None;
1120 XSetFillStyle(dpy, background[i], FillSolid);
1125 if (WindowState &&
1126 (new_height!=win_height || new_width!=win_width ||
1127 (!flags.is_shaded && flags.needs_resize_after_unshade)))
1129 #ifdef COMPLEX_WINDOW_PLACEMENT
1130 if (Anchor)
1132 /* compensate for fvwm borders when going from unmapped to mapped */
1133 int map_x_adjust = (WindowState - 1) * win_border_x;
1134 int map_y_adjust = (WindowState - 1) * win_border_y;
1136 switch (win_grav) {
1137 case NorthWestGravity:
1138 case SouthWestGravity:
1139 win_x -= map_x_adjust;
1140 break;
1141 case NorthEastGravity:
1142 case SouthEastGravity:
1143 win_x += win_width - new_width + map_x_adjust;
1144 break;
1147 switch (win_grav) {
1148 case NorthWestGravity:
1149 case NorthEastGravity:
1150 win_y -= map_y_adjust;
1151 break;
1152 case SouthEastGravity:
1153 case SouthWestGravity:
1154 win_y += win_height - new_height + map_y_adjust;
1155 break;
1157 /* XMoveResizeWindow(dpy, win, win_x, win_y, new_width, new_height); */
1159 if (flags.is_shaded)
1160 flags.needs_resize_after_unshade = 1;
1161 else if (Anchor && WindowState == 2)
1162 XMoveResizeWindow(dpy, win, win_x, win_y, new_width, new_height);
1163 else
1164 XResizeWindow(dpy, win, new_width, new_height);
1165 /* The new code is sooo much simpler :-) */
1166 #else
1167 if (flags.is_shaded)
1168 flags.needs_resize_after_unshade = 1;
1169 else
1170 /* This relies on fvwm honouring South/East gemoetry when resizing. */
1171 XResizeWindow(dpy, win, new_width, new_height);
1172 #endif
1174 UpdateArray(&buttons,new_width);
1175 if (new_height>0) win_height = new_height;
1176 if (new_width>0) win_width = new_width;
1177 if (WindowState==2)
1179 XMapWindow(dpy,win);
1180 WindowState=1;
1185 makename - Based on the flags return me '(name)' or 'name'
1187 char *makename(const char *string, Bool iconified)
1189 char *ptr;
1191 if (!iconified)
1192 return safestrdup(string);
1193 ptr=safemalloc(strlen(string)+3);
1194 sprintf(ptr, "(%s)", string);
1195 return ptr;
1199 LinkAction - Link an response to a users action
1201 void LinkAction(char *string)
1203 char *temp;
1204 temp=string;
1205 while(isspace((unsigned char)*temp))
1206 temp++;
1207 if(strncasecmp(temp, "Click", 5)==0)
1209 int n;
1210 int b;
1211 int i;
1213 i = sscanf(temp + 5, "%d%n", &b, &n);
1214 if (i > 0 && b >=1 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
1216 CopyString(&ClickAction[b - 1], temp + 5 + n);
1219 else if(strncasecmp(temp, "Enter", 5)==0)
1220 CopyString(&EnterAction,&temp[5]);
1224 MakeMeWindow - Create and setup the window we will need
1226 void MakeMeWindow(void)
1228 XSizeHints hints;
1229 XClassHint classhints;
1230 XGCValues gcval;
1231 unsigned long gcmask;
1232 unsigned int dummy1, dummy2;
1233 int x, y, ret, count;
1234 int wx;
1235 int wy;
1236 Window dummyroot, dummychild;
1237 int i;
1238 XSetWindowAttributes attr;
1240 if ((count = ItemCountVisible(&windows))==0 && Transient)
1242 exit(0);
1244 AdjustWindow(False);
1246 hints.width=win_width;
1247 hints.height=win_height;
1248 hints.win_gravity=NorthWestGravity;
1249 hints.flags=PSize|PWinGravity;
1251 if (Transient)
1253 fscreen_scr_arg fscr;
1255 if (FQueryPointer(
1256 dpy, Root, &dummyroot, &dummychild, &wx, &wy, &x, &y,
1257 &dummy1) == False)
1259 /* pointer is on a different screen */
1260 wx = 0;
1261 wy = 0;
1263 fscr.xypos.x = wx;
1264 fscr.xypos.y = wy;
1265 FScreenGetScrRect(
1266 &fscr, FSCREEN_XYPOS,
1267 &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height);
1268 wx -= hints.width / 2;
1269 wy -= buttonheight / 2;
1270 if (wx + hints.width > screen_g.x + screen_g.width)
1272 wx = screen_g.x + screen_g.width - hints.width;
1274 if (wx < screen_g.x)
1276 wx = screen_g.x;
1278 if (wy + hints.height > screen_g.y + screen_g.height)
1280 wy = screen_g.y + screen_g.height - hints.height;
1282 if (wy < screen_g.y)
1284 wy = screen_g.y;
1286 hints.win_gravity = NorthWestGravity;
1287 hints.flags |= USPosition;
1289 else if (geometry!= NULL)
1291 /* now evaluate the geometry parsed above */
1292 ret = FScreenParseGeometry(geometry, &x, &y, &dummy1, &dummy2);
1293 hints.win_gravity=NorthWestGravity;
1294 if ((ret & XValue) && (ret & YValue))
1296 wx = x;
1297 wy = y;
1298 if (ret & XNegative)
1300 wx += XDisplayWidth(dpy,screen) - win_width;
1301 hints.win_gravity=NorthEastGravity;
1303 if (ret & YNegative)
1305 wy += XDisplayHeight(dpy,screen) - win_height;
1306 if (ret & XNegative)
1308 hints.win_gravity=SouthEastGravity;
1310 else
1312 hints.win_gravity=SouthWestGravity;
1315 hints.flags |= USPosition;
1318 #ifndef COMPLEX_WINDOW_PLACEMENT
1319 if (!Anchor)
1321 if (hints.win_gravity == SouthWestGravity)
1322 hints.win_gravity=NorthWestGravity;
1323 else if (hints.win_gravity == SouthEastGravity)
1324 hints.win_gravity=NorthEastGravity;
1326 #endif
1329 win_x = wx;
1330 win_y = wy;
1331 win_grav = hints.win_gravity;
1334 for (i = 0; i != MAX_COLOUR_SETS; i++)
1335 if(Pdepth < 2)
1337 back[i] = GetColor("white");
1338 fore[i] = GetColor("black");
1340 else
1342 if (colorset[i] >= 0) {
1343 back[i] = Colorset[colorset[i]].bg;
1344 fore[i] = Colorset[colorset[i]].fg;
1345 } else {
1346 back[i] = GetColor(BackColor[i] == NULL ? BackColor[0] : BackColor[i]);
1347 fore[i] = GetColor(ForeColor[i] == NULL ? ForeColor[0] : ForeColor[i]);
1351 /* FvwmWinList paints the entire window and does not rely on the xserver to
1352 * render the background. Setting the background_pixmap to None prevents the
1353 * server from doing anything on expose events. The exception is when one of
1354 * the colorsets is transparent which requires help from the server */
1355 win_bg = None;
1356 for (i = 0; i != MAX_COLOUR_SETS; i++)
1358 if (CSET_IS_TRANSPARENT_PR(colorset[i]))
1360 win_bg = ParentRelative;
1361 break;
1364 attr.background_pixmap = win_bg;
1365 attr.border_pixel = 0;
1366 attr.colormap = Pcmap;
1367 win=XCreateWindow(dpy, Root, wx, wy, hints.width, hints.height, 0,
1368 Pdepth, InputOutput, Pvisual,
1369 CWBackPixmap | CWBorderPixel | CWColormap, &attr);
1370 if (Transient)
1372 XSetTransientForHint(dpy, win, Root);
1375 wm_del_win=XInternAtom(dpy,"WM_DELETE_WINDOW",False);
1376 XSetWMProtocols(dpy,win,&wm_del_win,1);
1378 FwinString->win = win;
1381 XTextProperty nametext;
1382 char *list[]={NULL,NULL};
1383 list[0] = Module+1;
1385 classhints.res_name=safestrdup(Module+1);
1386 classhints.res_class=safestrdup("FvwmWinList");
1388 if(!XStringListToTextProperty(list,1,&nametext))
1390 fprintf(stderr,"%s: Failed to convert name to XText\n",Module);
1391 exit(1);
1393 XSetWMProperties(dpy,win,&nametext,&nametext,
1394 NULL,0,&hints,NULL,&classhints);
1395 XFree(nametext.value);
1398 if (!Transient)
1400 XGrabButton(dpy,1,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync,
1401 GrabModeAsync,None,None);
1402 XGrabButton(dpy,2,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync,
1403 GrabModeAsync,None,None);
1404 XGrabButton(dpy,3,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync,
1405 GrabModeAsync,None,None);
1406 SetMwmHints(
1407 MWM_DECOR_ALL|MWM_DECOR_RESIZEH|MWM_DECOR_MAXIMIZE|MWM_DECOR_MINIMIZE,
1408 MWM_FUNC_ALL|MWM_FUNC_RESIZE|MWM_FUNC_MAXIMIZE|MWM_FUNC_MINIMIZE,
1409 MWM_INPUT_MODELESS);
1411 else
1413 SetMwmHints(0,MWM_FUNC_ALL,MWM_INPUT_MODELESS);
1416 for (i = 0; i != MAX_COLOUR_SETS; i++)
1418 gcval.foreground=fore[i];
1419 gcval.background=back[i];
1420 gcmask=GCForeground|GCBackground;
1421 if (FButtonFont->font != NULL)
1423 gcval.font=FButtonFont->font->fid;
1424 gcmask |= GCFont;
1426 graph[i]=fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
1428 if(Pdepth < 2)
1429 gcval.foreground=GetShadow(fore[i]);
1430 else
1431 if (colorset[i] < 0)
1432 gcval.foreground=GetShadow(back[i]);
1433 else
1434 gcval.foreground=Colorset[colorset[i]].shadow;
1435 gcval.background=back[i];
1436 gcmask=GCForeground|GCBackground;
1437 shadow[i]=fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
1439 if (colorset[i] < 0)
1440 gcval.foreground=GetHilite(back[i]);
1441 else
1442 gcval.foreground=Colorset[colorset[i]].hilite;
1443 gcval.background=back[i];
1444 gcmask=GCForeground|GCBackground;
1445 hilite[i]=fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
1447 gcval.foreground=back[i];
1448 gcmask=GCForeground;
1449 background[i]=fvwmlib_XCreateGC(dpy,win,gcmask,&gcval);
1451 if ((colorset[i] >= 0) && Colorset[colorset[i]].pixmap &&
1452 !CSET_IS_TRANSPARENT_PR(colorset[i]))
1454 if (CSET_IS_TRANSPARENT_ROOT(colorset[i]))
1456 pixmap[i] = CreateBackgroundPixmap(
1457 dpy, win, win_width, win_height,
1458 &Colorset[colorset[i]], Pdepth,
1459 background[i], False);
1461 else
1463 pixmap[i] = CreateBackgroundPixmap(
1464 dpy, win, win_width, buttonheight,
1465 &Colorset[colorset[i]], Pdepth,
1466 background[i], False);
1468 XSetTile(dpy, background[i], pixmap[i]);
1469 XSetFillStyle(dpy, background[i], FillTiled);
1472 AdjustWindow(True);
1473 XSelectInput(dpy,win,(StructureNotifyMask | ExposureMask | KeyPressMask));
1475 if (ItemCountVisible(&windows) > 0)
1477 XMapRaised(dpy,win);
1478 WindowState=1;
1479 } else WindowState=2;
1481 if (Transient)
1483 int i = 0;
1485 XSync(dpy,0);
1486 while (i < 1000 &&
1487 XGrabPointer(dpy, win, True,
1488 ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|
1489 PointerMotionMask|EnterWindowMask|LeaveWindowMask,
1490 GrabModeAsync, GrabModeAsync, None,
1491 None, CurrentTime) != GrabSuccess)
1493 i++;
1494 /* If you go too fast, other windows may not get a change to release
1495 * any grab that they have. */
1496 usleep(1000);
1498 XSync(dpy,0);
1499 if (i >= 1000)
1501 fprintf(stderr,"failed to grab pointer\n");
1502 exit(1);
1504 Pressed = !!SomeButtonDown(dummy1);
1509 StartMeUp - Do X initialization things
1511 void StartMeUp_I(void)
1513 if (!(dpy = XOpenDisplay("")))
1515 fprintf(stderr,"%s: can't open display %s", Module,
1516 XDisplayName(""));
1517 exit (1);
1519 flib_init_graphics(dpy);
1521 x_fd = XConnectionNumber(dpy);
1522 screen= DefaultScreen(dpy);
1523 Root = RootWindow(dpy, screen);
1524 win = None;
1526 return;
1529 void StartMeUp_II(void)
1531 XSizeHints g_hints;
1532 int g_hints_rc;
1534 if (geometry == NULL)
1535 UpdateString(&geometry, "");
1536 /* evaluate further down */
1537 g_hints_rc = FScreenParseGeometryWithScreen(
1538 geometry, &g_hints.x, &g_hints.y, (unsigned int *)&g_hints.width,
1539 (unsigned int *)&g_hints.height, &fscreen);
1540 FScreenGetScrRect(
1541 NULL, fscreen, &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height);
1543 if ((FButtonFont = FlocaleLoadFont(dpy,font_string,Module)) == NULL)
1545 fprintf(stderr,"%s: Cannot load font, Exitting\n", Module);
1546 exit(1);
1549 fontheight = FButtonFont->height;
1550 buttonheight = fontheight + 3 + 2 * ReliefWidth;
1552 win_width=FlocaleTextWidth(FButtonFont,"XXXXXXXXXXXXXXX",10);
1557 ShutMeDown - Do X client cleanup
1559 void ShutMeDown(void)
1561 FreeList(&windows);
1562 FreeAllButtons(&buttons);
1563 /* XFreeGC(dpy,graph);*/
1564 if (WindowState) XDestroyWindow(dpy,win);
1565 XCloseDisplay(dpy);
1569 ChangeWindowName - Self explanitory
1570 Original work from FvwmIdent:
1571 Copyright 1994, Robert Nation and Nobutaka Suzuki.
1573 void ChangeWindowName(char *str)
1575 XTextProperty name;
1576 if (XStringListToTextProperty(&str,1,&name) == 0) {
1577 fprintf(stderr,"%s: cannot allocate window name.\n",Module);
1578 return;
1580 XSetWMName(dpy,win,&name);
1581 XSetWMIconName(dpy,win,&name);
1582 XFree(name.value);
1587 * Sets mwm hints
1591 * Now, if we (hopefully) have MWW - compatible window manager ,
1592 * say, mwm, ncdwm, or else, we will set useful decoration style.
1593 * Never check for MWM_RUNNING property.May be considered bad.
1596 void SetMwmHints(unsigned int value, unsigned int funcs, unsigned int input)
1598 PropMwmHints prop;
1600 if (MwmAtom==None)
1602 MwmAtom=XInternAtom(dpy,"_MOTIF_WM_HINTS",False);
1604 if (MwmAtom!=None)
1606 /* sh->mwm.decorations contains OR of the MWM_DECOR_XXXXX */
1607 prop.props[0] =
1608 MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS |
1609 MWM_HINTS_INPUT_MODE;
1610 prop.props[1] = funcs;
1611 prop.props[2]= value;
1612 prop.props[3] = input;
1614 /* HOP - LA! */
1615 XChangeProperty(
1616 dpy, win, MwmAtom, MwmAtom, 32, PropModeReplace,
1617 (unsigned char *)&(prop.props[0]),
1618 PROP_MWM_HINTS_ELEMENTS);
1623 X Error Handler
1625 int ErrorHandler(Display *d, XErrorEvent *event)
1627 /* some errors are OK=ish */
1628 if (event->error_code == BadPixmap)
1629 return 0;
1630 if (event->error_code == BadDrawable)
1631 return 0;
1632 if (FRenderGetErrorCodeBase() + FRenderBadPicture == event->error_code)
1633 return 0;
1635 PrintXErrorAndCoredump(d, event, Module);
1636 return 0;