1 /*
2 * Copyright (C) 2005 Fabian Yamaguchi <fabiany at gmx.net>
3 * Copyright (C) 2004 Sasha Vasko <sasha at aftercode.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /*#define DO_CLOCKING */
21 #define LOCAL_DEBUG
22 #define EVENT_TRACE
23
24 #include "../../configure.h"
25 #include "../../libAfterStep/asapp.h"
26
27 #include <signal.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <regex.h>
31 #include <stdlib.h>
32 #include <math.h>
33
34 #include "../../libAfterImage/afterimage.h"
35
36 #include "../../libAfterStep/afterstep.h"
37 #include "../../libAfterStep/screen.h"
38 #include "../../libAfterStep/module.h"
39 #include "../../libAfterStep/mystyle.h"
40 #include "../../libAfterStep/mystyle_property.h"
41 #include "../../libAfterStep/parser.h"
42 #include "../../libAfterStep/clientprops.h"
43 #include "../../libAfterStep/wmprops.h"
44 #include "../../libAfterStep/decor.h"
45 #include "../../libAfterStep/aswindata.h"
46 #include "../../libAfterStep/balloon.h"
47 #include "../../libAfterStep/event.h"
48 #include "../../libAfterStep/shape.h"
49 #include "../../libAfterStep/ascommand.h"
50 #include "../../libAfterStep/operations.h"
51
52 #include "../../libAfterBase/aslist.h"
53
54 #include "../../libAfterConf/afterconf.h"
55
56 /**********************************************************************/
57 /* ARRANGE local variables : */
58 /**********************************************************************/
59 #define ARRANGE_Untitled (0x01<<0)
60 #define ARRANGE_Transient (0x01<<1)
61 #define ARRANGE_Sticky (0x01<<2)
62 #define ARRANGE_Maximized (0x01<<3)
63 #define ARRANGE_All (ARRANGE_Untitled|ARRANGE_Transient| \
64 ARRANGE_Sticky|ARRANGE_Maximized| ARRANGE_WinlistSkip)
65 #define ARRANGE_Reversed (0x01<<4)
66 #define ARRANGE_Desk (0x01<<5)
67 #define ARRANGE_FlatX (0x01<<6)
68 #define ARRANGE_FlatY (0x01<<7)
69 #define ARRANGE_IncX (0x01<<8)
70 #define ARRANGE_IncY (0x01<<9)
71 #define ARRANGE_NoRaise (0x01<<10)
72 #define ARRANGE_NoStretch (0x01<<11)
73 #define ARRANGE_Resize (0x01<<12)
74 #define ARRANGE_Tile (0x01<<13)
75 #define ARRANGE_OffsetX_Set (0x01<<14)
76 #define ARRANGE_OffsetY_Set (0x01<<15)
77 #define ARRANGE_MaxWidth_Set (0x01<<16)
78 #define ARRANGE_MaxHeight_Set (0x01<<17)
79 #define ARRANGE_Tile_Horizontally (0x01<<18)
80 #define ARRANGE_AllDesks (0x01<<19)
81 #define ARRANGE_WinlistSkip (0x01<<20)
82 #define ARRANGE_SmartTile (0x01<<21)
83
84 struct ASArrangeState
85 {
86 ASFlagType flags ;
87 int incx, incy ;
88 int count ;
89
90 int offset_x, offset_y ;
91 int max_width, max_height ;
92
93 int curr_x, curr_y ;
94
95 int *elem, *group;
96 int *elem_size, *group_size; /* in pixels */
97 int start_elem; /* position of start_elem */
98
99 int tile_width, tile_height;
100
101 char *pattern;
102
103 ASBiDirList *clients_order;
104
105 }ArrangeState;
106
107 typedef struct
108 {
109 Window cl;
110 }client_item;
111
112 /**********************************************************************/
113 /**********************************************************************/
114 /* Our configuration options : */
115 /**********************************************************************/
116
117 /**********************************************************************/
118 void GetBaseOptions (const char *filename);
119 void HandleEvents();
120 void process_message (send_data_type type, send_data_type *body);
121 void tile_windows();
122 void cascade_windows();
123 void Arrange_DeadPipe(int);
124
125 int
atopixel(char * s,int size)126 atopixel (char *s, int size)
127 {
128 int l = strlen (s);
129 if (l < 1)
130 return 0;
131 if (s[l-1] == 'p' || s[l-1] == 'P' )
132 {
133 /* number was followed by a p/P
134 * => number was already a pixel-value */
135 s[l-1] = '\0' ;
136 return atoi (s);
137 }
138 /* return s percent of size */
139 return (atoi (s) * size) / 100;
140 }
141
142 void
select_suitable_windows(void)143 select_suitable_windows(void)
144 {
145
146 /* Select all windows, then get
147 * rid of those we don't want. */
148 select_all( False );
149
150 LOCAL_DEBUG_OUT("# Number of selected windows: %d\n", num_selected_windows());
151
152 /* we don't want to arrange fullscreen-windows */
153 select_windows_by_flag( AS_Fullscreen, True);
154 /* we do not want to arrange AfterSTep's modules */
155
156 select_windows_by_flag( AS_Module, True);
157 LOCAL_DEBUG_OUT("# Number of selected windows: %d\n", num_selected_windows());
158
159 /* also we do not want to arrange AvoidCover windows : */
160 select_windows_by_flag(AS_AvoidCover, True);
161
162 /* Remove winlist-skip-windows if user doesn't want to
163 arrange them */
164 if( !get_flags( ArrangeState.flags, ARRANGE_WinlistSkip))
165 select_windows_by_flag(AS_SkipWinList, True);
166
167 LOCAL_DEBUG_OUT("# Number of selected windows: %d\n", num_selected_windows());
168
169 /* return if window is untitled and we don't want
170 to arrange untitled windows */
171 if( !get_flags( ArrangeState.flags, ARRANGE_Untitled ))
172 select_untitled_windows(True);
173
174 LOCAL_DEBUG_OUT("# Number of selected windows: %d\n", num_selected_windows());
175
176 /* return if window is transient and we don't want
177 to arrange transient windows. */
178 if( !get_flags( ArrangeState.flags, ARRANGE_Transient ))
179 select_windows_by_flag(AS_Transient, True);
180
181 LOCAL_DEBUG_OUT("# Number of selected windows: %d\n", num_selected_windows());
182
183 /* return if window is sticky and we don't want
184 to arrange sticky windows. */
185 if( !get_flags( ArrangeState.flags, ARRANGE_Sticky ))
186 select_windows_by_state_flag(AS_Sticky, True);
187 LOCAL_DEBUG_OUT("# Number of selected windows: %d\n", num_selected_windows());
188
189
190 /*return if window is maximized and we don't want
191 to arrange maximized windows. */
192
193 if( !get_flags( ArrangeState.flags, ARRANGE_Maximized ))
194 select_windows_by_state_flag(AS_MaximizedX|AS_MaximizedY|AS_Fullscreen, True);
195
196 LOCAL_DEBUG_OUT("# Number of selected windows: %d\n", num_selected_windows());
197
198 /* return if window is not on current desk and we don't want
199 to arrange windows of all desks. */
200 if( !get_flags( ArrangeState.flags, ARRANGE_AllDesks))
201 {
202 select_windows_on_desk(False);
203
204 /* if user passed ARRANGE_AllDesks, it's safe to assume
205 * he wants to arrange on all screens as well, so we
206 * only check for ARRANGE_Desk if AllDesks was not set */
207
208 /* return if window is not on current screen and we don't want
209 to arrange windows on the whole desk. */
210 if( !get_flags( ArrangeState.flags, ARRANGE_Desk))
211 select_windows_on_screen(False);
212 }
213
214 LOCAL_DEBUG_OUT("# Number of selected windows: %d\n", num_selected_windows());
215
216 /* If a pattern was specified, only select windows matching the pattern*/
217 if( ArrangeState.pattern )
218 select_windows_by_pattern(ArrangeState.pattern, False, False);
219
220 }
221
222
223 int
main(int argc,char ** argv)224 main( int argc, char **argv )
225 {
226 int i ;
227 int nargc = 0 ;
228 XRectangle *area;
229 Bool resize_touched = False;
230 /* Save our program name - for error messages */
231 set_DeadPipe_handler(Arrange_DeadPipe);
232 InitMyApp (CLASS_ARRANGE, argc, argv, NULL, NULL, OPTION_SINGLE|OPTION_RESTART );
233 set_signal_handler( SIGSEGV );
234 ConnectX( ASDefaultScr, 0 );
235
236 memset( &ArrangeState, 0x00, sizeof(ArrangeState));
237
238
239 /* Set some sane default values if still unset */
240
241 ArrangeState.max_width = Scr.MyDisplayWidth ;
242 ArrangeState.max_height = Scr.MyDisplayHeight ;
243 ArrangeState.incx = 20 ;
244 ArrangeState.incy = 20 ;
245
246
247 /* Check the Name of the Program to see wether to tile or cascade*/
248 if( mystrcasecmp( MyName , "Tile" ) == 0 )
249 {
250 set_flags( ArrangeState.flags, ARRANGE_Tile );
251 set_flags( ArrangeState.flags, ARRANGE_Resize);
252 }
253
254 for( i = 1 ; i< argc ; ++i)
255 {
256 if( argv[i] == NULL )
257 continue;
258 /*
259 From manpage of old Cascade:
260 Up to four numbers can be placed in the command line
261 that are not switches.
262 The first pair specify an x and y offset to start
263 the first window (default 0, 0). The second pair
264 specify a maximal width and height for layered windows.
265 */
266 if( isdigit( argv[i][0] ) )
267 {
268 if( nargc == 0 )
269 {
270 ArrangeState.offset_x = atopixel( argv[i], Scr.MyDisplayWidth );
271 set_flags( ArrangeState.flags, ARRANGE_OffsetX_Set );
272 }else if( nargc == 1 )
273 {
274 ArrangeState.offset_y = atopixel( argv[i], Scr.MyDisplayHeight );
275 set_flags( ArrangeState.flags, ARRANGE_OffsetY_Set );
276 }else if( nargc == 2 )
277 {
278 ArrangeState.max_width = atopixel( argv[i], Scr.MyDisplayWidth );
279 set_flags( ArrangeState.flags, ARRANGE_MaxWidth_Set );
280 }else if( nargc == 3 )
281 {
282 ArrangeState.max_height = atopixel( argv[i], Scr.MyDisplayHeight );
283 set_flags( ArrangeState.flags, ARRANGE_MaxHeight_Set );
284 }
285 ++nargc ;
286 }else if( argv[i][0] == '-' )
287 {
288 if( argv[i][1] == '\0' )
289 continue;
290 else if( argv[i][2] == '\0' )
291 {
292 switch( argv[i][1] )
293 {
294 case 'u' : /* Causes untitled windows to also be affected (implied by \-all). */
295 set_flags( ArrangeState.flags, ARRANGE_Untitled );
296 break ;
297 case 't' : /* Causes transient windows to also be affected (implied by \-all). */
298 set_flags( ArrangeState.flags, ARRANGE_Transient );
299 break ;
300 case 's' : /* Causes sticky windows to also be affected (implied by \-all). */
301 set_flags( ArrangeState.flags, ARRANGE_Sticky );
302 break ;
303 case 'm' : /* Causes maximized windows to also be affected (implied by \-all). */
304 set_flags( ArrangeState.flags, ARRANGE_Maximized );
305 break ;
306 case 'a' : /* Causes \fIall\fP window styles to be affected, even ones with the WindowListSkip style. */
307 set_flags( ArrangeState.flags, ARRANGE_All );
308 break ;
309 case 'r' : /* Reverses the window sequence. */
310 set_flags( ArrangeState.flags, ARRANGE_Reversed );
311 break ;
312
313 case 'H': /* For tiling: Tile horizontally (Default is vertically ) */
314
315 set_flags( ArrangeState.flags, ARRANGE_Tile_Horizontally );
316 break;
317 }
318 }else if( mystrcasecmp( argv[i], "-desk" ) == 0 )
319 {
320 /* Causes all windows on the desk to be cascaded instead of the current screen only. */
321 set_flags( ArrangeState.flags, ARRANGE_Desk );
322 }else if( mystrcasecmp( argv[i], "-alldesks") == 0)
323 {
324 set_flags(ArrangeState.flags, ARRANGE_AllDesks);
325 }
326 else if( mystrcasecmp( argv[i], "-flatx" ) == 0 )
327 {
328 /* Inhibits border width increment. */
329 set_flags( ArrangeState.flags, ARRANGE_FlatX );
330 }else if( mystrcasecmp( argv[i], "-flaty" ) == 0 )
331 {
332 /* Inhibits border height increment. */
333 set_flags( ArrangeState.flags, ARRANGE_FlatY );
334 }else if( mystrcasecmp( argv[i], "-incx" ) == 0 && i+1 < argc && argv[i+1] != NULL )
335 {
336 /* Specifies a horizontal increment which is successively added to
337 cascaded windows. \fIarg\fP is a percentage of screen width, or pixel
338 value if a \fIp\fP is suffixed. Default is zero.
339 */
340 ++i ;
341 ArrangeState.incx = atopixel (argv[i], Scr.MyDisplayWidth);
342 set_flags( ArrangeState.flags, ARRANGE_IncX );
343 }else if( mystrcasecmp( argv[i], "-incy" ) == 0 && i+1 < argc && argv[i+1] != NULL )
344 {
345 /* Specifies a vertical increment which is successively added to cascaded
346 windows. \fIarg\fP is a percentage of screen height, or pixel value
347 if a \fIp\fP is suffixed. Default is zero.
348 */
349 ++i ;
350 ArrangeState.incy = atopixel (argv[i], Scr.MyDisplayHeight);
351 set_flags( ArrangeState.flags, ARRANGE_IncY );
352 }else if( mystrcasecmp( argv[i], "-noraise" ) == 0 )
353 {
354 /* Inhibits window raising, leaving the depth ordering intact. */
355 set_flags( ArrangeState.flags, ARRANGE_NoRaise );
356 }else if( mystrcasecmp( argv[i], "-nostretch" ) == 0 )
357 {
358 /* Inhibits window expansion when using the \-resize option. Windows
359 will only shrink to fit the maximal width and height (if given).
360 */
361 set_flags( ArrangeState.flags, ARRANGE_NoStretch );
362 }else if( mystrcasecmp( argv[i], "-resize" ) == 0 )
363 {
364 /* Forces all windows to resize to the constrained width and height (if given). */
365 set_flags( ArrangeState.flags, ARRANGE_Resize );
366 resize_touched = True;
367 }else if( mystrcasecmp( argv[i], "-noresize") == 0)
368 {
369 clear_flags( ArrangeState.flags, ARRANGE_Resize );
370 resize_touched = True;
371 }else if( mystrcasecmp( argv[i], "-tile") == 0 )
372 {
373 set_flags( ArrangeState.flags, ARRANGE_Tile );
374 if(! resize_touched )
375 set_flags(ArrangeState.flags, ARRANGE_Resize );
376 }
377 else if( mystrcasecmp( argv[i], "-smart") == 0)
378 {
379 set_flags(ArrangeState.flags, ARRANGE_SmartTile);
380 }else if( mystrcasecmp( argv[i], "-pattern") == 0 && i+1 <argc && argv[i+1] != NULL)
381 {
382 ArrangeState.pattern = argv[i+1];
383 }
384 /* these apply to tiling only : */
385 else if( mystrcasecmp( argv[i], "-mn") == 0 && i+1 < argc )
386 {
387 /* Tiles up to \fIarg\fP windows in tile direction. If more windows
388 exist, a new direction row or column is created (in effect, a matrix is created).
389 */
390 ++i ;
391 ArrangeState.count = atoi( argv[i] );
392 }
393
394 }
395 }
396
397 ascom_init();
398 /* Request a list of all windows, while we load our config */
399 ascom_update_winlist();
400
401 LoadBaseConfig ( GetBaseOptions);
402
403 /* fix area */
404 area = ascom_get_available_area();
405
406 if( !get_flags( ArrangeState.flags, ARRANGE_OffsetX_Set ) )
407 ArrangeState.offset_x = area->x;
408
409 if( !get_flags( ArrangeState.flags, ARRANGE_OffsetY_Set ) )
410 ArrangeState.offset_y = area->y;
411
412 if( !get_flags( ArrangeState.flags, ARRANGE_MaxWidth_Set ) )
413 ArrangeState.max_width = area->width;
414
415 if( !get_flags( ArrangeState.flags, ARRANGE_MaxHeight_Set ) )
416 ArrangeState.max_height = area->height;
417
418 free(area);
419
420 /************/
421
422 select_suitable_windows();
423
424 /* rearrange windows */
425
426 if( get_flags( ArrangeState.flags, ARRANGE_Tile ) )
427 tile_windows();
428 else
429 cascade_windows();
430
431 ascom_wait();
432 ascom_deinit();
433
434 /* exit */
435 Arrange_DeadPipe (0);
436
437 return 0 ;
438 }
439
440
441 void
Arrange_DeadPipe(int nonsense)442 Arrange_DeadPipe (int nonsense)
443 {
444 static int already_dead = False ;
445 if( already_dead )
446 return;/* non-reentrant function ! */
447 already_dead = True ;
448
449 window_data_cleanup();
450
451 FreeMyAppResources();
452
453 #ifdef DEBUG_ALLOCS
454 print_unfreed_mem ();
455 #endif /* DEBUG_ALLOCS */
456
457 XFlush (dpy); /* need this for SetErootPixmap to take effect */
458 XCloseDisplay (dpy); /* need this for SetErootPixmap to take effect */
459 exit (0);
460 }
461
462 void
GetBaseOptions(const char * filename)463 GetBaseOptions (const char *filename)
464 {
465 ReloadASEnvironment( NULL, NULL, NULL, False, False );
466 }
467
468
469 /********************************************************************/
470 /* showing our main window : */
471 /********************************************************************/
472
473 void
tile_windows()474 tile_windows()
475 {
476 int n_groups;
477 int n_windows = num_selected_windows();
478 Bool reverse = get_flags(ArrangeState.flags, ARRANGE_Reversed);
479
480 LOCAL_DEBUG_OUT("Number of windows to be arranged: %d\n", n_windows);
481 LOCAL_DEBUG_OUT("max_width/max_height: %d/%d\n", ArrangeState.max_width, ArrangeState.max_height);
482
483 /* If number of elements per group was not set */
484 if(ArrangeState.count == 0)
485 {
486 if( ! get_flags(ArrangeState.flags, ARRANGE_SmartTile) )
487 ArrangeState.count = n_windows; /*Put all elements in one group*/
488 else
489 ArrangeState.count = (int) sqrt(n_windows);
490 }
491 n_groups = n_windows / ArrangeState.count;
492 /* If not all windows fit in n_groups groups, an
493 * extra group for remaining windows is needed.*/
494 if(n_windows % ArrangeState.count)
495 n_groups++;
496
497 LOCAL_DEBUG_OUT("ngroups: %d", n_groups);
498
499 ArrangeState.curr_x = ArrangeState.offset_x ;
500 ArrangeState.curr_y = ArrangeState.offset_y ;
501
502 LOCAL_DEBUG_OUT("curr_x/curr_y: %d/%d\n", ArrangeState.curr_x, ArrangeState.curr_y);
503
504 if(get_flags( ArrangeState.flags, ARRANGE_Tile_Horizontally))
505 {
506 ArrangeState.start_elem = ArrangeState.curr_x;
507 ArrangeState.elem = &ArrangeState.curr_x;
508 ArrangeState.group = &ArrangeState.curr_y;
509
510 ArrangeState.tile_width =
511 ArrangeState.max_width / ArrangeState.count;
512 ArrangeState.tile_height =
513 ArrangeState.max_height/ n_groups ;
514
515 ArrangeState.elem_size = &ArrangeState.tile_width;
516 ArrangeState.group_size = &ArrangeState.tile_height;
517
518 }else
519 {
520 ArrangeState.start_elem = ArrangeState.curr_y;
521 ArrangeState.elem = &ArrangeState.curr_y;
522 ArrangeState.group = &ArrangeState.curr_x;
523
524 ArrangeState.tile_width =
525 ArrangeState.max_width / n_groups;
526 ArrangeState.tile_height =
527 ArrangeState.max_height / ArrangeState.count ;
528
529 ArrangeState.elem_size = &ArrangeState.tile_height;
530 ArrangeState.group_size = &ArrangeState.tile_width ;
531 }
532
533 while(! winlist_is_empty() )
534 {
535 move_params p;
536 const ASWindowData *wd;
537
538 /* If group is full */
539 if(*(ArrangeState.elem) ==
540 (ArrangeState.start_elem +
541 ArrangeState.count * *(ArrangeState.elem_size)))
542 {
543 /* Make new group */
544 *(ArrangeState.group)+= *(ArrangeState.group_size);
545 /* Make this the first item of the new group */
546 *(ArrangeState.elem) = ArrangeState.start_elem;
547 }
548
549
550 /* Raise the client if allowed */
551 if( !get_flags( ArrangeState.flags, ARRANGE_NoRaise ) )
552 ascom_do_one("raise", NULL, reverse);
553
554
555 /* If the client is iconified, deiconify it. */
556 ascom_do_one("deiconify", NULL, reverse);
557
558 p.x = ArrangeState.curr_x;
559 p.y = ArrangeState.curr_y;
560
561 /* Move window */
562 ascom_do_one("move", &p, reverse);
563
564 wd = ascom_get_next_window( reverse );
565
566 /* Make sure we don't stretch if ARRANGE_NoStretch was set */
567 if ( !( get_flags( ArrangeState.flags, ARRANGE_NoStretch) &&
568 ( (wd->frame_rect.width < ArrangeState.tile_width)
569 || (wd->frame_rect.height < ArrangeState.tile_height)
570 )))
571 {
572 resize_params rparams;
573 rparams.width = ArrangeState.tile_width ;
574 rparams.height = ArrangeState.tile_height ;
575 /* Resize window if allowed*/
576 if( get_flags(ArrangeState.flags, ARRANGE_Resize ))
577 ascom_do_one("resize", &rparams, reverse);
578 }
579
580
581 /* Transfer window onto CurrentDesk */
582 if( wd->desk != Scr.CurrentDesk )
583 {
584 send_to_desk_params p;
585 p.desk = Scr.CurrentDesk;
586 LOCAL_DEBUG_OUT("#CurrentDesk: %d", Scr.CurrentDesk);
587
588 ascom_do_one("sendtodesk", &p, reverse);
589 }
590
591 (*(ArrangeState.elem))+= *ArrangeState.elem_size;
592
593 ascom_pop_winlist(reverse);
594 }
595
596 }
597
598 /* Cascade */
599
600 void
cascade_windows()601 cascade_windows()
602 {
603
604 ArrangeState.curr_x = ArrangeState.offset_x ;
605 ArrangeState.curr_y = ArrangeState.offset_y ;
606
607
608 while( !winlist_is_empty() )
609 {
610 move_params p;
611 const ASWindowData *wd;
612 Bool reverse = get_flags(ArrangeState.flags, ARRANGE_Reversed);
613
614 /* Raise the client if allowed */
615 if( !get_flags( ArrangeState.flags, ARRANGE_NoRaise ) )
616 ascom_do_one("raise", NULL, reverse);
617
618
619 /* If the client is iconified, deiconify it. */
620 ascom_do_one("deiconify", NULL, reverse);
621
622 /* move window */
623 p.x = ArrangeState.curr_x;
624 p.y = ArrangeState.curr_y;
625 ascom_do_one("move", &p, reverse);
626
627 ArrangeState.curr_x += ArrangeState.incx ;
628 ArrangeState.curr_y += ArrangeState.incy ;
629
630 wd = ascom_get_next_window(reverse);
631
632 if( get_flags( ArrangeState.flags, ARRANGE_Resize ) )
633 {
634 /* Make sure we don't stretch of ARRANGE_NoStretch was set */
635 if ( !( get_flags( ArrangeState.flags, ARRANGE_NoStretch) &&
636 ( (wd->frame_rect.width < ArrangeState.max_width)
637 || (wd->frame_rect.height < ArrangeState.max_height)
638 )))
639 {
640 resize_params rp;
641 rp.width = ArrangeState.max_width ;
642 rp.height = ArrangeState.max_height ;
643 if( get_flags( ArrangeState.flags, ARRANGE_Resize) )
644 ascom_do_one("resize", &rp, reverse);
645 }
646 }
647
648 /* Transfer window onto CurrentDesk */
649 if( wd->desk != Scr.CurrentDesk )
650 {
651 send_to_desk_params p;
652 p.desk = Scr.CurrentDesk;
653
654 ascom_do_one("sendtodesk", &p, reverse);
655 }
656
657
658 ascom_pop_winlist(reverse);
659 }
660
661 }
662