2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 /* ---------------------------- included header files ---------------------- */
23 #include "libs/fvwmlib.h"
24 #include "libs/charmap.h"
25 #include "libs/wcontext.h"
28 #include "execcontext.h"
32 #include "module_interface.h"
35 #include "add_window.h"
37 /* ---------------------------- local definitions -------------------------- */
39 /* ---------------------------- local macros ------------------------------- */
41 /* ---------------------------- imports ------------------------------------ */
43 /* ---------------------------- included code files ------------------------ */
45 /* ---------------------------- local types -------------------------------- */
47 /* ---------------------------- forward declarations ----------------------- */
49 /* ---------------------------- local variables ---------------------------- */
51 /* ---------------------------- exported variables (globals) --------------- */
53 /* ---------------------------- local functions ---------------------------- */
55 /* ---------------------------- interface functions ------------------------ */
57 /* Removes decorations from the source rectangle and moves it according to the
58 * gravity specification. */
59 void gravity_get_naked_geometry(
60 int gravity
, FvwmWindow
*t
, rectangle
*dest_g
, rectangle
*orig_g
)
66 get_window_borders(t
, &b
);
67 gravity_get_offsets(gravity
, &xoff
, &yoff
);
68 dest_g
->x
= orig_g
->x
+ ((xoff
+ 1) * (orig_g
->width
- 1)) / 2;
69 dest_g
->y
= orig_g
->y
+ ((yoff
+ 1) * (orig_g
->height
- 1)) / 2;
70 dest_g
->width
= orig_g
->width
- b
.total_size
.width
;
71 dest_g
->height
= orig_g
->height
- b
.total_size
.height
;
76 /* Decorate the rectangle. Resize and shift it according to gravity. */
77 void gravity_add_decoration(
78 int gravity
, FvwmWindow
*t
, rectangle
*dest_g
, rectangle
*orig_g
)
82 get_window_borders(t
, &b
);
85 gravity
, dest_g
, b
.total_size
.width
, b
.total_size
.height
);
90 void get_relative_geometry(rectangle
*rel_g
, rectangle
*abs_g
)
92 rel_g
->x
= abs_g
->x
- Scr
.Vx
;
93 rel_g
->y
= abs_g
->y
- Scr
.Vy
;
94 rel_g
->width
= abs_g
->width
;
95 rel_g
->height
= abs_g
->height
;
100 void get_absolute_geometry(rectangle
*abs_g
, rectangle
*rel_g
)
102 abs_g
->x
= rel_g
->x
+ Scr
.Vx
;
103 abs_g
->y
= rel_g
->y
+ Scr
.Vy
;
104 abs_g
->width
= rel_g
->width
;
105 abs_g
->height
= rel_g
->height
;
110 void gravity_translate_to_northwest_geometry(
111 int gravity
, FvwmWindow
*t
, rectangle
*dest_g
, rectangle
*orig_g
)
116 gravity_get_offsets(gravity
, &xoff
, &yoff
);
117 dest_g
->x
= orig_g
->x
-
118 ((xoff
+ 1) * (orig_g
->width
- 1 +
119 2 * t
->attr_backup
.border_width
)) / 2;
120 dest_g
->y
= orig_g
->y
-
121 ((yoff
+ 1) * (orig_g
->height
- 1 +
122 2 * t
->attr_backup
.border_width
)) / 2;
123 dest_g
->width
= orig_g
->width
;
124 dest_g
->height
= orig_g
->height
;
129 void gravity_translate_to_northwest_geometry_no_bw(
130 int gravity
, FvwmWindow
*t
, rectangle
*dest_g
, rectangle
*orig_g
)
132 int bw
= t
->attr_backup
.border_width
;
134 t
->attr_backup
.border_width
= 0;
135 gravity_translate_to_northwest_geometry(gravity
, t
, dest_g
, orig_g
);
136 t
->attr_backup
.border_width
= bw
;
141 void get_title_geometry(
142 FvwmWindow
*fw
, rectangle
*ret_g
)
149 get_window_borders(fw
, &b
);
150 get_window_borders_no_title(fw
, &nt
);
151 w
= (ret_g
->width
> 0) ? ret_g
->width
: fw
->g
.frame
.width
;
152 h
= (ret_g
->height
> 0) ? ret_g
->height
: fw
->g
.frame
.height
;
153 ret_g
->x
= nt
.top_left
.width
;
154 ret_g
->y
= nt
.top_left
.height
;
155 switch (GET_TITLE_DIR(fw
))
158 ret_g
->y
= h
- b
.bottom_right
.height
;
161 ret_g
->width
= w
- b
.total_size
.width
;
162 ret_g
->height
= fw
->title_thickness
;
165 ret_g
->x
= w
- b
.bottom_right
.width
;
168 ret_g
->width
= fw
->title_thickness
;
169 ret_g
->height
= h
- b
.total_size
.height
;
178 void get_title_gravity_factors(
179 FvwmWindow
*fw
, int *ret_fx
, int *ret_fy
)
181 switch (GET_TITLE_DIR(fw
))
204 Bool
get_title_button_geometry(
205 FvwmWindow
*fw
, rectangle
*ret_g
, int context
)
209 if (context
& C_TITLE
)
213 get_title_geometry(fw
, ret_g
);
214 ret_g
->x
+= fw
->g
.frame
.x
;
215 ret_g
->y
+= fw
->g
.frame
.y
;
220 bnum
= get_button_number(context
);
221 if (bnum
< 0 || FW_W_BUTTON(fw
, bnum
) == None
)
226 dpy
, FW_W_BUTTON(fw
, bnum
), &JunkRoot
, &ret_g
->x
, &ret_g
->y
,
227 (unsigned int*)&ret_g
->width
, (unsigned int*)&ret_g
->height
,
228 (unsigned int*)&JunkBW
, (unsigned int*)&JunkDepth
) == 0)
232 XTranslateCoordinates(
233 dpy
, FW_W_FRAME(fw
), Scr
.Root
, ret_g
->x
, ret_g
->y
, &ret_g
->x
,
234 &ret_g
->y
, &JunkChild
);
239 void get_title_font_size_and_offset(
240 FvwmWindow
*fw
, direction_t title_dir
,
241 Bool is_left_title_rotated_cw
, Bool is_right_title_rotated_cw
,
242 Bool is_top_title_rotated
, Bool is_bottom_title_rotated
,
243 int *size
, int *offset
)
249 Bool is_rotated_cw
, is_rotated
;
250 rotation_t draw_rotation
;
252 /* adjust font offset according to height specified in title style */
253 decor_size
= fw
->decor
->title_height
;
254 font_size
= fw
->title_font
->height
+ EXTRA_TITLE_FONT_HEIGHT
;
259 is_rotated_cw
= (title_dir
== DIR_W
) ?
260 is_left_title_rotated_cw
: is_right_title_rotated_cw
;
263 fw
->title_text_rotation
= ROTATION_90
;
267 fw
->title_text_rotation
= ROTATION_270
;
273 is_rotated
= (title_dir
== DIR_N
) ?
274 is_top_title_rotated
: is_bottom_title_rotated
;
277 fw
->title_text_rotation
= ROTATION_180
;
281 fw
->title_text_rotation
= ROTATION_0
;
285 if (USE_TITLE_DECOR_ROTATION(fw
))
287 draw_rotation
= ROTATION_0
;
291 draw_rotation
= fw
->title_text_rotation
;
293 min_offset
= FlocaleGetMinOffset(
294 fw
->title_font
, draw_rotation
);
295 extra_size
= (decor_size
> 0) ? decor_size
- font_size
: 0;
296 *offset
= min_offset
;
297 if (fw
->decor
->min_title_height
> 0 &&
298 font_size
+ extra_size
< fw
->decor
->min_title_height
)
300 extra_size
= fw
->decor
->min_title_height
- font_size
;
304 *offset
+= extra_size
/ 2;
306 *size
= font_size
+ extra_size
;
311 void get_icon_corner(
312 FvwmWindow
*fw
, rectangle
*ret_g
)
314 switch (GET_TITLE_DIR(fw
))
318 ret_g
->x
= fw
->g
.frame
.x
;
319 ret_g
->y
= fw
->g
.frame
.y
;
322 ret_g
->x
= fw
->g
.frame
.x
;
323 ret_g
->y
= fw
->g
.frame
.y
+ fw
->g
.frame
.height
-
327 ret_g
->x
= fw
->g
.frame
.x
+ fw
->g
.frame
.width
-
329 ret_g
->y
= fw
->g
.frame
.y
;
336 void get_shaded_geometry(
337 FvwmWindow
*fw
, rectangle
*small_g
, rectangle
*big_g
)
340 /* this variable is necessary so the function can be called with
341 * small_g == big_g */
342 int big_width
= big_g
->width
;
343 int big_height
= big_g
->height
;
346 get_window_borders(fw
, &b
);
349 switch (SHADED_DIR(fw
))
354 small_g
->y
= big_g
->y
+ big_height
- b
.total_size
.height
;
360 small_g
->height
= b
.total_size
.height
;
361 if (small_g
->height
== 0)
371 switch (SHADED_DIR(fw
))
376 small_g
->x
= big_g
->x
+ big_width
- b
.total_size
.width
;
382 small_g
->width
= b
.total_size
.width
;
383 if (small_g
->width
== 0)
396 void get_shaded_geometry_with_dir(
397 FvwmWindow
*fw
, rectangle
*small_g
, rectangle
*big_g
,
398 direction_t shade_dir
)
400 direction_t old_shade_dir
;
402 old_shade_dir
= SHADED_DIR(fw
);
403 SET_SHADED_DIR(fw
, shade_dir
);
404 get_shaded_geometry(fw
, small_g
, big_g
);
405 SET_SHADED_DIR(fw
, old_shade_dir
);
410 void get_unshaded_geometry(
411 FvwmWindow
*fw
, rectangle
*ret_g
)
415 if (IS_MAXIMIZED(fw
))
421 *ret_g
= fw
->g
.normal
;
423 get_relative_geometry(ret_g
, ret_g
);
427 *ret_g
= fw
->g
.frame
;
433 void get_shaded_client_window_pos(
434 FvwmWindow
*fw
, rectangle
*ret_g
)
439 get_window_borders(fw
, &b
);
440 big_g
= (IS_MAXIMIZED(fw
)) ? fw
->g
.max
: fw
->g
.normal
;
441 get_relative_geometry(&big_g
, &big_g
);
442 switch (SHADED_DIR(fw
))
447 ret_g
->y
= 1 - big_g
.height
+ b
.total_size
.height
;
453 switch (SHADED_DIR(fw
))
458 ret_g
->x
= 1 - big_g
.width
+ b
.total_size
.width
;
468 /* returns the dimensions of the borders */
469 void get_window_borders(
470 const FvwmWindow
*fw
, size_borders
*borders
)
472 borders
->top_left
.width
= fw
->boundary_width
;
473 borders
->bottom_right
.width
= fw
->boundary_width
;
474 borders
->top_left
.height
= fw
->boundary_width
;
475 borders
->bottom_right
.height
= fw
->boundary_width
;
476 switch (GET_TITLE_DIR(fw
))
479 borders
->top_left
.height
+= fw
->title_thickness
;
482 borders
->bottom_right
.height
+= fw
->title_thickness
;
485 borders
->top_left
.width
+= fw
->title_thickness
;
488 borders
->bottom_right
.width
+= fw
->title_thickness
;
491 borders
->total_size
.width
=
492 borders
->top_left
.width
+ borders
->bottom_right
.width
;
493 borders
->total_size
.height
=
494 borders
->top_left
.height
+ borders
->bottom_right
.height
;
499 /* returns the dimensions of the borders without the title */
500 void get_window_borders_no_title(
501 const FvwmWindow
*fw
, size_borders
*borders
)
503 borders
->top_left
.width
= fw
->boundary_width
;
504 borders
->bottom_right
.width
= fw
->boundary_width
;
505 borders
->top_left
.height
= fw
->boundary_width
;
506 borders
->bottom_right
.height
= fw
->boundary_width
;
507 borders
->total_size
.width
=
508 borders
->top_left
.width
+ borders
->bottom_right
.width
;
509 borders
->total_size
.height
=
510 borders
->top_left
.height
+ borders
->bottom_right
.height
;
515 void set_window_border_size(
516 FvwmWindow
*fw
, int used_width
)
520 fw
->boundary_width
= 0;
521 fw
->unshaped_boundary_width
= 0;
525 fw
->unshaped_boundary_width
= used_width
;
526 fw
->boundary_width
= (fw
->wShaped
) ? 0 : used_width
;
532 /* Returns True if all window borders are only 1 pixel thick (or less). */
533 Bool
is_window_border_minimal(
538 get_window_borders_no_title(fw
, &nt
);
539 if (nt
.top_left
.width
> 1 || nt
.top_left
.height
> 1 ||
540 nt
.bottom_right
.width
> 1 || nt
.bottom_right
.height
> 1)
549 /* This function returns the geometry of the client window. If the window is
550 * shaded, the unshaded geometry is used instead. */
551 void get_client_geometry(
552 FvwmWindow
*fw
, rectangle
*ret_g
)
554 size_borders borders
;
556 get_unshaded_geometry(fw
, ret_g
);
557 get_window_borders(fw
, &borders
);
558 ret_g
->x
+= borders
.top_left
.width
;
559 ret_g
->y
+= borders
.top_left
.height
;
560 ret_g
->width
-= borders
.total_size
.width
;
561 ret_g
->height
-= borders
.total_size
.height
;
566 /* update the frame_g according to the window's g.normal or g.max and shaded
568 void update_relative_geometry(FvwmWindow
*fw
)
570 get_relative_geometry(
572 (IS_MAXIMIZED(fw
)) ? &fw
->g
.max
: &fw
->g
.normal
);
576 fw
, &fw
->g
.frame
, &fw
->g
.frame
);
582 /* update the g.normal or g.max according to the window's current position */
583 void update_absolute_geometry(FvwmWindow
*fw
)
588 /* store orig values in absolute coords */
589 dest_g
= (IS_MAXIMIZED(fw
)) ? &fw
->g
.max
: &fw
->g
.normal
;
591 dest_g
->x
= fw
->g
.frame
.x
+ Scr
.Vx
;
592 dest_g
->y
= fw
->g
.frame
.y
+ Scr
.Vy
;
593 dest_g
->width
= fw
->g
.frame
.width
;
594 dest_g
->height
= fw
->g
.frame
.height
;
597 switch (SHADED_DIR(fw
))
602 dest_g
->y
+= fw
->g
.frame
.height
- frame_g
.height
;
607 dest_g
->height
= frame_g
.height
;
610 switch (SHADED_DIR(fw
))
615 dest_g
->x
+= fw
->g
.frame
.width
- frame_g
.width
;
620 dest_g
->width
= frame_g
.width
;
628 /* make sure a maximized window and it's normal version are never a page or
630 void maximize_adjust_offset(FvwmWindow
*fw
)
637 if (!IS_MAXIMIZED(fw
))
639 /* otherwise we might corrupt the g.normal */
642 off_x
= fw
->g
.normal
.x
- fw
->g
.max
.x
- fw
->g
.max_offset
.x
;
643 off_y
= fw
->g
.normal
.y
- fw
->g
.max
.y
- fw
->g
.max_offset
.y
;
644 dw
= Scr
.MyDisplayWidth
;
645 dh
= Scr
.MyDisplayHeight
;
648 fw
->g
.normal
.x
-= (off_x
/ dw
) * dw
;
650 else if (off_x
<= -dw
)
652 fw
->g
.normal
.x
+= (-off_x
/ dw
) * dw
;
656 fw
->g
.normal
.y
-= (off_y
/ dh
) * dh
;
658 else if (off_y
<= -dh
)
660 fw
->g
.normal
.y
+= (-off_y
/ dh
) * dh
;
666 #define MAKEMULT(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
667 static void __cs_handle_aspect_ratio(
668 size_rect
*ret_s
, FvwmWindow
*fw
, size_rect s
, const size_rect base
,
669 const size_rect inc
, size_rect min
, size_rect max
, int xmotion
,
670 int ymotion
, int flags
)
672 volatile double odefect
;
673 volatile double defect
;
674 volatile double rmax
;
675 volatile double rmin
;
680 if (fw
->hints
.flags
& PBaseSize
)
683 * ICCCM 2 demands that aspect ratio should apply to width -
684 * base_width. To prevent funny results, we reset PBaseSize in
685 * GetWindowSizeHints, if base is not smaller than min.
687 s
.width
-= base
.width
;
688 max
.width
-= base
.width
;
689 min
.width
-= base
.width
;
690 s
.height
-= base
.height
;
691 max
.height
-= base
.height
;
692 min
.height
-= base
.height
;
694 rmin
= (double)fw
->hints
.min_aspect
.x
/ (double)fw
->hints
.min_aspect
.y
;
695 rmax
= (double)fw
->hints
.max_aspect
.x
/ (double)fw
->hints
.max_aspect
.y
;
700 r
= (double)s
.width
/ (double)s
.height
;
712 if (r
< rmin
&& (flags
& CS_ROUND_UP
) && xmotion
== 0)
714 /* change width to match */
715 delta
= MAKEMULT(s
.height
* rmin
- s
.width
, inc
.width
);
716 if (s
.width
+ delta
<= max
.width
)
720 r
= (double)s
.width
/ (double)s
.height
;
724 /* change height to match */
726 s
.height
- s
.width
/ rmin
, inc
.height
);
727 if (s
.height
- delta
>= min
.height
)
734 s
.height
* rmin
- s
.width
, inc
.width
);
735 if (s
.width
+ delta
<= max
.width
)
740 r
= (double)s
.width
/ (double)s
.height
;
743 if (r
> rmax
&& (flags
& CS_ROUND_UP
) && ymotion
== 0)
745 /* change height to match */
746 delta
= MAKEMULT(s
.width
/rmax
- s
.height
, inc
.height
);
747 if (s
.height
+ delta
<= max
.height
)
751 r
= (double)s
.width
/ (double)s
.height
;
755 /* change width to match */
756 delta
= MAKEMULT(s
.width
- s
.height
* rmax
, inc
.width
);
757 if (s
.width
- delta
>= min
.width
)
764 s
.width
/ rmax
- s
.height
, inc
.height
);
765 if (s
.height
+ delta
<= max
.height
)
770 r
= (double)s
.width
/ (double)s
.height
;
781 } while (odefect
> defect
);
782 if (fw
->hints
.flags
& PBaseSize
)
796 * constrain_size - adjust the given width and height to account for the
797 * constraints imposed by size hints
800 FvwmWindow
*fw
, const XEvent
*e
, int *widthp
, int *heightp
,
801 int xmotion
, int ymotion
, int flags
)
812 if (DO_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw
) == 1)
816 if (HAS_NEW_WM_NORMAL_HINTS(fw
))
818 /* get the latest size hints */
820 GetWindowSizeHints(fw
);
821 SET_HAS_NEW_WM_NORMAL_HINTS(fw
, 0);
823 if (IS_MAXIMIZED(fw
) && (flags
& CS_UPDATE_MAX_DEFECT
))
825 *widthp
+= fw
->g
.max_defect
.width
;
826 *heightp
+= fw
->g
.max_defect
.height
;
828 /* gcc 4.1.1 warns about these not being initialized at the end,
829 * but the conditions for the use are the same...*/
831 old
.height
= *heightp
;
835 get_window_borders(fw
, &b
);
836 d
.width
-= b
.total_size
.width
;
837 d
.height
-= b
.total_size
.height
;
839 min
.width
= fw
->hints
.min_width
;
840 min
.height
= fw
->hints
.min_height
;
841 if (min
.width
< fw
->min_window_width
- b
.total_size
.width
)
843 min
.width
= fw
->min_window_width
- b
.total_size
.width
;
845 if (min
.height
< fw
->min_window_height
- b
.total_size
.height
)
848 fw
->min_window_height
- b
.total_size
.height
;
851 max
.width
= fw
->hints
.max_width
;
852 max
.height
= fw
->hints
.max_height
;
853 if (max
.width
> fw
->max_window_width
- b
.total_size
.width
)
855 max
.width
= fw
->max_window_width
- b
.total_size
.width
;
857 if (max
.height
> fw
->max_window_height
- b
.total_size
.height
)
860 fw
->max_window_height
- b
.total_size
.height
;
863 if (min
.width
> max
.width
)
865 min
.width
= max
.width
;
867 if (min
.height
> max
.height
)
869 min
.height
= max
.height
;
872 base
.width
= fw
->hints
.base_width
;
873 base
.height
= fw
->hints
.base_height
;
875 inc
.width
= fw
->hints
.width_inc
;
876 inc
.height
= fw
->hints
.height_inc
;
879 * First, clamp to min and max values
881 if (d
.width
< min
.width
)
885 if (d
.height
< min
.height
)
887 d
.height
= min
.height
;
889 if (d
.width
> max
.width
)
893 if (d
.height
> max
.height
)
895 d
.height
= max
.height
;
899 * Second, round to base + N * inc (up or down depending on resize
900 * type) if rounding up store amount
902 if (!(flags
& CS_ROUND_UP
))
904 d
.width
= ((d
.width
- base
.width
) / inc
.width
) *
905 inc
.width
+ base
.width
;
906 d
.height
= ((d
.height
- base
.height
) / inc
.height
) *
907 inc
.height
+ base
.height
;
911 round_up
.width
= d
.width
;
912 round_up
.height
= d
.height
;
913 d
.width
= ((d
.width
- base
.width
+ inc
.width
- 1) /
914 inc
.width
) * inc
.width
+ base
.width
;
915 d
.height
= ((d
.height
- base
.height
+ inc
.height
- 1) /
916 inc
.height
) * inc
.height
+ base
.height
;
917 round_up
.width
= d
.width
- round_up
.width
;
918 round_up
.height
= d
.height
- round_up
.height
;
922 * Step 2a: check we didn't move the edge off screen in interactive
925 if ((flags
& CS_ROUND_UP
) && e
!= NULL
&& e
->type
== MotionNotify
)
927 if (xmotion
> 0 && e
->xmotion
.x_root
< round_up
.width
)
929 d
.width
-= inc
.width
;
932 xmotion
< 0 && e
->xmotion
.x_root
>=
933 Scr
.MyDisplayWidth
- round_up
.width
)
935 d
.width
-= inc
.width
;
937 if (ymotion
> 0 && e
->xmotion
.y_root
< round_up
.height
)
939 d
.height
-= inc
.height
;
942 ymotion
< 0 && e
->xmotion
.y_root
>=
943 Scr
.MyDisplayHeight
- round_up
.height
)
945 d
.height
-= inc
.height
;
950 * Step 2b: Check that we didn't violate min and max.
952 if (d
.width
< min
.width
)
954 d
.width
+= inc
.width
;
956 if (d
.height
< min
.height
)
958 d
.height
+= inc
.height
;
960 if (d
.width
> max
.width
)
962 d
.width
-= inc
.width
;
964 if (d
.height
> max
.height
)
966 d
.height
-= inc
.height
;
970 * Third, adjust for aspect ratio
972 if (fw
->hints
.flags
& PAspect
)
974 __cs_handle_aspect_ratio(
975 &d
, fw
, d
, base
, inc
, min
, max
, xmotion
, ymotion
,
980 * Fourth, account for border width and title height
982 *widthp
= d
.width
+ b
.total_size
.width
;
983 *heightp
= d
.height
+ b
.total_size
.height
;
984 if (IS_MAXIMIZED(fw
) && (flags
& CS_UPDATE_MAX_DEFECT
))
986 /* update size defect for maximized window */
987 fw
->g
.max_defect
.width
= old
.width
- *widthp
;
988 fw
->g
.max_defect
.height
= old
.height
- *heightp
;
994 /* This function does roughly the same as constrain_size, but takes into account
995 * that the window shifts according to gravity if constrain_size actually
996 * changes the width or height. The frame_g of the window is not changed. The
997 * target geometry is expected to be in *rect and will be retured through rect.
999 void gravity_constrain_size(
1000 int gravity
, FvwmWindow
*t
, rectangle
*rect
, int flags
)
1002 int new_width
= rect
->width
;
1003 int new_height
= rect
->height
;
1005 if (IS_MAXIMIZED(t
) && (flags
& CS_UPDATE_MAX_DEFECT
))
1008 gravity
, rect
, t
->g
.max_defect
.width
,
1009 t
->g
.max_defect
.height
);
1010 t
->g
.max_defect
.width
= 0;
1011 t
->g
.max_defect
.height
= 0;
1012 new_width
= rect
->width
;
1013 new_height
= rect
->height
;
1016 t
, NULL
, &new_width
, &new_height
, 0, 0, flags
);
1017 if (rect
->width
!= new_width
|| rect
->height
!= new_height
)
1020 gravity
, rect
, new_width
- rect
->width
,
1021 new_height
- rect
->height
);
1027 /* returns the icon title geometry if it is visible */
1028 Bool
get_visible_icon_title_geometry(
1029 FvwmWindow
*fw
, rectangle
*ret_g
)
1031 if (HAS_NO_ICON_TITLE(fw
) || IS_ICON_UNMAPPED(fw
) ||
1034 memset(ret_g
, 0, sizeof(*ret_g
));
1037 *ret_g
= fw
->icon_g
.title_w_g
;
1042 /* returns the icon title geometry if it the icon title window exists */
1043 Bool
get_icon_title_geometry(
1044 FvwmWindow
*fw
, rectangle
*ret_g
)
1046 if (HAS_NO_ICON_TITLE(fw
))
1048 memset(ret_g
, 0, sizeof(*ret_g
));
1051 *ret_g
= fw
->icon_g
.title_w_g
;
1056 /* returns the icon picture geometry if it is visible */
1057 Bool
get_visible_icon_picture_geometry(
1058 FvwmWindow
*fw
, rectangle
*ret_g
)
1060 if (fw
->icon_g
.picture_w_g
.width
== 0 ||
1061 IS_ICON_UNMAPPED(fw
) || !IS_ICONIFIED(fw
))
1063 memset(ret_g
, 0, sizeof(*ret_g
));
1066 *ret_g
= fw
->icon_g
.picture_w_g
;
1071 /* returns the icon picture geometry if it is exists */
1072 Bool
get_icon_picture_geometry(
1073 FvwmWindow
*fw
, rectangle
*ret_g
)
1075 if (fw
->icon_g
.picture_w_g
.width
== 0)
1077 memset(ret_g
, 0, sizeof(*ret_g
));
1080 *ret_g
= fw
->icon_g
.picture_w_g
;
1085 /* returns the icon geometry (unexpanded title plus pixmap) if it is visible */
1086 Bool
get_visible_icon_geometry(
1087 FvwmWindow
*fw
, rectangle
*ret_g
)
1089 if (IS_ICON_UNMAPPED(fw
) || !IS_ICONIFIED(fw
))
1091 memset(ret_g
, 0, sizeof(*ret_g
));
1094 if (fw
->icon_g
.picture_w_g
.width
> 0)
1096 *ret_g
= fw
->icon_g
.picture_w_g
;
1097 if (!HAS_NO_ICON_TITLE(fw
))
1099 ret_g
->height
+= fw
->icon_g
.title_w_g
.height
;
1102 else if (!HAS_NO_ICON_TITLE(fw
))
1104 *ret_g
= fw
->icon_g
.title_w_g
;
1108 memset(ret_g
, 0, sizeof(*ret_g
));
1115 /* returns the icon geometry (unexpanded title plus pixmap) if it exists */
1116 void get_icon_geometry(
1117 FvwmWindow
*fw
, rectangle
*ret_g
)
1119 /* valid geometry? */
1120 if (fw
->icon_g
.picture_w_g
.width
> 0)
1122 *ret_g
= fw
->icon_g
.picture_w_g
;
1123 if (!HAS_NO_ICON_TITLE(fw
))
1125 ret_g
->height
+= fw
->icon_g
.title_w_g
.height
;
1128 else if (fw
->icon_g
.title_w_g
.width
> 0)
1130 *ret_g
= fw
->icon_g
.title_w_g
;
1132 /* valid position? */
1133 else if (fw
->icon_g
.picture_w_g
.x
!= 0 || fw
->icon_g
.picture_w_g
.y
!= 0)
1135 *ret_g
= fw
->icon_g
.picture_w_g
;
1137 else if (fw
->icon_g
.title_w_g
.x
!= 0 || fw
->icon_g
.title_w_g
.y
!= 0)
1139 *ret_g
= fw
->icon_g
.title_w_g
;
1143 memset(ret_g
, 0, sizeof(*ret_g
));
1149 /* Returns the visible geometry of a window or icon. This can be used to test
1150 * if this region overlaps other windows. */
1151 Bool
get_visible_window_or_icon_geometry(
1152 FvwmWindow
*fw
, rectangle
*ret_g
)
1154 if (IS_ICONIFIED(fw
))
1156 return get_visible_icon_geometry(fw
, ret_g
);
1158 *ret_g
= fw
->g
.frame
;
1163 void move_icon_to_position(
1166 Bool draw_picture_w
= False
;
1167 Bool draw_title_w
= False
;
1169 if (fw
->icon_g
.picture_w_g
.width
> 0)
1173 if (Scr
.Hilite
== fw
)
1182 dpy
, FW_W_ICON_PIXMAP(fw
),
1183 fw
->icon_g
.picture_w_g
.x
,
1184 fw
->icon_g
.picture_w_g
.y
);
1185 if (fw
->icon_alphaPixmap
||
1186 (cs
>= 0 && Colorset
[cs
].icon_alpha_percent
< 100) ||
1187 CSET_IS_TRANSPARENT(fw
->icon_background_cs
) ||
1188 (!IS_ICON_SHAPED(fw
) && fw
->icon_background_padding
> 0))
1190 draw_picture_w
= True
;
1193 if (!HAS_NO_ICON_TITLE(fw
))
1198 if (Scr
.Hilite
== fw
)
1200 cs
= fw
->icon_title_cs_hi
;
1204 cs
= fw
->icon_title_cs
;
1207 dpy
, FW_W_ICON_TITLE(fw
),
1208 fw
->icon_g
.title_w_g
.x
,
1209 fw
->icon_g
.title_w_g
.y
);
1210 if (CSET_IS_TRANSPARENT(cs
) &&
1211 !get_visible_icon_picture_geometry(fw
, &dummy
) &&
1212 get_visible_icon_title_geometry(fw
, &dummy
))
1214 draw_title_w
= True
;
1218 if (draw_title_w
|| draw_picture_w
)
1221 fw
, draw_title_w
, draw_picture_w
, False
, draw_picture_w
,
1228 void broadcast_icon_geometry(
1229 FvwmWindow
*fw
, Bool do_force
)
1234 rc
= get_visible_icon_geometry(fw
, &g
);
1235 if (rc
== True
&& (!IS_ICON_UNMAPPED(fw
) || do_force
== True
))
1238 M_ICON_LOCATION
, 7, (long)FW_W(fw
),
1239 (long)FW_W_FRAME(fw
), (unsigned long)fw
,
1240 (long)g
.x
, (long)g
.y
, (long)g
.width
, (long)g
.height
);
1246 void modify_icon_position(
1247 FvwmWindow
*fw
, int dx
, int dy
)
1249 if (fw
->icon_g
.picture_w_g
.width
> 0 || HAS_NO_ICON_TITLE(fw
))
1251 /* picture position is also valid if there is neither a picture
1253 fw
->icon_g
.picture_w_g
.x
+= dx
;
1254 fw
->icon_g
.picture_w_g
.y
+= dy
;
1256 if (!HAS_NO_ICON_TITLE(fw
))
1258 fw
->icon_g
.title_w_g
.x
+= dx
;
1259 fw
->icon_g
.title_w_g
.y
+= dy
;
1265 /* set the icon position to the specified value. take care of the actual icon
1267 void set_icon_position(
1268 FvwmWindow
*fw
, int x
, int y
)
1270 if (fw
->icon_g
.picture_w_g
.width
> 0)
1272 fw
->icon_g
.picture_w_g
.x
= x
;
1273 fw
->icon_g
.picture_w_g
.y
= y
;
1277 fw
->icon_g
.picture_w_g
.x
= 0;
1278 fw
->icon_g
.picture_w_g
.y
= 0;
1280 if (!HAS_NO_ICON_TITLE(fw
))
1282 fw
->icon_g
.title_w_g
.x
= x
;
1283 fw
->icon_g
.title_w_g
.y
= y
;
1287 fw
->icon_g
.title_w_g
.x
= 0;
1288 fw
->icon_g
.title_w_g
.y
= 0;
1290 if (fw
->icon_g
.picture_w_g
.width
> 0 &&
1291 !HAS_NO_ICON_TITLE(fw
))
1293 fw
->icon_g
.title_w_g
.x
-=
1294 (fw
->icon_g
.title_w_g
.width
-
1295 fw
->icon_g
.picture_w_g
.width
) / 2;
1296 fw
->icon_g
.title_w_g
.y
+=
1297 fw
->icon_g
.picture_w_g
.height
;
1299 else if (fw
->icon_g
.picture_w_g
.width
<= 0 && HAS_NO_ICON_TITLE(fw
))
1301 /* In case there is no icon, fake the icon position so the
1302 * modules know where its window was iconified. */
1303 fw
->icon_g
.picture_w_g
.x
= x
;
1304 fw
->icon_g
.picture_w_g
.y
= y
;
1310 void set_icon_picture_size(
1311 FvwmWindow
*fw
, int w
, int h
)
1313 if (fw
->icon_g
.picture_w_g
.width
> 0)
1315 fw
->icon_g
.picture_w_g
.width
= w
;
1316 fw
->icon_g
.picture_w_g
.height
= h
;
1320 fw
->icon_g
.picture_w_g
.width
= 0;
1321 fw
->icon_g
.picture_w_g
.height
= 0;
1327 void resize_icon_title_height(FvwmWindow
*fw
, int dh
)
1329 if (!HAS_NO_ICON_TITLE(fw
))
1331 fw
->icon_g
.title_w_g
.height
+= dh
;
1337 void get_page_offset_rectangle(
1338 int *ret_page_x
, int *ret_page_y
, rectangle
*r
)
1340 int xoff
= Scr
.Vx
% Scr
.MyDisplayWidth
;
1341 int yoff
= Scr
.Vy
% Scr
.MyDisplayHeight
;
1343 /* maximize on the page where the center of the window is */
1344 *ret_page_x
= truncate_to_multiple(
1345 r
->x
+ r
->width
/ 2 + xoff
, Scr
.MyDisplayWidth
) - xoff
;
1346 *ret_page_y
= truncate_to_multiple(
1347 r
->y
+ r
->height
/ 2 + yoff
, Scr
.MyDisplayHeight
) - yoff
;
1352 void get_page_offset(
1353 int *ret_page_x
, int *ret_page_y
, FvwmWindow
*fw
)
1357 r
.x
= fw
->g
.frame
.x
;
1358 r
.y
= fw
->g
.frame
.y
;
1359 r
.width
= fw
->g
.frame
.width
;
1360 r
.height
= fw
->g
.frame
.height
;
1361 get_page_offset_rectangle(ret_page_x
, ret_page_y
, &r
);
1366 void get_page_offset_check_visible(
1367 int *ret_page_x
, int *ret_page_y
, FvwmWindow
*fw
)
1369 if (IsRectangleOnThisPage(&fw
->g
.frame
, fw
->Desk
))
1371 /* maximize on visible page if any part of the window is
1378 get_page_offset(ret_page_x
, ret_page_y
, fw
);
1384 /* ---------------------------- builtin commands --------------------------- */