3 * FvwmRearrange.c -- fvwm module to arrange windows
5 * Copyright (C) 1996, 1997, 1998, 1999 Andrew T. Veliath
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Combined FvwmTile and FvwmCascade to FvwmRearrange module.
24 * 9-Nov-1998 Dominik Vogt
30 #include "libs/ftime.h"
31 #include <sys/types.h>
35 #ifdef HAVE_SYS_BSDTYPES_H
36 #include <sys/bsdtypes.h>
40 #include <sys/select.h>
45 #include "libs/fvwmlib.h"
46 #include "libs/FScreen.h"
47 #include "libs/Module.h"
48 #include "fvwm/fvwm.h"
49 #include "libs/vpacket.h"
50 #include "libs/System.h"
52 typedef struct window_item
{
55 unsigned long width
, height
;
56 struct window_item
*prev
, *next
;
57 } window_item
, *window_list
;
63 static ModuleArgs
*module
;
65 fd_set_size_t fd_width
;
66 window_list wins
= NULL
, wins_tail
= NULL
;
71 int ofsx
= 0, ofsy
= 0;
72 int maxw
= 0, maxh
= 0;
74 int untitled
= 0, transients
= 0;
78 int reversed
= 0, raise_window
= 1;
83 int flatx
= 0, flaty
= 0;
84 int incx
= 0, incy
= 0;
95 RETSIGTYPE
DeadPipe(int sig
)
101 void insert_window_list(window_list
*wl
, window_item
*i
)
104 if ((i
->prev
= (*wl
)->prev
))
109 i
->next
= i
->prev
= NULL
;
113 void free_window_list(window_list wl
)
125 int is_suitable_window(unsigned long *body
)
127 XWindowAttributes xwa
;
128 struct ConfigWinPacket
*cfgpacket
= (void *) body
;
130 if ((DO_SKIP_WINDOW_LIST(cfgpacket
)) && !all
)
133 if ((IS_MAXIMIZED(cfgpacket
)) && !maximized
)
136 if ((IS_STICKY_ACROSS_PAGES(cfgpacket
)) && !sticky_page
)
139 if ((IS_STICKY_ACROSS_DESKS(cfgpacket
)) && !sticky_desk
)
142 if (!XGetWindowAttributes(dpy
, cfgpacket
->w
, &xwa
))
145 if (xwa
.map_state
!= IsViewable
)
148 if (!(IS_MAPPED(cfgpacket
)))
151 if (IS_ICONIFIED(cfgpacket
))
156 int x
= (int)cfgpacket
->frame_x
, y
= (int)cfgpacket
->frame_y
;
157 int w
= (int)cfgpacket
->frame_width
, h
= (int)cfgpacket
->frame_height
;
158 if (x
>= dx
+ dwidth
|| y
>= dy
+ dheight
|| x
+ w
<= dx
|| y
+ h
<= dy
)
162 if (!(HAS_TITLE(cfgpacket
)) && !untitled
)
165 if ((IS_TRANSIENT(cfgpacket
)) && !transients
)
174 struct ConfigWinPacket
*cfgpacket
;
179 FD_SET(fd
[1], &infds
);
180 select(fd_width
, SELECT_FD_SET_CAST
&infds
, 0, 0, NULL
);
182 if ( (packet
= ReadFvwmPacket(fd
[1])) == NULL
)
185 cfgpacket
= (struct ConfigWinPacket
*) packet
->body
;
186 switch (packet
->type
) {
187 case M_CONFIGURE_WINDOW
:
188 if (is_suitable_window(packet
->body
)) {
190 (window_item
*)safemalloc(sizeof( window_item
));
191 wi
->frame
= cfgpacket
->frame
;
192 wi
->th
= cfgpacket
->title_height
;
193 wi
->bw
= cfgpacket
->border_width
;
194 wi
->width
= cfgpacket
->frame_width
;
195 wi
->height
= cfgpacket
->frame_height
;
196 if (!wins_tail
) wins_tail
= wi
;
197 insert_window_list(&wins
, wi
);
203 case M_END_WINDOWLIST
:
208 "%s: internal inconsistency: unknown message 0x%08x\n",
209 module
->name
, (int)packet
->type
);
216 void wait_configure(window_item
*wi
)
220 /** Uh, what's the point of the select() here?? **/
223 FD_SET(fd
[1], &infds
);
224 select(fd_width
, SELECT_FD_SET_CAST
&infds
, 0, 0, NULL
);
227 FvwmPacket
* packet
= ReadFvwmPacket(fd
[1]);
228 if ( packet
== NULL
)
230 if ( packet
->type
== M_CONFIGURE_WINDOW
231 && (Window
)(packet
->body
[1]) == wi
->frame
)
236 int atopixel(char *s
, unsigned long f
)
240 if (isalpha(s
[l
- 1])) {
243 s2
[strlen(s2
) - 1] = 0;
246 return (atoi(s
) * f
) / 100;
249 void move_resize_raise_window(
250 window_item
*wi
, int x
, int y
, int w
, int h
)
256 const char *function
= do_maximize
?
257 "ResizeMoveMaximize":
259 sprintf(msg
, "%s %dp %dp %up %up", function
, w
, h
, x
, y
);
260 SendText(fd
, msg
, wi
->frame
);
264 const char *function
= do_maximize
?
265 "ResizeMoveMaximize":
266 do_animate
? "AnimatedMove" : "Move";
268 sprintf(msg
, "%s keep keep %up %up", function
, x
, y
);
270 sprintf(msg
, "%s %up %up", function
, x
, y
);
271 SendText(fd
, msg
, wi
->frame
);
275 SendText(fd
, "Raise", wi
->frame
);
280 void tile_windows(void)
282 int cur_x
= ofsx
, cur_y
= ofsy
;
283 int final_w
= -1, final_h
= -1;
284 int wdiv
, hdiv
, i
, j
, count
= 1;
285 window_item
*w
= reversed
? wins_tail
: wins
;
288 if ((maxnum
> 0) && (maxnum
< wins_count
)) {
289 count
= wins_count
/ maxnum
;
290 if (wins_count
% maxnum
) ++count
;
291 hdiv
= (maxy
- ofsy
+ 1) / maxnum
;
294 hdiv
= (maxy
- ofsy
+ 1) / wins_count
;
296 wdiv
= (maxx
- ofsx
+ 1) / count
;
298 for (i
= 0; w
&& (i
< count
); ++i
) {
299 for (j
= 0; w
&& (j
< maxnum
); ++j
) {
300 int nw
= wdiv
- w
->bw
* 2;
301 int nh
= hdiv
- w
->bw
* 2 - w
->th
;
310 final_w
= (nw
> 0) ? nw
: w
->width
;
311 final_h
= (nh
> 0) ? nh
: w
->height
;
313 move_resize_raise_window(w
, cur_x
, cur_y
, final_w
, final_h
);
316 w
= reversed
? w
->prev
: w
->next
;
322 if ((maxnum
> 0) && (maxnum
< wins_count
)) {
323 count
= wins_count
/ maxnum
;
324 if (wins_count
% maxnum
) ++count
;
325 wdiv
= (maxx
- ofsx
+ 1) / maxnum
;
328 wdiv
= (maxx
- ofsx
+ 1) / wins_count
;
330 hdiv
= (maxy
- ofsy
+ 1) / count
;
332 for (i
= 0; w
&& (i
< count
); ++i
) {
333 for (j
= 0; w
&& (j
< maxnum
); ++j
) {
334 int nw
= wdiv
- w
->bw
* 2;
335 int nh
= hdiv
- w
->bw
* 2 - w
->th
;
344 final_w
= (nw
> 0) ? nw
: w
->width
;
345 final_h
= (nh
> 0) ? nh
: w
->height
;
347 move_resize_raise_window(w
, cur_x
, cur_y
, final_w
, final_h
);
350 w
= reversed
? w
->prev
: w
->next
;
358 void cascade_windows(void)
360 int cur_x
= ofsx
, cur_y
= ofsy
;
361 int final_w
= -1, final_h
= -1;
362 window_item
*w
= reversed
? wins_tail
: wins
;
365 unsigned long nw
= 0, nh
= 0;
369 && (w
->width
> maxw
))
372 && (w
->height
> maxh
))
379 final_w
= nw
? nw
: w
->width
;
380 final_h
= nh
? nh
: w
->height
;
383 move_resize_raise_window(w
, cur_x
, cur_y
, final_w
, final_h
);
389 cur_y
+= w
->bw
+ w
->th
;
391 w
= reversed
? w
->prev
: w
->next
;
395 void parse_args(char *s
, int argc
, char *argv
[], int argi
)
399 for (; argi
< argc
; ++argi
)
401 if (!strcmp(argv
[argi
], "-tile") || !strcmp(argv
[argi
], "-cascade")) {
404 else if (!strcmp(argv
[argi
], "-u")) {
407 else if (!strcmp(argv
[argi
], "-t")) {
410 else if (!strcmp(argv
[argi
], "-a")) {
411 all
= untitled
= transients
= maximized
= 1;
416 else if (!strcmp(argv
[argi
], "-r")) {
419 else if (!strcmp(argv
[argi
], "-noraise")) {
422 else if (!strcmp(argv
[argi
], "-noresize")) {
425 else if (!strcmp(argv
[argi
], "-nostretch")) {
428 else if (!strcmp(argv
[argi
], "-desk")) {
431 else if (!strcmp(argv
[argi
], "-flatx")) {
434 else if (!strcmp(argv
[argi
], "-flaty")) {
437 else if (!strcmp(argv
[argi
], "-r")) {
440 else if (!strcmp(argv
[argi
], "-h")) {
443 else if (!strcmp(argv
[argi
], "-m")) {
446 else if (!strcmp(argv
[argi
], "-s")) {
450 else if (!strcmp(argv
[argi
], "-sp")) {
453 else if (!strcmp(argv
[argi
], "-sd")) {
456 else if (!strcmp(argv
[argi
], "-mn") && ((argi
+ 1) < argc
)) {
457 maxnum
= atoi(argv
[++argi
]);
459 else if (!strcmp(argv
[argi
], "-resize")) {
462 else if (!strcmp(argv
[argi
], "-nostretch")) {
465 else if (!strcmp(argv
[argi
], "-incx") && ((argi
+ 1) < argc
)) {
466 incx
= atopixel(argv
[++argi
], dwidth
);
468 else if (!strcmp(argv
[argi
], "-incy") && ((argi
+ 1) < argc
)) {
469 incy
= atopixel(argv
[++argi
], dheight
);
471 else if (!strcmp(argv
[argi
], "-maximize")) {
474 else if (!strcmp(argv
[argi
], "-nomaximize")) {
477 else if (!strcmp(argv
[argi
], "-animate")) {
480 else if (!strcmp(argv
[argi
], "-noanimate")) {
486 "%s: %s: ignoring unknown arg %s\n",
487 module
->name
, s
, argv
[argi
]);
491 ofsx
= atopixel(argv
[argi
], dwidth
);
492 } else if (nsargc
== 2) {
493 ofsy
= atopixel(argv
[argi
], dheight
);
494 } else if (nsargc
== 3) {
496 maxw
= atopixel(argv
[argi
], dwidth
);
498 maxx
= atopixel(argv
[argi
], dwidth
);
499 } else if (nsargc
== 4) {
501 maxh
= atopixel(argv
[argi
], dheight
);
503 maxy
= atopixel(argv
[argi
], dheight
);
513 int main(int argc
, char *argv
[])
519 console
= fopen("/dev/console","w");
520 if (!console
) console
= stderr
;
522 module
= ParseModuleArgs(argc
,argv
,0);
525 fprintf(stderr
,"FvwmRearrange: module should be executed by fvwm only\n");
529 fd
[0] = module
->to_fvwm
;
530 fd
[1] = module
->from_fvwm
;
532 if (!(dpy
= XOpenDisplay(NULL
))) {
533 fprintf(console
, "%s: couldn't open display %s\n",
538 signal (SIGPIPE
, DeadPipe
);
541 scr
= DefaultScreen(dpy
);
542 fd_width
= GetFdWidth();
545 strcat(match
, module
->name
);
546 InitGetConfigLine(fd
,match
);
547 GetConfigLine(fd
, &config_line
);
548 while (config_line
!= NULL
)
550 if (strncasecmp(config_line
, XINERAMA_CONFIG_STRING
,
551 sizeof(XINERAMA_CONFIG_STRING
) - 1) == 0)
553 FScreenConfigureModule(
554 config_line
+ sizeof(XINERAMA_CONFIG_STRING
) - 1);
556 GetConfigLine(fd
, &config_line
);
558 FScreenGetScrRect(NULL
, FSCREEN_CURRENT
, &dx
, &dy
, &dwidth
, &dheight
);
560 if (strcmp(module
->name
, "FvwmCascade") &&
561 (!strcmp(module
->name
, "FvwmTile") ||
562 (argc
>= 7 && !strcmp(argv
[6], "-tile")))) {
571 parse_args("module args", module
->user_argc
, module
->user_argv
, 0);
586 SendText(fd
, "Send_WindowList", 0);
588 /* tell fvwm we're running */
589 SendFinishedStartupNotification(fd
);
591 while (get_window()) /* */;
598 free_window_list(wins
);
600 if (console
!= stderr
)