1 /* -*-c-*- */
2 
3 /* This module, and the entire NoClutter program, and the concept for
4  * interfacing this module to the Window Manager, are all original work
5  * by Robert Nation and Nobutaka Suzuki <nobuta-s@is.aist-nara.ac.jp>
6  *
7  * Copyright 1994, Robert Nation and Nobutaka Suzuki.
8  * No guarantees or warantees or anything
9  * are provided or implied in any way whatsoever. Use this program at your
10  * own risk. Permission to use this program for any purpose is given,
11  * as long as the copyright is kept intact. */
12 
13 /* This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, see: <http://www.gnu.org/licenses/>
25  */
26 
27 #include "config.h"
28 
29 #include <stdio.h>
30 #include <signal.h>
31 #include <fcntl.h>
32 #include <sys/wait.h>
33 #include "libs/ftime.h"
34 
35 #if HAVE_SYS_SELECT_H
36 #include <sys/select.h>
37 #endif
38 
39 #include <unistd.h>
40 #include <ctype.h>
41 
42 #include "libs/fvwm_x11.h"
43 #include "libs/fvwmlib.h"
44 #include "libs/FShape.h"
45 #include "libs/FEvent.h"
46 #include "libs/Module.h"
47 #include "libs/Colorset.h"
48 #include "libs/fvwmsignal.h"
49 #include "libs/Flocale.h"
50 #include "libs/Parse.h"
51 #include "libs/FRenderInit.h"
52 #include "libs/Graphics.h"
53 #include "libs/System.h"
54 #include "libs/Target.h"
55 #include "libs/XError.h"
56 
57 #include "FvwmIdent.h"
58 
59 static RETSIGTYPE TerminateHandler(int);
60 
61 static ModuleArgs *module;
62 static fd_set_size_t fd_width;
63 static int fd[2];
64 
65 static Display *dpy;                    /* which display are we talking to */
66 static Window Root;
67 static GC gc;
68 
69 static FlocaleFont *Ffont;
70 static FlocaleWinString *FwinString;
71 
72 static int screen;
73 static int x_fd;
74 
75 static char *yes = "Yes";
76 static char *no = "No";
77 static char *mname;
78 
79 /* default colorset to use, set to -1 when explicitly setting colors */
80 static int colorset = 0;
81 
82 static char *BackColor = "white";
83 static char *ForeColor = "black";
84 static char *font_string = NULL;
85 
86 static Pixel fore_pix;
87 static Pixel back_pix;
88 static Window main_win;
89 static Bool UsePixmapDrawing = False; /* if True draw everything in a pixmap
90 				       * and set the window background. Use
91 				       * this with Xft */
92 static int main_width;
93 static int main_height;
94 
95 static EventMask mw_events =
96   ExposureMask | ButtonPressMask | KeyPressMask |
97   ButtonReleaseMask | KeyReleaseMask | StructureNotifyMask;
98 
99 static Atom wm_del_win;
100 
101 static struct target_struct target;
102 static int found=0;
103 
104 static int ListSize=0;
105 
106 static struct Item* itemlistRoot = NULL;
107 static int max_col1, max_col2;
108 static char id[15], desktop[21], swidth[12], sheight[12], borderw[21];
109 static char geometry[30], mymin_aspect[24], max_aspect[24], layer[21];
110 static char ewmh_init_state[512];
111 
112 /* FIXME: default layer should be received from fvwm */
113 #define default_layer DEFAULT_DEFAULT_LAYER
114 static int minimal_layer = default_layer;
115 static int my_layer = default_layer;
116 
117 /*
118  *
119  *  Procedure:
120  *      main - start of module
121  *
122  */
main(int argc,char ** argv)123 int main(int argc, char **argv)
124 {
125 	char *display_name = NULL;
126 	char *tline;
127 
128 	FlocaleInit(LC_CTYPE, "", "", "FvwmIdent");
129 
130 	module = ParseModuleArgs(argc,argv,0); /* no alias */
131 	if (module == NULL)
132 	{
133 		fvwm_debug(__func__,
134 			   "FvwmIdent Version %s should only be executed"
135 			   " by fvwm!\n", VERSION);
136 		exit(1);
137 	}
138 
139 	xasprintf(&mname, "*%s", module->name);
140 
141 #ifdef HAVE_SIGACTION
142 	{
143 		struct sigaction  sigact;
144 
145 		sigemptyset(&sigact.sa_mask);
146 		sigaddset(&sigact.sa_mask, SIGPIPE);
147 		sigaddset(&sigact.sa_mask, SIGTERM);
148 		sigaddset(&sigact.sa_mask, SIGQUIT);
149 		sigaddset(&sigact.sa_mask, SIGINT);
150 		sigaddset(&sigact.sa_mask, SIGHUP);
151 # ifdef SA_INTERRUPT
152 		sigact.sa_flags = SA_INTERRUPT;
153 # else
154 		sigact.sa_flags = 0;
155 # endif
156 		sigact.sa_handler = TerminateHandler;
157 
158 		sigaction(SIGPIPE, &sigact, NULL);
159 		sigaction(SIGTERM, &sigact, NULL);
160 		sigaction(SIGQUIT, &sigact, NULL);
161 		sigaction(SIGINT,  &sigact, NULL);
162 		sigaction(SIGHUP,  &sigact, NULL);
163 	}
164 #else
165 	/* We don't have sigaction(), so fall back to less robust methods.  */
166 #ifdef USE_BSD_SIGNALS
167 	fvwmSetSignalMask( sigmask(SIGPIPE) |
168 			   sigmask(SIGTERM) |
169 			   sigmask(SIGQUIT) |
170 			   sigmask(SIGINT) |
171 			   sigmask(SIGHUP) );
172 #endif
173 	signal(SIGPIPE, TerminateHandler);
174 	signal(SIGTERM, TerminateHandler);
175 	signal(SIGQUIT, TerminateHandler);
176 	signal(SIGINT,  TerminateHandler);
177 	signal(SIGHUP,  TerminateHandler);
178 #ifdef HAVE_SIGINTERRUPT
179 	siginterrupt(SIGPIPE, 1);
180 	siginterrupt(SIGTERM, 1);
181 	siginterrupt(SIGQUIT, 1);
182 	siginterrupt(SIGINT, 1);
183 	siginterrupt(SIGHUP, 1);
184 #endif
185 #endif
186 
187 	fd[0] = module->to_fvwm;
188 	fd[1] = module->from_fvwm;
189 
190 	/* Open the Display */
191 	if (!(dpy = XOpenDisplay(display_name)))
192 	{
193 		fvwm_debug(__func__, "%s: can't open display %s",
194 			   module->name,
195 			   XDisplayName(display_name));
196 		exit (1);
197 	}
198 	x_fd = XConnectionNumber(dpy);
199 	screen= DefaultScreen(dpy);
200 	Root = RootWindow(dpy, screen);
201 	XSetErrorHandler(ErrorHandler);
202 
203 	flib_init_graphics(dpy);
204 	FlocaleAllocateWinString(&FwinString);
205 
206 	SetMessageMask(fd, M_CONFIGURE_WINDOW | M_WINDOW_NAME | M_ICON_NAME
207 		       | M_RES_CLASS | M_RES_NAME | M_END_WINDOWLIST |
208 		       M_CONFIG_INFO | M_END_CONFIG_INFO | M_SENDCONFIG);
209 	SetMessageMask(fd, MX_PROPERTY_CHANGE);
210 	/* scan config file for set-up parameters */
211 	/* Colors and fonts */
212 
213 	InitGetConfigLine(fd, mname);
214 	GetConfigLine(fd,&tline);
215 
216 	while (tline != (char *)0)
217 	{
218 		if (strlen(tline) <= 1)
219 		{
220 			continue;
221 		}
222 		if (strncasecmp(tline, mname, module->namelen+1) == 0)
223 		{
224 			tline += (module->namelen +1);
225 			if (strncasecmp(tline, "Font", 4) == 0)
226 			{
227 				CopyStringWithQuotes(&font_string, &tline[4]);
228 			}
229 			else if (strncasecmp(tline, "Fore", 4) == 0)
230 			{
231 				CopyString(&ForeColor, &tline[4]);
232 				colorset = -1;
233 			}
234 			else if (strncasecmp(tline, "Back", 4) == 0)
235 			{
236 				CopyString(&BackColor, &tline[4]);
237 				colorset = -1;
238 			}
239 			else if (strncasecmp(tline, "Colorset", 8) == 0)
240 			{
241 				sscanf(&tline[8], "%d", &colorset);
242 				AllocColorset(colorset);
243 			}
244 			else if (strncasecmp(tline, "MinimalLayer", 12) == 0)
245 			{
246 				char *layer_str = PeekToken(&tline[12], NULL);
247 				if (layer_str == NULL)
248 				{
249 					minimal_layer = default_layer;
250 				}
251 				else if (sscanf(
252 					layer_str, "%d", &minimal_layer) != 1)
253 				{
254 					if (strncasecmp(
255 						layer_str, "none", 4) == 0)
256 					{
257 						minimal_layer = -1;
258 					}
259 					else
260 					{
261 						minimal_layer = default_layer;
262 					}
263 				}
264 			}
265 		}
266 		else if (strncasecmp(tline, "Colorset", 8) == 0)
267 		{
268 			LoadColorset(&tline[8]);
269 		}
270 		GetConfigLine(fd, &tline);
271 	}
272 
273 	if(module->window == 0)
274 	{
275 		fvwmlib_get_target_window(
276 			dpy, screen, module->name, &(module->window), True);
277 	}
278 
279 	fd_width = GetFdWidth();
280 
281 	/* Create a list of all windows */
282 	/* Request a list of all windows,
283 	 * wait for ConfigureWindow packets */
284 	SendText(fd, "Send_WindowList", 0);
285 
286 	/* tell fvwm we're running */
287 	SendFinishedStartupNotification(fd);
288 	if (module->window == Root)
289 	{
290 		exit(0);
291 	}
292 
293 	Loop(fd);
294 	return 0;
295 }
296 
297 /*
298  *
299  * Read the entire window list from fvwm
300  *
301  */
Loop(int * fd)302 void Loop(int *fd)
303 {
304 	while (1)
305 	{
306 		FvwmPacket* packet = ReadFvwmPacket(fd[1]);
307 		if ( packet == NULL )
308 		{
309 			exit(0);
310 		}
311 		else
312 		{
313 			process_message( packet->type, packet->body );
314 		}
315 	}
316 }
317 
318 
319 /*
320  *
321  * Process window list messages
322  *
323  */
process_message(unsigned long type,unsigned long * body)324 void process_message(unsigned long type,unsigned long *body)
325 {
326 	switch(type)
327 	{
328 		/* should turn off this packet but it comes after config_list
329 		 * so have to accept at least one */
330 	case M_CONFIGURE_WINDOW:
331 		list_configure(body);
332 		break;
333 	case M_WINDOW_NAME:
334 		list_window_name(body);
335 		break;
336 	case M_ICON_NAME:
337 		list_icon_name(body);
338 		break;
339 	case M_RES_CLASS:
340 		list_class(body);
341 		break;
342 	case M_RES_NAME:
343 		list_res_name(body);
344 		break;
345 	case M_END_WINDOWLIST:
346 		list_end();
347 		break;
348 	default:
349 		break;
350 	}
351 }
352 
353 /*
354  *
355  *  Procedure:
356  *      SIGPIPE handler - SIGPIPE means fvwm is dying
357  *
358  */
359 static RETSIGTYPE
TerminateHandler(int sig)360 TerminateHandler(int sig)
361 {
362 	fvwmSetTerminate(sig);
363 	SIGNAL_RETURN;
364 }
365 
366 /*
367  *
368  * Got window configuration info - if its our window, save data
369  *
370  */
list_configure(unsigned long * body)371 void list_configure(unsigned long *body)
372 {
373 	struct ConfigWinPacket  *cfgpacket = (void *) body;
374 
375 	if (
376 		(module->window == cfgpacket->frame)||
377 		(module->window == cfgpacket->w) ||
378 		((cfgpacket->icon_w != 0)&&
379 		 (module->window == cfgpacket->icon_w)) ||
380 		((cfgpacket->icon_pixmap_w)&&
381 		 (module->window == cfgpacket->icon_pixmap_w)))
382 	{
383 		module->window = cfgpacket->frame;
384 		target.id = cfgpacket->w;
385 
386 		target.monitor_id = cfgpacket->monitor_id;
387 		target.monitor = fxstrdup("unknown");
388 		{
389 			free(target.monitor);
390 			target.monitor = fxstrdup(
391 				monitor_by_output((int)target.monitor_id)->si->name);
392 		}
393 		target.frame = cfgpacket->frame;
394 		target.frame_x = cfgpacket->frame_x;
395 		target.frame_y = cfgpacket->frame_y;
396 		target.frame_w = cfgpacket->frame_width;
397 		target.frame_h = cfgpacket->frame_height;
398 		target.desktop = cfgpacket->desk;
399 		target.layer = cfgpacket->layer;
400 		memcpy(&target.flags,
401 		       &(cfgpacket->flags), sizeof(cfgpacket->flags));
402 		target.title_h = cfgpacket->title_height;
403 		target.title_dir = GET_TITLE_DIR(cfgpacket);
404 		target.border_w = cfgpacket->border_width;
405 		target.base_w = cfgpacket->hints_base_width;
406 		target.base_h = cfgpacket->hints_base_height;
407 		target.width_inc = cfgpacket->orig_hints_width_inc;
408 		target.height_inc = cfgpacket->orig_hints_height_inc;
409 		target.gravity = cfgpacket->hints_win_gravity;
410 		target.ewmh_hint_layer = cfgpacket->ewmh_hint_layer;
411 		target.ewmh_hint_desktop = cfgpacket->ewmh_hint_desktop;
412 		target.ewmh_window_type = cfgpacket->ewmh_window_type;
413 		found = 1;
414 
415 		my_layer = (int)target.layer;
416 		if (my_layer < minimal_layer)
417 		{
418 			my_layer = minimal_layer;
419 		}
420 	}
421 }
422 
423 /*
424  *
425  * Capture  Window name info
426  *
427  */
list_window_name(unsigned long * body)428 void list_window_name(unsigned long *body)
429 {
430 	if (
431 		(module->window == (Window)body[1])||
432 		(module->window == (Window)body[0]))
433 	{
434 		strncpy(target.name,(char *)&body[3],255);
435 	}
436 }
437 
438 /*
439  *
440  * Capture  Window Icon name info
441  *
442  */
list_icon_name(unsigned long * body)443 void list_icon_name(unsigned long *body)
444 {
445 	if (
446 		(module->window == (Window)body[1])||
447 		(module->window == (Window)body[0]))
448 	{
449 		strncpy(target.icon_name,(char *)&body[3],255);
450 	}
451 }
452 
453 
454 /*
455  *
456  * Capture  Window class name info
457  *
458  */
list_class(unsigned long * body)459 void list_class(unsigned long *body)
460 {
461 	if (
462 		(module->window == (Window)body[1])||
463 		(module->window == (Window)body[0]))
464 	{
465 		strncpy(target.class,(char *)&body[3],255);
466 	}
467 }
468 
469 
470 /*
471  *
472  * Capture  Window resource info
473  *
474  */
list_res_name(unsigned long * body)475 void list_res_name(unsigned long *body)
476 {
477 	if ((module->window == (Window)body[1])||
478 	    (module->window == (Window)body[0]))
479 	{
480 		strncpy(target.res,(char *)&body[3],255);
481 	}
482 }
483 
list_property_change(unsigned long * body)484 void list_property_change(unsigned long *body)
485 {
486 	if (body[0] == MX_PROPERTY_CHANGE_BACKGROUND && body[2] == 0 &&
487 	    CSET_IS_TRANSPARENT_PR(colorset))
488 	{
489 		if (UsePixmapDrawing)
490 		{
491 			PixmapDrawWindow(
492 				main_width, main_height);
493 		}
494 		else
495 		{
496 			UpdateBackgroundTransparency(
497 				dpy, main_win, main_width,
498 				main_height,
499 				&Colorset[(colorset)], Pdepth,
500 				gc, True);
501 		}
502 	}
503 }
504 
list_config_info(unsigned long * body)505 void list_config_info(unsigned long *body)
506 {
507 	char *tline, *token;
508 
509 	tline = (char*)&body[3];
510 	tline = GetNextToken(tline, &token);
511 	if (StrEquals(token, "Colorset") && colorset >= 0 &&
512 	    LoadColorset(tline) == colorset)
513 	{
514 		if (FftSupport && Ffont->fftf.fftfont != NULL)
515 		{
516 			UsePixmapDrawing = True;
517 		}
518 		/* track all colorset changes & update display if necessary */
519 		/* ask for movement events iff transparent */
520 		if (CSET_IS_TRANSPARENT(colorset))
521 		{
522 
523 			mw_events |= StructureNotifyMask;
524 			if (CSET_IS_TRANSPARENT_PR_PURE(colorset))
525 			{
526 				UsePixmapDrawing = False;
527 			}
528 		}
529 		else
530 		{
531 			mw_events &= ~(StructureNotifyMask);
532 		}
533 		if (UsePixmapDrawing)
534 		{
535 #if 0
536 			mw_events &= ~(ExposureMask);
537 #endif
538 		}
539 		else
540 		{
541 			mw_events |= ExposureMask;
542 		}
543 		XSelectInput(dpy, main_win, mw_events);
544 		XSetForeground(dpy, gc, Colorset[colorset].fg);
545 		if (UsePixmapDrawing)
546 		{
547 			PixmapDrawWindow(main_width, main_height);
548 		}
549 		else
550 		{
551 			SetWindowBackground(
552 				dpy, main_win, main_width, main_height,
553 				&Colorset[colorset], Pdepth, gc, True);
554 		}
555 	}
556 	free(token);
557 }
558 
559 /*
560  *
561  * Process X Events
562  *
563  */
ProcessXEvent(int x,int y)564 int ProcessXEvent(int x, int y)
565 {
566 	XEvent Event,event;
567 	static int is_key_pressed = 0;
568 	static int is_button_pressed = 0;
569 	char buf[32];
570 	static int ex=10000, ey=10000, ex2=0, ey2=0;
571 
572 	while (FPending(dpy))
573 	{
574 		FNextEvent(dpy,&Event);
575 		switch(Event.type)
576 		{
577 		case Expose:
578 			ex = min(ex, Event.xexpose.x);
579 			ey = min(ey, Event.xexpose.y);
580 			ex2 = max(ex2, Event.xexpose.x + Event.xexpose.width);
581 			ey2=max(ey2 , Event.xexpose.y + Event.xexpose.height);
582 			while (FCheckTypedEvent(dpy, Expose, &Event))
583 			{
584 				ex = min(ex, Event.xexpose.x);
585 				ey = min(ey, Event.xexpose.y);
586 				ex2 = max(
587 					ex2,
588 					Event.xexpose.x + Event.xexpose.width);
589 				ey2=max(ey2,
590 					Event.xexpose.y + Event.xexpose.height);
591 			}
592 			if (FftSupport && Ffont->fftf.fftfont != NULL)
593 			{
594 				XClearArea(
595 					dpy, main_win,
596 					ex, ey, ex2-ex, ey2-ey, False);
597 			}
598 			DrawItems(main_win, ex, ey, ex2-ex, ey2-ey);
599 			ex = ey = 10000;
600 			ex2 = ey2 = 0;
601 			break;
602 		case KeyPress:
603 			is_key_pressed = 1;
604 			break;
605 		case ButtonPress:
606 			is_button_pressed = Event.xbutton.button;
607 			break;
608 		case KeyRelease:
609 			if (is_key_pressed)
610 			{
611 				exit(0);
612 			}
613 			break;
614 		case ButtonRelease:
615 			if (is_button_pressed)
616 			{
617 				if (is_button_pressed == 2 &&
618 				    Event.xbutton.button == 2)
619 				{
620 					/* select a new window when
621 					 * button 2 is pressed */
622 					SetMessageMask(
623 						fd, M_CONFIGURE_WINDOW   |
624 						M_WINDOW_NAME    |
625 						M_ICON_NAME      |
626 						M_RES_CLASS      |
627 						M_RES_NAME       |
628 						M_END_WINDOWLIST |
629 						M_CONFIG_INFO    |
630 						M_END_CONFIG_INFO|
631 						M_SENDCONFIG);
632 					SendText(fd, "Send_WindowList", 0);
633 					XDestroyWindow(dpy, main_win);
634 					DestroyList();
635 					fvwmlib_get_target_window(
636 						dpy, screen, module->name,
637 						 &(module->window), True);
638 					found = 0;
639 					return 1;
640 				}
641 				else
642 				{
643 					exit(0);
644 				}
645 			}
646 			break;
647 		case ClientMessage:
648 			if (Event.xclient.format==32 &&
649 			    Event.xclient.data.l[0]==wm_del_win)
650 			{
651 				exit(0);
652 			}
653 			break;
654 		case ReparentNotify:
655 			if (minimal_layer >= 0)
656 			{
657 				sprintf(buf, "Layer 0 %d", my_layer);
658 				SendText(fd, buf, main_win);
659 			}
660 			SendText(fd, "Raise", main_win);
661 			break;
662 		case ConfigureNotify:
663 			fev_sanitise_configure_notify(&Event.xconfigure);
664                        /* this only happens with transparent windows,
665 			* slurp up as many events as possible before
666 			* redrawing to reduce flickering */
667 			while (FCheckTypedEvent(
668 				dpy, ConfigureNotify, &event))
669 			{
670 				fev_sanitise_configure_notify(
671 					&event.xconfigure);
672 				if (!event.xconfigure.send_event)
673 					continue;
674 				Event.xconfigure.x = event.xconfigure.x;
675 				Event.xconfigure.y = event.xconfigure.y;
676 				Event.xconfigure.send_event = True;
677 			}
678 			/* Only refresh if moved */
679 			if ((Event.xconfigure.send_event ||
680 			     CSET_IS_TRANSPARENT_PR_PURE(colorset)) &&
681 			    (x != Event.xconfigure.x ||
682 			     y != Event.xconfigure.y))
683 			{
684 				static Bool is_initial_cn = True;
685 				Bool do_eat_expose = False;
686 
687 				x = Event.xconfigure.x;
688 				y = Event.xconfigure.y;
689 				/* flush any expose events */
690 				if (UsePixmapDrawing)
691 				{
692 					PixmapDrawWindow(
693 						main_width, main_height);
694 					do_eat_expose = True;
695 				}
696 				else if (colorset == -1)
697 				{
698 					do_eat_expose = True;
699 				}
700 				else if (UpdateBackgroundTransparency(
701 					dpy, main_win, main_width,
702 					main_height,
703 					&Colorset[(colorset)], Pdepth,
704 					gc, True) == True)
705 				{
706 					do_eat_expose = True;
707 				}
708 				if (do_eat_expose == True &&
709 				    is_initial_cn == False)
710 				{
711 					while (FCheckTypedEvent(
712 						dpy, Expose, &Event))
713 					{
714 						/* nothing */
715 					}
716 				}
717 				is_initial_cn = False;
718 			}
719 			break;
720 		}
721 	}
722 	XFlush (dpy);
723 
724 	return 0;
725 }
726 
727 /*
728  *
729  * End of window list, open an x window and display data in it
730  *
731  */
list_end(void)732 void list_end(void)
733 {
734 	XSizeHints mysizehints;
735 	XGCValues gcv;
736 	unsigned long gcm;
737 	int lmax,height;
738 	int x,y;
739 	XSetWindowAttributes attributes;
740 
741 	if(!found)
742 	{
743 		exit(0);
744 	}
745 
746 	/* tell fvwm to only send config messages */
747 	SetMessageMask(fd, M_CONFIG_INFO | M_SENDCONFIG);
748 
749 	if ((Ffont = FlocaleLoadFont(dpy, font_string, module->name)) == NULL)
750 	{
751 		fvwm_debug(__func__, "%s: cannot load font, exiting\n",
752 			   module->name);
753 		exit(1);
754 	}
755 
756 	/* chose the rendering methode */
757 	if (FftSupport && Ffont->fftf.fftfont != NULL)
758 	{
759 		UsePixmapDrawing = True;
760 	}
761 	/* make window infomation list */
762 	MakeList();
763 
764 	/* size and create the window */
765 	lmax = max_col1 + max_col2 + 15;
766 
767 	height = ListSize * (Ffont->height);
768 
769 	mysizehints.flags=
770 		USSize|USPosition|PWinGravity|PResizeInc|PBaseSize|PMinSize|
771 		PMaxSize;
772 	main_width = mysizehints.width = lmax + 10;
773 	main_height = mysizehints.height = height + 10;
774 	mysizehints.width_inc = 1;
775 	mysizehints.height_inc = 1;
776 	mysizehints.base_height = mysizehints.height;
777 	mysizehints.base_width = mysizehints.width;
778 	mysizehints.min_height = mysizehints.height;
779 	mysizehints.min_width = mysizehints.width;
780 	mysizehints.max_height = mysizehints.height;
781 	mysizehints.max_width = mysizehints.width;
782 	mysizehints.win_gravity = NorthWestGravity;
783 	{
784 		int sx;
785 		int sy;
786 		int sw;
787 		int sh;
788 		Window JunkW;
789 		int JunkC;
790 		unsigned int JunkM;
791 		fscreen_scr_arg fscr;
792 
793 		if (!FQueryPointer(
794 			dpy, Root, &JunkW, &JunkW, &x, &y, &JunkC, &JunkC,
795 			&JunkM))
796 		{
797 			/* pointer is on a different screen */
798 			x = 0;
799 			y = 0;
800 		}
801 
802 		fscr.xypos.x = x;
803 		fscr.xypos.y = y;
804 		FScreenGetScrRect(&fscr, FSCREEN_XYPOS, &sx, &sy, &sw, &sh);
805 		if (y + height + 100 > sy + sh)
806 		{
807 			y = sy + sh - height - 10;
808 			mysizehints.win_gravity = SouthWestGravity;
809 		}
810 		if (x + lmax + 100 > sx + sw)
811 		{
812 			x = sx + sw - lmax - 10;
813 			if (mysizehints.win_gravity == SouthWestGravity)
814 				mysizehints.win_gravity = SouthEastGravity;
815 			else
816 				mysizehints.win_gravity = NorthEastGravity;
817 		}
818 	}
819 
820 	if (Pdepth < 2)
821 	{
822 		back_pix = GetColor("white");
823 		fore_pix = GetColor("black");
824 	}
825 	else
826 	{
827 		back_pix = (colorset < 0)?
828 			GetColor(BackColor) : Colorset[colorset].bg;
829 		fore_pix = (colorset < 0)?
830 			GetColor(ForeColor) : Colorset[colorset].fg;
831 	}
832 
833 	attributes.colormap = Pcmap;
834 	attributes.border_pixel = 0;
835 	attributes.background_pixel = back_pix;
836 	main_win = XCreateWindow(
837 		dpy, Root, x, y, mysizehints.width, mysizehints.height, 0,
838 		Pdepth, InputOutput, Pvisual, CWColormap | CWBackPixel |
839 		CWBorderPixel, &attributes);
840 	wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False);
841 	XSetWMProtocols(dpy,main_win,&wm_del_win,1);
842 
843 	/* hack to prevent mapping on wrong screen with StartsOnScreen */
844 	FScreenMangleScreenIntoUSPosHints(FSCREEN_XYPOS, &mysizehints);
845 	XSetWMNormalHints(dpy,main_win,&mysizehints);
846 	/* have to ask for configure events when transparent */
847 	if (CSET_IS_TRANSPARENT(colorset))
848 	{
849 		mw_events |= StructureNotifyMask;
850 		if (CSET_IS_TRANSPARENT_PR_PURE(colorset))
851 		{
852 			UsePixmapDrawing = 0;
853 		}
854 	}
855 	if (!UsePixmapDrawing)
856 	{
857 		mw_events |= ExposureMask;
858 	}
859 
860 	XSelectInput(dpy, main_win, mw_events);
861 	change_window_name(module->name);
862 
863 	gcm = GCForeground;
864 	gcv.foreground = fore_pix;
865 	if (Ffont->font != NULL)
866 	{
867 		gcm |= GCFont;
868 		gcv.font = Ffont->font->fid;
869 	}
870 	gc = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv);
871 	if (UsePixmapDrawing)
872 	{
873 		PixmapDrawWindow(main_width, main_height);
874 	}
875 	else if (colorset >= 0)
876 	{
877 		SetWindowBackground(
878 			dpy, main_win, main_width, main_height,
879 			&Colorset[(colorset)], Pdepth, gc, True);
880 	}
881 	XMapWindow(dpy,main_win);
882 
883 	/* Window is created. Display it until the user clicks or deletes it.
884 	 * also grok any dynamic config changes */
885 	while(1)
886 	{
887 		FvwmPacket* packet;
888 		int x_fd = XConnectionNumber(dpy);
889 		fd_set fdset;
890 
891 		FD_ZERO(&fdset);
892 		FD_SET(fd[1], &fdset);
893 		FD_SET(x_fd, &fdset);
894 
895 		/* process all X events first */
896 		if (ProcessXEvent(x,y) == 1)
897 		{
898 			return;
899 		}
900 
901 		/* wait for X-event or config line */
902 		select(fd_width, SELECT_FD_SET_CAST &fdset, NULL, NULL, NULL );
903 
904 		/* parse any dynamic config lines */
905 		if (FD_ISSET(fd[1], &fdset))
906 		{
907 			packet = ReadFvwmPacket(fd[1]);
908 			if (packet == NULL)
909 				exit(0);
910 			if (packet &&  packet->type == MX_PROPERTY_CHANGE)
911 			{
912 				list_property_change(packet->body);
913 			}
914 			if (packet && packet->type == M_CONFIG_INFO)
915 			{
916 				list_config_info(packet->body);
917 			}
918 		}
919 	}
920 }
921 
922 /*
923  *
924  * Draw the items
925  *
926  */
DrawItems(Drawable d,int x,int y,int w,int h)927 void DrawItems(Drawable d, int x, int y, int w, int h)
928 {
929 	int fontheight,i=0;
930 	struct Item *cur = itemlistRoot;
931 	Region region = 0;
932 
933 	fontheight = Ffont->height;
934 	FwinString->win = d;
935 	FwinString->gc = gc;
936 	FwinString->flags.has_clip_region = False;
937 	if (w > 0)
938 	{
939 		XRectangle r;
940 
941 		r.x = x;
942 		r.y = y;
943 		r.width = w;
944 		r.height = h;
945 
946 		region = XCreateRegion();
947 		XUnionRectWithRegion(&r, region, region);
948 		XSetRegion(dpy, gc, region);
949 		FwinString->flags.has_clip_region = True;
950 		FwinString->clip_region = region;
951 	}
952 
953 	if (colorset >= 0)
954 	{
955 		FwinString->colorset = &Colorset[colorset];
956 		FwinString->flags.has_colorset = True;
957 	}
958 	while(cur != NULL) /* may be optimised */
959 	{
960 		/* first column */
961 		FwinString->str = cur->col1;
962 		FwinString->x = 5;
963 		FwinString->y = 5 + Ffont->ascent + i * fontheight;
964 		FlocaleDrawString(dpy, Ffont, FwinString, 0);
965 
966 		/* second column */
967 		FwinString->str = cur->col2;
968 		FwinString->x = 10 + max_col1;
969 		FlocaleDrawString(dpy, Ffont, FwinString, 0);
970 
971 		++i;
972 		cur = cur->next;
973 	}
974 	if (FwinString->flags.has_clip_region)
975 	{
976 		XDestroyRegion(region);
977 		XSetClipMask(dpy, gc, None);
978 	}
979 	XFlush (dpy);
980 }
981 
PixmapDrawWindow(int w,int h)982 void PixmapDrawWindow(int w, int h)
983 {
984 	Pixmap pix;
985 	XGCValues gcv;
986 	unsigned long gcm;
987 
988 	if (colorset >= 0)
989 	{
990 		Pixmap cs_pix;
991 		cs_pix = CreateBackgroundPixmap(dpy, main_win, w, h,
992 						&Colorset[(colorset)],
993 						Pdepth, gc, False);
994 		if (cs_pix == ParentRelative)
995 		{
996 			pix = cs_pix;
997 		}
998 		else
999 		{
1000 			pix = CreateTiledPixmap(
1001 				dpy, cs_pix, 0,0,w,h,Pdepth, gc);
1002 			XFreePixmap(dpy, cs_pix);
1003 		}
1004 	}
1005 	else
1006 	{
1007 		gcm = GCForeground;
1008 		gcv.foreground = back_pix;
1009 		XChangeGC(dpy, gc, gcm, &gcv);
1010 		pix = XCreatePixmap(dpy, main_win, w, h, Pdepth);
1011 		XFillRectangle(dpy, pix, gc, 0, 0, w, h);
1012 		gcv.foreground = fore_pix;
1013 		XChangeGC(dpy, gc, gcm, &gcv);
1014 	}
1015 
1016 	if (pix != ParentRelative)
1017 	{
1018 		DrawItems(pix, 0, 0, 0, 0);
1019 		XSetWindowBackgroundPixmap(dpy, main_win, pix);
1020 		XClearWindow(dpy, main_win);
1021 		XFreePixmap(dpy, pix);
1022 	}
1023 	else
1024 	{
1025 		XSetWindowBackgroundPixmap(dpy, main_win, pix);
1026 		XClearWindow(dpy, main_win);
1027 		DrawItems(main_win, 0, 0, 0, 0);
1028 	}
1029 }
1030 
1031 /*
1032  *  Change the window name displayed in the title bar.
1033  */
change_window_name(char * str)1034 void change_window_name(char *str)
1035 {
1036 	XTextProperty name;
1037 	XClassHint myclasshints;
1038 
1039 	if (XStringListToTextProperty(&str,1,&name) == 0)
1040 	{
1041 		fvwm_debug(__func__, "%s: cannot allocate window name",
1042 			   module->name);
1043 		return;
1044 	}
1045 	XSetWMName(dpy,main_win,&name);
1046 	XSetWMIconName(dpy,main_win,&name);
1047 	XFree(name.value);
1048 	myclasshints.res_name = str;
1049 	myclasshints.res_class = "FvwmIdent";
1050 	XSetClassHint(dpy,main_win,&myclasshints);
1051 }
1052 
1053 
DestroyList(void)1054 void DestroyList(void)
1055 {
1056 	struct Item *t;
1057 	struct Item *tmp;
1058 
1059 	for (t = itemlistRoot; t; t = tmp)
1060 	{
1061 		tmp = t->next;
1062 		free(t);
1063 	}
1064 	itemlistRoot = NULL;
1065 }
1066 
1067 /*
1068 *
1069 * Add s1(string at first column) and s2(string at second column) to itemlist
1070 *
1071 */
AddToList(char * s1,char * s2)1072 void AddToList(char *s1, char* s2)
1073 {
1074 	int tw1, tw2;
1075 	struct Item* item, *cur = itemlistRoot;
1076 
1077 	tw1 = FlocaleTextWidth(Ffont, s1, strlen(s1));
1078 	tw2 = FlocaleTextWidth(Ffont, s2, strlen(s2));
1079 	max_col1 = max_col1 > tw1 ? max_col1 : tw1;
1080 	max_col2 = max_col2 > tw2 ? max_col2 : tw2;
1081 
1082 	item = fxmalloc(sizeof(struct Item));
1083 	item->col1 = s1;
1084 	item->col2 = s2;
1085 	item->next = NULL;
1086 
1087 	if (cur == NULL)
1088 	{
1089 		itemlistRoot = item;
1090 	}
1091 	else
1092 	{
1093 		while(cur->next != NULL)
1094 		{
1095 			cur = cur->next;
1096 		}
1097 		cur->next = item;
1098 	}
1099 	ListSize++;
1100 }
1101 
MakeList(void)1102 void MakeList(void)
1103 {
1104 	int bw,width,height,x1,y1,x2,y2;
1105 	char loc[24];
1106 	static char xstr[21],ystr[21];
1107 	/* GSFR - quick hack because the new macros depend on a prt reference
1108 	 */
1109 	struct target_struct  *targ  =  &target;
1110 
1111 	ListSize = 0;
1112 
1113 	bw = 2*target.border_w;
1114 	width = target.frame_w - bw;
1115 	height = target.frame_h - bw;
1116 	if (target.title_dir == DIR_W || target.title_dir == DIR_E)
1117 	{
1118 		width -= target.title_h;
1119 	}
1120 	else if (target.title_dir == DIR_N || target.title_dir == DIR_S)
1121 	{
1122 		height -= target.title_h;
1123 	}
1124 
1125 	sprintf(desktop, "%ld",  target.desktop);
1126 	sprintf(layer,   "%ld",  target.layer);
1127 	sprintf(id,      "0x%x", (unsigned int)target.id);
1128 	sprintf(swidth,  "%d",   width);
1129 	sprintf(sheight, "%d",   height);
1130 	sprintf(borderw, "%ld",  target.border_w);
1131 	sprintf(xstr,    "%ld",  target.frame_x);
1132 	sprintf(ystr,    "%ld",  target.frame_y);
1133 
1134 	AddToList("Name:",          target.name);
1135 	AddToList("Icon Name:",     target.icon_name);
1136 	AddToList("Class:",         target.class);
1137 	AddToList("Resource:",      target.res);
1138 	AddToList("Window ID:",     id);
1139 	AddToList("Monitor:",       target.monitor);
1140 	AddToList("Desk:",          desktop);
1141 	AddToList("Layer:",         layer);
1142 	AddToList("Width:",         swidth);
1143 	AddToList("Height:",        sheight);
1144 	AddToList("X (current page):",   xstr);
1145 	AddToList("Y (current page):",   ystr);
1146 	AddToList("Boundary Width:", borderw);
1147 
1148 	AddToList("StickyPage:",    (IS_STICKY_ACROSS_PAGES(targ) ? yes : no));
1149 	AddToList("StickyDesk:",    (IS_STICKY_ACROSS_DESKS(targ) ? yes : no));
1150 	AddToList("StickyPageIcon:",
1151 		(IS_ICON_STICKY_ACROSS_PAGES(targ) ? yes : no));
1152 	AddToList("StickyDeskIcon:",
1153 		(IS_ICON_STICKY_ACROSS_DESKS(targ) ? yes : no));
1154 	AddToList("NoTitle:",       (HAS_TITLE(targ)    ? no : yes));
1155 	AddToList("Iconified:",     (IS_ICONIFIED(targ) ? yes : no));
1156 	AddToList("Transient:",     (IS_TRANSIENT(targ) ? yes : no));
1157 	AddToList("WindowListSkip:", (DO_SKIP_WINDOW_LIST(targ) ? yes : no));
1158 
1159 	switch(target.gravity)
1160 	{
1161 	case ForgetGravity:
1162 		AddToList("Gravity:", "Forget");
1163 		break;
1164 	case NorthWestGravity:
1165 		AddToList("Gravity:", "NorthWest");
1166 		break;
1167 	case NorthGravity:
1168 		AddToList("Gravity:", "North");
1169 		break;
1170 	case NorthEastGravity:
1171 		AddToList("Gravity:", "NorthEast");
1172 		break;
1173 	case WestGravity:
1174 		AddToList("Gravity:", "West");
1175 		break;
1176 	case CenterGravity:
1177 		AddToList("Gravity:", "Center");
1178 		break;
1179 	case EastGravity:
1180 		AddToList("Gravity:", "East");
1181 		break;
1182 	case SouthWestGravity:
1183 		AddToList("Gravity:", "SouthWest");
1184 		break;
1185 	case SouthGravity:
1186 		AddToList("Gravity:", "South");
1187 		break;
1188 	case SouthEastGravity:
1189 		AddToList("Gravity:", "SouthEast");
1190 		break;
1191 	case StaticGravity:
1192 		AddToList("Gravity:", "Static");
1193 		break;
1194 	default:
1195 		AddToList("Gravity:", "Unknown");
1196 		break;
1197 	}
1198 	x1 = target.frame_x;
1199 	if(x1 < 0)
1200 	{
1201 		x1 = 0;
1202 	}
1203 	x2 = DisplayWidth(dpy,screen) - x1 - target.frame_w;
1204 	if(x2 < 0)
1205 	{
1206 		x2 = 0;
1207 	}
1208 	y1 = target.frame_y;
1209 	if(y1 < 0)
1210 	{
1211 		y1 = 0;
1212 	}
1213 	y2 = DisplayHeight(dpy,screen) - y1 -  target.frame_h;
1214 	if(y2 < 0)
1215 	{
1216 		y2 = 0;
1217 	}
1218 	width = (width - target.base_w)/target.width_inc;
1219 	height = (height - target.base_h)/target.height_inc;
1220 
1221 	sprintf(loc,"%dx%d",width,height);
1222 	strcpy(geometry, loc);
1223 
1224 	if ((target.gravity == EastGravity) ||
1225 	    (target.gravity == NorthEastGravity)||
1226 	    (target.gravity == SouthEastGravity))
1227 	{
1228 		sprintf(loc,"-%d",x2);
1229 	}
1230 	else
1231 	{
1232 		sprintf(loc,"+%d",x1);
1233 	}
1234 	strcat(geometry, loc);
1235 
1236 	if((target.gravity == SouthGravity)||
1237 	   (target.gravity == SouthEastGravity)||
1238 	   (target.gravity == SouthWestGravity))
1239 	{
1240 		sprintf(loc,"-%d",y2);
1241 	}
1242 	else
1243 	{
1244 		sprintf(loc,"+%d",y1);
1245 	}
1246 	strcat(geometry, loc);
1247 	AddToList("Geometry:", geometry);
1248 
1249 	{
1250 		Atom *protocols = NULL, *ap;
1251 		Atom _XA_WM_TAKE_FOCUS = XInternAtom(
1252 			dpy, "WM_TAKE_FOCUS", False);
1253 		XWMHints *wmhintsp = XGetWMHints(dpy,target.id);
1254 		int i,n;
1255 		Boolean HasTakeFocus=False,InputField=True;
1256 		char *focus_policy="",*ifstr="",*tfstr="";
1257 
1258 		if (wmhintsp)
1259 		{
1260 			InputField=wmhintsp->input;
1261 			ifstr=InputField?"True":"False";
1262 			XFree(wmhintsp);
1263 		}
1264 		else
1265 		{
1266 			ifstr="XWMHints missing";
1267 		}
1268 		if (XGetWMProtocols(dpy,target.id,&protocols,&n))
1269 		{
1270 			for (i = 0, ap = protocols; i < n; i++, ap++)
1271 			{
1272 				if (*ap == (Atom)_XA_WM_TAKE_FOCUS)
1273 					HasTakeFocus = True;
1274 			}
1275 			tfstr=HasTakeFocus?"Present":"Absent";
1276 			XFree(protocols);
1277 		}
1278 		else
1279 		{
1280 			tfstr="XGetWMProtocols failed";
1281 		}
1282 		if (HasTakeFocus)
1283 		{
1284 			if (InputField)
1285 			{
1286 				focus_policy = "Locally Active";
1287 			}
1288 			else
1289 			{
1290 				focus_policy = "Globally Active";
1291 			}
1292 		}
1293 		else
1294 		{
1295 			if (InputField)
1296 			{
1297 				focus_policy = "Passive";
1298 			}
1299 			else
1300 			{
1301 				focus_policy = "No Input";
1302 			}
1303 		}
1304 		AddToList("Focus Policy:",focus_policy);
1305 		AddToList("  - Input Field:",ifstr);
1306 		AddToList("  - WM_TAKE_FOCUS:",tfstr);
1307 		{
1308 			/* flags hints that were supplied */
1309 			long supplied_return;
1310 			int getrc;
1311 			XSizeHints *size_hints =
1312 				XAllocSizeHints(); /* the size hints */
1313 			if ((getrc = XGetWMSizeHints(
1314 				dpy,target.id, /* get size hints */
1315 				size_hints,    /* Hints */
1316 				&supplied_return,
1317 				XA_WM_ZOOM_HINTS)))
1318 			{
1319 				if (supplied_return & PAspect)
1320 				{ /* if window has a aspect ratio */
1321 					sprintf(
1322 						mymin_aspect, "%d/%d",
1323 						size_hints->min_aspect.x,
1324 						size_hints->min_aspect.y);
1325 					AddToList(
1326 						"Minimum aspect ratio:",
1327 						mymin_aspect);
1328 					sprintf(
1329 						max_aspect, "%d/%d",
1330 						size_hints->max_aspect.x,
1331 						size_hints->max_aspect.y);
1332 					AddToList(
1333 						"Maximum aspect ratio:",
1334 						max_aspect);
1335 				} /* end aspect ratio */
1336 				XFree(size_hints);
1337 			} /* end getsizehints worked */
1338 		}
1339 	}
1340 
1341 	/* EWMH window type */
1342 	if (target.ewmh_window_type == EWMH_WINDOW_TYPE_DESKTOP_ID)
1343 		AddToList("EWMH Window Type:","Desktop");
1344 	else if (target.ewmh_window_type == EWMH_WINDOW_TYPE_DIALOG_ID)
1345 		AddToList("EWMH Window Type:","Dialog");
1346 	else if (target.ewmh_window_type == EWMH_WINDOW_TYPE_DOCK_ID)
1347 		AddToList("EWMH Window Type:","Dock");
1348 	else if (target.ewmh_window_type == EWMH_WINDOW_TYPE_MENU_ID)
1349 		AddToList("EWMH Window Type:","Menu");
1350 	else if (target.ewmh_window_type == EWMH_WINDOW_TYPE_NORMAL_ID)
1351 		AddToList("EWMH Window Type:","Normal");
1352 	else if (target.ewmh_window_type == EWMH_WINDOW_TYPE_TOOLBAR_ID)
1353 		AddToList("EWMH Window Type:","ToolBar");
1354 
1355 	/* EWMH wm state */
1356 	ewmh_init_state[0] = '\0';
1357 	if (HAS_EWMH_INIT_FULLSCREEN_STATE(targ) == EWMH_STATE_HAS_HINT)
1358 	{
1359 		strcat(ewmh_init_state, "FullScreen ");
1360 	}
1361 	if (HAS_EWMH_INIT_HIDDEN_STATE(targ) == EWMH_STATE_HAS_HINT)
1362 	{
1363 		strcat(ewmh_init_state, "Iconic ");
1364 	}
1365 	if (HAS_EWMH_INIT_MAXHORIZ_STATE(targ) == EWMH_STATE_HAS_HINT)
1366 	{
1367 		strcat(ewmh_init_state, "MaxHoriz ");
1368 	}
1369 	if (HAS_EWMH_INIT_MAXVERT_STATE(targ) == EWMH_STATE_HAS_HINT)
1370 	{
1371 		strcat(ewmh_init_state, "MaxVert ");
1372 	}
1373 	if (HAS_EWMH_INIT_MODAL_STATE(targ) == EWMH_STATE_HAS_HINT)
1374 	{
1375 		strcat(ewmh_init_state, "Modal ");
1376 	}
1377 	if (HAS_EWMH_INIT_SHADED_STATE(targ)== EWMH_STATE_HAS_HINT)
1378 	{
1379 		strcat(ewmh_init_state, "Shaded ");
1380 	}
1381 	if (HAS_EWMH_INIT_SKIP_PAGER_STATE(targ) == EWMH_STATE_HAS_HINT ||
1382 	    HAS_EWMH_INIT_SKIP_TASKBAR_STATE(targ) == EWMH_STATE_HAS_HINT )
1383 	{
1384 		strcat(ewmh_init_state, "SkipList ");
1385 	}
1386 	if (HAS_EWMH_INIT_STICKY_STATE(targ) == EWMH_STATE_HAS_HINT ||
1387 	    (HAS_EWMH_INIT_WM_DESKTOP(targ) ==  EWMH_STATE_HAS_HINT &&
1388 	     (target.ewmh_hint_desktop == (unsigned long)-2 ||
1389 	      target.ewmh_hint_desktop == (unsigned long)-1)))
1390 	{
1391 		strcat(ewmh_init_state, "Sticky ");
1392 	}
1393 	/* FIXME: we should use the fvwm default layers */
1394 	if (target.ewmh_hint_layer == 6)
1395 	{
1396 		strcat(ewmh_init_state, "StaysOnTop ");
1397 	}
1398 	else if (target.ewmh_hint_layer == 2)
1399 	{
1400 		strcat(ewmh_init_state, "StaysOnBottom ");
1401 	}
1402 	if (HAS_EWMH_INIT_WM_DESKTOP(targ) == EWMH_STATE_HAS_HINT &&
1403 	    target.ewmh_hint_desktop < 256)
1404 	{
1405                 char desk_buf[32];
1406                 snprintf(desk_buf, 32, "StartOnDesk %lu ", target.ewmh_hint_desktop);
1407 		strcat(ewmh_init_state, desk_buf);
1408 	}
1409 	if (ewmh_init_state[0] != '\0')
1410 	{
1411 		/* remove ending space */
1412 		ewmh_init_state[strlen(ewmh_init_state)-1] = '\0';
1413 		AddToList("EWMH Init State:",ewmh_init_state);
1414 	}
1415 }
1416 
1417 /*
1418   X Error Handler
1419 */
1420 static int
ErrorHandler(Display * d,XErrorEvent * event)1421 ErrorHandler(Display *d, XErrorEvent *event)
1422 {
1423 #if 0
1424 	if (event->error_code == BadPixmap)
1425 	{
1426 		return 0;
1427 	}
1428 	if (event->error_code == BadDrawable)
1429 	{
1430 		return 0;
1431 	}
1432 	if (event->error_code == FRenderGetErrorCodeBase() + FRenderBadPicture)
1433 	{
1434 		return 0;
1435 	}
1436 #endif
1437 
1438 	PrintXErrorAndCoredump(d, event, module->name);
1439 	return 0;
1440 }
1441