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>
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. */
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.
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.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "libs/ftime.h"
37 #include <sys/select.h>
43 #include <X11/Xutil.h>
44 #include <X11/Xproto.h>
45 #include <X11/Xatom.h>
46 #include <X11/Intrinsic.h>
47 #include <X11/cursorfont.h>
48 #include <X11/keysym.h>
50 #include "libs/fvwmlib.h"
51 #include "libs/FScreen.h"
52 #include "libs/FShape.h"
53 #include "libs/Module.h"
54 #include "libs/Colorset.h"
55 #include "libs/fvwmsignal.h"
56 #include "libs/Flocale.h"
57 #include "libs/Parse.h"
58 #include "libs/FRenderInit.h"
59 #include "libs/Graphics.h"
60 #include "libs/System.h"
61 #include "libs/Target.h"
62 #include "libs/XError.h"
64 #include "FvwmIdent.h"
66 static RETSIGTYPE
TerminateHandler(int);
68 static ModuleArgs
*module
;
69 static fd_set_size_t fd_width
;
72 static Display
*dpy
; /* which display are we talking to */
76 static FlocaleFont
*Ffont
;
77 static FlocaleWinString
*FwinString
;
82 static char *yes
= "Yes";
83 static char *no
= "No";
85 /* default colorset to use, set to -1 when explicitly setting colors */
86 static int colorset
= 0;
88 static char *BackColor
= "white";
89 static char *ForeColor
= "black";
90 static char *font_string
= NULL
;
92 static Pixel fore_pix
;
93 static Pixel back_pix
;
94 static Window main_win
;
95 static Bool UsePixmapDrawing
= False
; /* if True draw everything in a pixmap
96 * and set the window background. Use
98 static int main_width
;
99 static int main_height
;
101 static EventMask mw_events
=
102 ExposureMask
| ButtonPressMask
| KeyPressMask
|
103 ButtonReleaseMask
| KeyReleaseMask
| StructureNotifyMask
;
105 static Atom wm_del_win
;
107 static struct target_struct target
;
110 static int ListSize
=0;
112 static struct Item
* itemlistRoot
= NULL
;
113 static int max_col1
, max_col2
;
114 static char id
[15], desktop
[10], swidth
[10], sheight
[10], borderw
[10];
115 static char geometry
[30], mymin_aspect
[11], max_aspect
[11], layer
[10];
116 static char ewmh_init_state
[512];
118 /* FIXME: default layer should be received from fvwm */
119 #define default_layer DEFAULT_DEFAULT_LAYER
120 static int minimal_layer
= default_layer
;
121 static int my_layer
= default_layer
;
126 * main - start of module
129 int main(int argc
, char **argv
)
131 char *display_name
= NULL
;
134 FlocaleInit(LC_CTYPE
, "", "", "FvwmIdent");
136 module
= ParseModuleArgs(argc
,argv
,0); /* no alias */
140 stderr
, "FvwmIdent Version %s should only be executed"
141 " by fvwm!\n", VERSION
);
145 #ifdef HAVE_SIGACTION
147 struct sigaction sigact
;
149 sigemptyset(&sigact
.sa_mask
);
150 sigaddset(&sigact
.sa_mask
, SIGPIPE
);
151 sigaddset(&sigact
.sa_mask
, SIGTERM
);
152 sigaddset(&sigact
.sa_mask
, SIGQUIT
);
153 sigaddset(&sigact
.sa_mask
, SIGINT
);
154 sigaddset(&sigact
.sa_mask
, SIGHUP
);
156 sigact
.sa_flags
= SA_INTERRUPT
;
160 sigact
.sa_handler
= TerminateHandler
;
162 sigaction(SIGPIPE
, &sigact
, NULL
);
163 sigaction(SIGTERM
, &sigact
, NULL
);
164 sigaction(SIGQUIT
, &sigact
, NULL
);
165 sigaction(SIGINT
, &sigact
, NULL
);
166 sigaction(SIGHUP
, &sigact
, NULL
);
169 /* We don't have sigaction(), so fall back to less robust methods. */
170 #ifdef USE_BSD_SIGNALS
171 fvwmSetSignalMask( sigmask(SIGPIPE
) |
177 signal(SIGPIPE
, TerminateHandler
);
178 signal(SIGTERM
, TerminateHandler
);
179 signal(SIGQUIT
, TerminateHandler
);
180 signal(SIGINT
, TerminateHandler
);
181 signal(SIGHUP
, TerminateHandler
);
182 #ifdef HAVE_SIGINTERRUPT
183 siginterrupt(SIGPIPE
, 1);
184 siginterrupt(SIGTERM
, 1);
185 siginterrupt(SIGQUIT
, 1);
186 siginterrupt(SIGINT
, 1);
187 siginterrupt(SIGHUP
, 1);
191 fd
[0] = module
->to_fvwm
;
192 fd
[1] = module
->from_fvwm
;
194 /* Open the Display */
195 if (!(dpy
= XOpenDisplay(display_name
)))
197 fprintf(stderr
,"%s: can't open display %s", module
->name
,
198 XDisplayName(display_name
));
201 x_fd
= XConnectionNumber(dpy
);
202 screen
= DefaultScreen(dpy
);
203 Root
= RootWindow(dpy
, screen
);
204 XSetErrorHandler(ErrorHandler
);
206 flib_init_graphics(dpy
);
207 FlocaleAllocateWinString(&FwinString
);
209 SetMessageMask(fd
, M_CONFIGURE_WINDOW
| M_WINDOW_NAME
| M_ICON_NAME
210 | M_RES_CLASS
| M_RES_NAME
| M_END_WINDOWLIST
|
211 M_CONFIG_INFO
| M_END_CONFIG_INFO
| M_SENDCONFIG
);
212 SetMessageMask(fd
, MX_PROPERTY_CHANGE
);
213 /* scan config file for set-up parameters */
214 /* Colors and fonts */
216 InitGetConfigLine(fd
,CatString3("*",module
->name
,0));
217 GetConfigLine(fd
,&tline
);
219 while (tline
!= (char *)0)
221 if (strlen(tline
) <= 1)
225 if (strncasecmp(tline
,
226 CatString3("*",module
->name
,0),
227 module
->namelen
+1) == 0)
229 tline
+= (module
->namelen
+1);
230 if (strncasecmp(tline
, "Font", 4) == 0)
232 CopyStringWithQuotes(&font_string
, &tline
[4]);
234 else if (strncasecmp(tline
, "Fore", 4) == 0)
236 CopyString(&ForeColor
, &tline
[4]);
239 else if (strncasecmp(tline
, "Back", 4) == 0)
241 CopyString(&BackColor
, &tline
[4]);
244 else if (strncasecmp(tline
, "Colorset", 8) == 0)
246 sscanf(&tline
[8], "%d", &colorset
);
247 AllocColorset(colorset
);
249 else if (strncasecmp(tline
, "MinimalLayer", 12) == 0)
251 char *layer_str
= PeekToken(&tline
[12], NULL
);
252 if (layer_str
== NULL
)
254 minimal_layer
= default_layer
;
257 layer_str
, "%d", &minimal_layer
) != 1)
260 layer_str
, "none", 4) == 0)
266 minimal_layer
= default_layer
;
271 else if (strncasecmp(tline
, "Colorset", 8) == 0)
273 LoadColorset(&tline
[8]);
275 else if (strncasecmp(
276 tline
, XINERAMA_CONFIG_STRING
,
277 sizeof(XINERAMA_CONFIG_STRING
) - 1) == 0)
279 FScreenConfigureModule(
280 tline
+ sizeof(XINERAMA_CONFIG_STRING
) - 1);
282 GetConfigLine(fd
, &tline
);
285 if(module
->window
== 0)
287 fvwmlib_get_target_window(
288 dpy
, screen
, module
->name
, &(module
->window
), True
);
291 fd_width
= GetFdWidth();
293 /* Create a list of all windows */
294 /* Request a list of all windows,
295 * wait for ConfigureWindow packets */
296 SendText(fd
, "Send_WindowList", 0);
298 /* tell fvwm we're running */
299 SendFinishedStartupNotification(fd
);
300 if (module
->window
== Root
)
311 * Read the entire window list from fvwm
318 FvwmPacket
* packet
= ReadFvwmPacket(fd
[1]);
319 if ( packet
== NULL
)
325 process_message( packet
->type
, packet
->body
);
333 * Process window list messages
336 void process_message(unsigned long type
,unsigned long *body
)
340 /* should turn off this packet but it comes after config_list
341 * so have to accept at least one */
342 case M_CONFIGURE_WINDOW
:
343 list_configure(body
);
346 list_window_name(body
);
349 list_icon_name(body
);
357 case M_END_WINDOWLIST
:
368 * SIGPIPE handler - SIGPIPE means fvwm is dying
372 TerminateHandler(int sig
)
374 fvwmSetTerminate(sig
);
380 * Got window configuration info - if its our window, save data
383 void list_configure(unsigned long *body
)
385 struct ConfigWinPacket
*cfgpacket
= (void *) body
;
388 (module
->window
== cfgpacket
->frame
)||
389 (module
->window
== cfgpacket
->w
) ||
390 ((cfgpacket
->icon_w
!= 0)&&
391 (module
->window
== cfgpacket
->icon_w
)) ||
392 ((cfgpacket
->icon_pixmap_w
)&&
393 (module
->window
== cfgpacket
->icon_pixmap_w
)))
395 module
->window
= cfgpacket
->frame
;
396 target
.id
= cfgpacket
->w
;
397 target
.frame
= cfgpacket
->frame
;
398 target
.frame_x
= cfgpacket
->frame_x
;
399 target
.frame_y
= cfgpacket
->frame_y
;
400 target
.frame_w
= cfgpacket
->frame_width
;
401 target
.frame_h
= cfgpacket
->frame_height
;
402 target
.desktop
= cfgpacket
->desk
;
403 target
.layer
= cfgpacket
->layer
;
404 memcpy(&target
.flags
,
405 &(cfgpacket
->flags
), sizeof(cfgpacket
->flags
));
406 target
.title_h
= cfgpacket
->title_height
;
407 target
.title_dir
= GET_TITLE_DIR(cfgpacket
);
408 target
.border_w
= cfgpacket
->border_width
;
409 target
.base_w
= cfgpacket
->hints_base_width
;
410 target
.base_h
= cfgpacket
->hints_base_height
;
411 target
.width_inc
= cfgpacket
->orig_hints_width_inc
;
412 target
.height_inc
= cfgpacket
->orig_hints_height_inc
;
413 target
.gravity
= cfgpacket
->hints_win_gravity
;
414 target
.ewmh_hint_layer
= cfgpacket
->ewmh_hint_layer
;
415 target
.ewmh_hint_desktop
= cfgpacket
->ewmh_hint_desktop
;
416 target
.ewmh_window_type
= cfgpacket
->ewmh_window_type
;
419 my_layer
= (int)target
.layer
;
420 if (my_layer
< minimal_layer
)
422 my_layer
= minimal_layer
;
429 * Capture Window name info
432 void list_window_name(unsigned long *body
)
435 (module
->window
== (Window
)body
[1])||
436 (module
->window
== (Window
)body
[0]))
438 strncpy(target
.name
,(char *)&body
[3],255);
444 * Capture Window Icon name info
447 void list_icon_name(unsigned long *body
)
450 (module
->window
== (Window
)body
[1])||
451 (module
->window
== (Window
)body
[0]))
453 strncpy(target
.icon_name
,(char *)&body
[3],255);
460 * Capture Window class name info
463 void list_class(unsigned long *body
)
466 (module
->window
== (Window
)body
[1])||
467 (module
->window
== (Window
)body
[0]))
469 strncpy(target
.class,(char *)&body
[3],255);
476 * Capture Window resource info
479 void list_res_name(unsigned long *body
)
481 if ((module
->window
== (Window
)body
[1])||
482 (module
->window
== (Window
)body
[0]))
484 strncpy(target
.res
,(char *)&body
[3],255);
488 void list_property_change(unsigned long *body
)
490 if (body
[0] == MX_PROPERTY_CHANGE_BACKGROUND
&& body
[2] == 0 &&
491 CSET_IS_TRANSPARENT_PR(colorset
))
493 if (UsePixmapDrawing
)
496 main_width
, main_height
);
500 UpdateBackgroundTransparency(
501 dpy
, main_win
, main_width
,
503 &Colorset
[(colorset
)], Pdepth
,
509 void list_config_info(unsigned long *body
)
513 tline
= (char*)&body
[3];
514 tline
= GetNextToken(tline
, &token
);
515 if (StrEquals(token
, "Colorset") && colorset
>= 0 &&
516 LoadColorset(tline
) == colorset
)
518 if (FftSupport
&& Ffont
->fftf
.fftfont
!= NULL
)
520 UsePixmapDrawing
= True
;
522 /* track all colorset changes & update display if necessary */
523 /* ask for movement events iff transparent */
524 if (CSET_IS_TRANSPARENT(colorset
))
527 mw_events
|= StructureNotifyMask
;
528 if (CSET_IS_TRANSPARENT_PR_PURE(colorset
))
530 UsePixmapDrawing
= False
;
535 mw_events
&= ~(StructureNotifyMask
);
537 if (UsePixmapDrawing
)
540 mw_events
&= ~(ExposureMask
);
545 mw_events
|= ExposureMask
;
547 XSelectInput(dpy
, main_win
, mw_events
);
548 XSetForeground(dpy
, gc
, Colorset
[colorset
].fg
);
549 if (UsePixmapDrawing
)
551 PixmapDrawWindow(main_width
, main_height
);
556 dpy
, main_win
, main_width
, main_height
,
557 &Colorset
[colorset
], Pdepth
, gc
, True
);
560 else if (StrEquals(token
, XINERAMA_CONFIG_STRING
))
562 FScreenConfigureModule(tline
);
573 int ProcessXEvent(int x
, int y
)
576 static int is_key_pressed
= 0;
577 static int is_button_pressed
= 0;
579 static int ex
=10000, ey
=10000, ex2
=0, ey2
=0;
581 while (FPending(dpy
))
583 FNextEvent(dpy
,&Event
);
587 ex
= min(ex
, Event
.xexpose
.x
);
588 ey
= min(ey
, Event
.xexpose
.y
);
589 ex2
= max(ex2
, Event
.xexpose
.x
+ Event
.xexpose
.width
);
590 ey2
=max(ey2
, Event
.xexpose
.y
+ Event
.xexpose
.height
);
591 while (FCheckTypedEvent(dpy
, Expose
, &Event
))
593 ex
= min(ex
, Event
.xexpose
.x
);
594 ey
= min(ey
, Event
.xexpose
.y
);
597 Event
.xexpose
.x
+ Event
.xexpose
.width
);
599 Event
.xexpose
.y
+ Event
.xexpose
.height
);
601 if (FftSupport
&& Ffont
->fftf
.fftfont
!= NULL
)
605 ex
, ey
, ex2
-ex
, ey2
-ey
, False
);
607 DrawItems(main_win
, ex
, ey
, ex2
-ex
, ey2
-ey
);
615 is_button_pressed
= Event
.xbutton
.button
;
624 if (is_button_pressed
)
626 if (is_button_pressed
== 2 &&
627 Event
.xbutton
.button
== 2)
629 /* select a new window when
630 * button 2 is pressed */
632 fd
, M_CONFIGURE_WINDOW
|
641 SendText(fd
, "Send_WindowList", 0);
642 XDestroyWindow(dpy
, main_win
);
644 fvwmlib_get_target_window(
645 dpy
, screen
, module
->name
,
646 &(module
->window
), True
);
657 if (Event
.xclient
.format
==32 &&
658 Event
.xclient
.data
.l
[0]==wm_del_win
)
664 if (minimal_layer
>= 0)
666 sprintf(buf
, "Layer 0 %d", my_layer
);
667 SendText(fd
, buf
, main_win
);
669 SendText(fd
, "Raise", main_win
);
671 case ConfigureNotify
:
672 /* this only happens with transparent windows,
673 * slurp up as many events as possible before
674 * redrawing to reduce flickering */
675 while (FCheckTypedEvent(
676 dpy
, ConfigureNotify
, &event
))
678 if (!event
.xconfigure
.send_event
)
680 Event
.xconfigure
.x
= event
.xconfigure
.x
;
681 Event
.xconfigure
.y
= event
.xconfigure
.y
;
682 Event
.xconfigure
.send_event
= True
;
684 /* Only refresh if moved */
685 if ((Event
.xconfigure
.send_event
||
686 CSET_IS_TRANSPARENT_PR_PURE(colorset
)) &&
687 (x
!= Event
.xconfigure
.x
||
688 y
!= Event
.xconfigure
.y
))
690 static Bool is_initial_cn
= True
;
691 Bool do_eat_expose
= False
;
693 x
= Event
.xconfigure
.x
;
694 y
= Event
.xconfigure
.y
;
695 /* flush any expose events */
696 if (UsePixmapDrawing
)
699 main_width
, main_height
);
700 do_eat_expose
= True
;
702 else if (colorset
== -1)
704 do_eat_expose
= True
;
706 else if (UpdateBackgroundTransparency(
707 dpy
, main_win
, main_width
,
709 &Colorset
[(colorset
)], Pdepth
,
712 do_eat_expose
= True
;
714 if (do_eat_expose
== True
&&
715 is_initial_cn
== False
)
717 while (FCheckTypedEvent(
718 dpy
, Expose
, &Event
))
723 is_initial_cn
= False
;
735 * End of window list, open an x window and display data in it
740 XSizeHints mysizehints
;
745 XSetWindowAttributes attributes
;
752 /* tell fvwm to only send config messages */
753 SetMessageMask(fd
, M_CONFIG_INFO
| M_SENDCONFIG
);
755 if ((Ffont
= FlocaleLoadFont(dpy
, font_string
, module
->name
)) == NULL
)
758 stderr
,"%s: cannot load font, exiting\n",
763 /* chose the rendering methode */
764 if (FftSupport
&& Ffont
->fftf
.fftfont
!= NULL
)
766 UsePixmapDrawing
= True
;
768 /* make window infomation list */
771 /* size and create the window */
772 lmax
= max_col1
+ max_col2
+ 15;
774 height
= ListSize
* (Ffont
->height
);
777 USSize
|USPosition
|PWinGravity
|PResizeInc
|PBaseSize
|PMinSize
|
779 main_width
= mysizehints
.width
= lmax
+ 10;
780 main_height
= mysizehints
.height
= height
+ 10;
781 mysizehints
.width_inc
= 1;
782 mysizehints
.height_inc
= 1;
783 mysizehints
.base_height
= mysizehints
.height
;
784 mysizehints
.base_width
= mysizehints
.width
;
785 mysizehints
.min_height
= mysizehints
.height
;
786 mysizehints
.min_width
= mysizehints
.width
;
787 mysizehints
.max_height
= mysizehints
.height
;
788 mysizehints
.max_width
= mysizehints
.width
;
789 mysizehints
.win_gravity
= NorthWestGravity
;
798 fscreen_scr_arg fscr
;
801 dpy
, Root
, &JunkW
, &JunkW
, &x
, &y
, &JunkC
, &JunkC
,
804 /* pointer is on a different screen */
811 FScreenGetScrRect(&fscr
, FSCREEN_XYPOS
, &sx
, &sy
, &sw
, &sh
);
812 if (y
+ height
+ 100 > sy
+ sh
)
814 y
= sy
+ sh
- height
- 10;
815 mysizehints
.win_gravity
= SouthWestGravity
;
817 if (x
+ lmax
+ 100 > sx
+ sw
)
819 x
= sx
+ sw
- lmax
- 10;
820 if (mysizehints
.win_gravity
== SouthWestGravity
)
821 mysizehints
.win_gravity
= SouthEastGravity
;
823 mysizehints
.win_gravity
= NorthEastGravity
;
829 back_pix
= GetColor("white");
830 fore_pix
= GetColor("black");
834 back_pix
= (colorset
< 0)?
835 GetColor(BackColor
) : Colorset
[colorset
].bg
;
836 fore_pix
= (colorset
< 0)?
837 GetColor(ForeColor
) : Colorset
[colorset
].fg
;
840 attributes
.colormap
= Pcmap
;
841 attributes
.border_pixel
= 0;
842 attributes
.background_pixel
= back_pix
;
843 main_win
= XCreateWindow(
844 dpy
, Root
, x
, y
, mysizehints
.width
, mysizehints
.height
, 0,
845 Pdepth
, InputOutput
, Pvisual
, CWColormap
| CWBackPixel
|
846 CWBorderPixel
, &attributes
);
847 wm_del_win
= XInternAtom(dpy
,"WM_DELETE_WINDOW",False
);
848 XSetWMProtocols(dpy
,main_win
,&wm_del_win
,1);
850 /* hack to prevent mapping on wrong screen with StartsOnScreen */
851 FScreenMangleScreenIntoUSPosHints(FSCREEN_XYPOS
, &mysizehints
);
852 XSetWMNormalHints(dpy
,main_win
,&mysizehints
);
853 /* have to ask for configure events when transparent */
854 if (CSET_IS_TRANSPARENT(colorset
))
856 mw_events
|= StructureNotifyMask
;
857 if (CSET_IS_TRANSPARENT_PR_PURE(colorset
))
859 UsePixmapDrawing
= 0;
862 if (!UsePixmapDrawing
)
864 mw_events
|= ExposureMask
;
867 XSelectInput(dpy
, main_win
, mw_events
);
868 change_window_name(module
->name
);
871 gcv
.foreground
= fore_pix
;
872 if (Ffont
->font
!= NULL
)
875 gcv
.font
= Ffont
->font
->fid
;
877 gc
= fvwmlib_XCreateGC(dpy
, main_win
, gcm
, &gcv
);
878 if (UsePixmapDrawing
)
880 PixmapDrawWindow(main_width
, main_height
);
882 else if (colorset
>= 0)
885 dpy
, main_win
, main_width
, main_height
,
886 &Colorset
[(colorset
)], Pdepth
, gc
, True
);
888 XMapWindow(dpy
,main_win
);
890 /* Window is created. Display it until the user clicks or deletes it.
891 * also grok any dynamic config changes */
895 int x_fd
= XConnectionNumber(dpy
);
899 FD_SET(fd
[1], &fdset
);
900 FD_SET(x_fd
, &fdset
);
902 /* process all X events first */
903 if (ProcessXEvent(x
,y
) == 1)
908 /* wait for X-event or config line */
909 select(fd_width
, SELECT_FD_SET_CAST
&fdset
, NULL
, NULL
, NULL
);
911 /* parse any dynamic config lines */
912 if (FD_ISSET(fd
[1], &fdset
))
914 packet
= ReadFvwmPacket(fd
[1]);
917 if (packet
&& packet
->type
== MX_PROPERTY_CHANGE
)
919 list_property_change(packet
->body
);
921 if (packet
&& packet
->type
== M_CONFIG_INFO
)
923 list_config_info(packet
->body
);
934 void DrawItems(Drawable d
, int x
, int y
, int w
, int h
)
937 struct Item
*cur
= itemlistRoot
;
940 fontheight
= Ffont
->height
;
943 FwinString
->flags
.has_clip_region
= False
;
953 region
= XCreateRegion();
954 XUnionRectWithRegion(&r
, region
, region
);
955 XSetRegion(dpy
, gc
, region
);
956 FwinString
->flags
.has_clip_region
= True
;
957 FwinString
->clip_region
= region
;
962 FwinString
->colorset
= &Colorset
[colorset
];
963 FwinString
->flags
.has_colorset
= True
;
965 while(cur
!= NULL
) /* may be optimised */
968 FwinString
->str
= cur
->col1
;
970 FwinString
->y
= 5 + Ffont
->ascent
+ i
* fontheight
;
971 FlocaleDrawString(dpy
, Ffont
, FwinString
, 0);
974 FwinString
->str
= cur
->col2
;
975 FwinString
->x
= 10 + max_col1
;
976 FlocaleDrawString(dpy
, Ffont
, FwinString
, 0);
981 if (FwinString
->flags
.has_clip_region
)
983 XDestroyRegion(region
);
984 XSetClipMask(dpy
, gc
, None
);
989 void PixmapDrawWindow(int w
, int h
)
998 cs_pix
= CreateBackgroundPixmap(dpy
, main_win
, w
, h
,
999 &Colorset
[(colorset
)],
1001 if (cs_pix
== ParentRelative
)
1007 pix
= CreateTiledPixmap(
1008 dpy
, cs_pix
, 0,0,w
,h
,Pdepth
, gc
);
1009 XFreePixmap(dpy
, cs_pix
);
1015 gcv
.foreground
= back_pix
;
1016 XChangeGC(dpy
, gc
, gcm
, &gcv
);
1017 pix
= XCreatePixmap(dpy
, main_win
, w
, h
, Pdepth
);
1018 XFillRectangle(dpy
, pix
, gc
, 0, 0, w
, h
);
1019 gcv
.foreground
= fore_pix
;
1020 XChangeGC(dpy
, gc
, gcm
, &gcv
);
1023 if (pix
!= ParentRelative
)
1025 DrawItems(pix
, 0, 0, 0, 0);
1026 XSetWindowBackgroundPixmap(dpy
, main_win
, pix
);
1027 XClearWindow(dpy
, main_win
);
1028 XFreePixmap(dpy
, pix
);
1032 XSetWindowBackgroundPixmap(dpy
, main_win
, pix
);
1033 XClearWindow(dpy
, main_win
);
1034 DrawItems(main_win
, 0, 0, 0, 0);
1039 * Change the window name displayed in the title bar.
1041 void change_window_name(char *str
)
1044 XClassHint myclasshints
;
1046 if (XStringListToTextProperty(&str
,1,&name
) == 0)
1048 fprintf(stderr
,"%s: cannot allocate window name",module
->name
);
1051 XSetWMName(dpy
,main_win
,&name
);
1052 XSetWMIconName(dpy
,main_win
,&name
);
1054 myclasshints
.res_name
= str
;
1055 myclasshints
.res_class
= "FvwmIdent";
1056 XSetClassHint(dpy
,main_win
,&myclasshints
);
1060 void DestroyList(void)
1065 for (t
= itemlistRoot
; t
; t
= tmp
)
1070 itemlistRoot
= NULL
;
1075 * Add s1(string at first column) and s2(string at second column) to itemlist
1078 void AddToList(char *s1
, char* s2
)
1081 struct Item
* item
, *cur
= itemlistRoot
;
1083 tw1
= FlocaleTextWidth(Ffont
, s1
, strlen(s1
));
1084 tw2
= FlocaleTextWidth(Ffont
, s2
, strlen(s2
));
1085 max_col1
= max_col1
> tw1
? max_col1
: tw1
;
1086 max_col2
= max_col2
> tw2
? max_col2
: tw2
;
1088 item
= (struct Item
*)safemalloc(sizeof(struct Item
));
1096 itemlistRoot
= item
;
1100 while(cur
->next
!= NULL
)
1111 int bw
,width
,height
,x1
,y1
,x2
,y2
;
1113 static char xstr
[6],ystr
[6];
1114 /* GSFR - quick hack because the new macros depend on a prt reference
1116 struct target_struct
*targ
= &target
;
1120 bw
= 2*target
.border_w
;
1121 width
= target
.frame_w
- bw
;
1122 height
= target
.frame_h
- bw
;
1123 if (target
.title_dir
== DIR_W
|| target
.title_dir
== DIR_E
)
1125 width
-= target
.title_h
;
1127 else if (target
.title_dir
== DIR_N
|| target
.title_dir
== DIR_S
)
1129 height
-= target
.title_h
;
1132 sprintf(desktop
, "%ld", target
.desktop
);
1133 sprintf(layer
, "%ld", target
.layer
);
1134 sprintf(id
, "0x%x", (unsigned int)target
.id
);
1135 sprintf(swidth
, "%d", width
);
1136 sprintf(sheight
, "%d", height
);
1137 sprintf(borderw
, "%ld", target
.border_w
);
1138 sprintf(xstr
, "%ld", target
.frame_x
);
1139 sprintf(ystr
, "%ld", target
.frame_y
);
1141 AddToList("Name:", target
.name
);
1142 AddToList("Icon Name:", target
.icon_name
);
1143 AddToList("Class:", target
.class);
1144 AddToList("Resource:", target
.res
);
1145 AddToList("Window ID:", id
);
1146 AddToList("Desk:", desktop
);
1147 AddToList("Layer:", layer
);
1148 AddToList("Width:", swidth
);
1149 AddToList("Height:", sheight
);
1150 AddToList("X (current page):", xstr
);
1151 AddToList("Y (current page):", ystr
);
1152 AddToList("Boundary Width:", borderw
);
1154 AddToList("StickyPage:", (IS_STICKY_ACROSS_PAGES(targ
) ? yes
: no
));
1155 AddToList("StickyDesk:", (IS_STICKY_ACROSS_DESKS(targ
) ? yes
: no
));
1156 AddToList("StickyPageIcon:",
1157 (IS_ICON_STICKY_ACROSS_PAGES(targ
) ? yes
: no
));
1158 AddToList("StickyDeskIcon:",
1159 (IS_ICON_STICKY_ACROSS_DESKS(targ
) ? yes
: no
));
1160 AddToList("NoTitle:", (HAS_TITLE(targ
) ? no
: yes
));
1161 AddToList("Iconified:", (IS_ICONIFIED(targ
) ? yes
: no
));
1162 AddToList("Transient:", (IS_TRANSIENT(targ
) ? yes
: no
));
1163 AddToList("WindowListSkip:", (DO_SKIP_WINDOW_LIST(targ
) ? yes
: no
));
1165 switch(target
.gravity
)
1168 AddToList("Gravity:", "Forget");
1170 case NorthWestGravity
:
1171 AddToList("Gravity:", "NorthWest");
1174 AddToList("Gravity:", "North");
1176 case NorthEastGravity
:
1177 AddToList("Gravity:", "NorthEast");
1180 AddToList("Gravity:", "West");
1183 AddToList("Gravity:", "Center");
1186 AddToList("Gravity:", "East");
1188 case SouthWestGravity
:
1189 AddToList("Gravity:", "SouthWest");
1192 AddToList("Gravity:", "South");
1194 case SouthEastGravity
:
1195 AddToList("Gravity:", "SouthEast");
1198 AddToList("Gravity:", "Static");
1201 AddToList("Gravity:", "Unknown");
1204 x1
= target
.frame_x
;
1209 x2
= DisplayWidth(dpy
,screen
) - x1
- target
.frame_w
;
1214 y1
= target
.frame_y
;
1219 y2
= DisplayHeight(dpy
,screen
) - y1
- target
.frame_h
;
1224 width
= (width
- target
.base_w
)/target
.width_inc
;
1225 height
= (height
- target
.base_h
)/target
.height_inc
;
1227 sprintf(loc
,"%dx%d",width
,height
);
1228 strcpy(geometry
, loc
);
1230 if ((target
.gravity
== EastGravity
) ||
1231 (target
.gravity
== NorthEastGravity
)||
1232 (target
.gravity
== SouthEastGravity
))
1234 sprintf(loc
,"-%d",x2
);
1238 sprintf(loc
,"+%d",x1
);
1240 strcat(geometry
, loc
);
1242 if((target
.gravity
== SouthGravity
)||
1243 (target
.gravity
== SouthEastGravity
)||
1244 (target
.gravity
== SouthWestGravity
))
1246 sprintf(loc
,"-%d",y2
);
1250 sprintf(loc
,"+%d",y1
);
1252 strcat(geometry
, loc
);
1253 AddToList("Geometry:", geometry
);
1256 Atom
*protocols
= NULL
, *ap
;
1257 Atom _XA_WM_TAKE_FOCUS
= XInternAtom(
1258 dpy
, "WM_TAKE_FOCUS", False
);
1259 XWMHints
*wmhintsp
= XGetWMHints(dpy
,target
.id
);
1261 Boolean HasTakeFocus
=False
,InputField
=True
;
1262 char *focus_policy
="",*ifstr
="",*tfstr
="";
1266 InputField
=wmhintsp
->input
;
1267 ifstr
=InputField
?"True":"False";
1272 ifstr
="XWMHints missing";
1274 if (XGetWMProtocols(dpy
,target
.id
,&protocols
,&n
))
1276 for (i
= 0, ap
= protocols
; i
< n
; i
++, ap
++)
1278 if (*ap
== (Atom
)_XA_WM_TAKE_FOCUS
)
1279 HasTakeFocus
= True
;
1281 tfstr
=HasTakeFocus
?"Present":"Absent";
1286 tfstr
="XGetWMProtocols failed";
1292 focus_policy
= "Locally Active";
1296 focus_policy
= "Globally Active";
1303 focus_policy
= "Passive";
1307 focus_policy
= "No Input";
1310 AddToList("Focus Policy:",focus_policy
);
1311 AddToList(" - Input Field:",ifstr
);
1312 AddToList(" - WM_TAKE_FOCUS:",tfstr
);
1314 /* flags hints that were supplied */
1315 long supplied_return
;
1317 XSizeHints
*size_hints
=
1318 XAllocSizeHints(); /* the size hints */
1319 if ((getrc
= XGetWMSizeHints(
1320 dpy
,target
.id
, /* get size hints */
1321 size_hints
, /* Hints */
1325 if (supplied_return
& PAspect
)
1326 { /* if window has a aspect ratio */
1328 mymin_aspect
, "%d/%d",
1329 size_hints
->min_aspect
.x
,
1330 size_hints
->min_aspect
.y
);
1332 "Minimum aspect ratio:",
1335 max_aspect
, "%d/%d",
1336 size_hints
->max_aspect
.x
,
1337 size_hints
->max_aspect
.y
);
1339 "Maximum aspect ratio:",
1341 } /* end aspect ratio */
1343 } /* end getsizehints worked */
1347 /* EWMH window type */
1348 if (target
.ewmh_window_type
== EWMH_WINDOW_TYPE_DESKTOP_ID
)
1349 AddToList("EWMH Window Type:","Desktop");
1350 else if (target
.ewmh_window_type
== EWMH_WINDOW_TYPE_DIALOG_ID
)
1351 AddToList("EWMH Window Type:","Dialog");
1352 else if (target
.ewmh_window_type
== EWMH_WINDOW_TYPE_DOCK_ID
)
1353 AddToList("EWMH Window Type:","Dock");
1354 else if (target
.ewmh_window_type
== EWMH_WINDOW_TYPE_MENU_ID
)
1355 AddToList("EWMH Window Type:","Menu");
1356 else if (target
.ewmh_window_type
== EWMH_WINDOW_TYPE_NORMAL_ID
)
1357 AddToList("EWMH Window Type:","Normal");
1358 else if (target
.ewmh_window_type
== EWMH_WINDOW_TYPE_TOOLBAR_ID
)
1359 AddToList("EWMH Window Type:","ToolBar");
1362 ewmh_init_state
[0] = '\0';
1363 if (HAS_EWMH_INIT_FULLSCREEN_STATE(targ
) == EWMH_STATE_HAS_HINT
)
1365 strcat(ewmh_init_state
, "FullScreen ");
1367 if (HAS_EWMH_INIT_HIDDEN_STATE(targ
) == EWMH_STATE_HAS_HINT
)
1369 strcat(ewmh_init_state
, "Iconic ");
1371 if (HAS_EWMH_INIT_MAXHORIZ_STATE(targ
) == EWMH_STATE_HAS_HINT
)
1373 strcat(ewmh_init_state
, "MaxHoriz ");
1375 if (HAS_EWMH_INIT_MAXVERT_STATE(targ
) == EWMH_STATE_HAS_HINT
)
1377 strcat(ewmh_init_state
, "MaxVert ");
1379 if (HAS_EWMH_INIT_MODAL_STATE(targ
) == EWMH_STATE_HAS_HINT
)
1381 strcat(ewmh_init_state
, "Modal ");
1383 if (HAS_EWMH_INIT_SHADED_STATE(targ
)== EWMH_STATE_HAS_HINT
)
1385 strcat(ewmh_init_state
, "Shaded ");
1387 if (HAS_EWMH_INIT_SKIP_PAGER_STATE(targ
) == EWMH_STATE_HAS_HINT
||
1388 HAS_EWMH_INIT_SKIP_TASKBAR_STATE(targ
) == EWMH_STATE_HAS_HINT
)
1390 strcat(ewmh_init_state
, "SkipList ");
1392 if (HAS_EWMH_INIT_STICKY_STATE(targ
) == EWMH_STATE_HAS_HINT
||
1393 (HAS_EWMH_INIT_WM_DESKTOP(targ
) == EWMH_STATE_HAS_HINT
&&
1394 (target
.ewmh_hint_desktop
== (unsigned long)-2 ||
1395 target
.ewmh_hint_desktop
== (unsigned long)-1)))
1397 strcat(ewmh_init_state
, "Sticky ");
1399 /* FIXME: we should use the fvwm default layers */
1400 if (target
.ewmh_hint_layer
== 6)
1402 strcat(ewmh_init_state
, "StaysOnTop ");
1404 else if (target
.ewmh_hint_layer
== 2)
1406 strcat(ewmh_init_state
, "StaysOnBottom ");
1408 if (HAS_EWMH_INIT_WM_DESKTOP(targ
) == EWMH_STATE_HAS_HINT
&&
1409 target
.ewmh_hint_desktop
< 256)
1411 strcat(ewmh_init_state
, "StartOnDesk");
1412 sprintf(ewmh_init_state
, "%s %lu ",
1413 ewmh_init_state
, target
.ewmh_hint_desktop
);
1415 if (ewmh_init_state
[0] != '\0')
1417 /* remove ending space */
1418 ewmh_init_state
[strlen(ewmh_init_state
)-1] = '\0';
1419 AddToList("EWMH Init State:",ewmh_init_state
);
1427 ErrorHandler(Display
*d
, XErrorEvent
*event
)
1430 if (event
->error_code
== BadPixmap
)
1434 if (event
->error_code
== BadDrawable
)
1438 if (event
->error_code
== FRenderGetErrorCodeBase() + FRenderBadPicture
)
1444 PrintXErrorAndCoredump(d
, event
, module
->name
);