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 ---------------------- */
24 #include "libs/fvwmlib.h"
25 #include "libs/FShape.h"
26 #include "libs/Grab.h"
27 #include "libs/charmap.h"
28 #include "libs/wcontext.h"
31 #include "execcontext.h"
36 #include "module_interface.h"
43 /* ---------------------------- local definitions -------------------------- */
45 /* ---------------------------- local macros ------------------------------- */
47 /* ---------------------------- imports ------------------------------------ */
49 /* ---------------------------- included code files ------------------------ */
51 /* ---------------------------- local types -------------------------------- */
61 } frame_decor_gravities_type
;
65 /* filled when args are created */
66 frame_move_resize_mode mode
;
67 frame_decor_gravities_type grav
;
69 size_borders b_no_title_g
;
70 rectangle curr_sidebar_g
;
79 int curr_titlebar_compression
;
80 direction_t shade_dir
;
81 window_parts trans_parts
;
84 unsigned do_force
: 1;
85 unsigned do_not_configure_client
: 1;
86 unsigned do_not_draw
: 1;
87 unsigned do_restore_gravity
: 1;
88 unsigned do_set_bit_gravity
: 1;
89 unsigned do_update_shape
: 1;
90 unsigned had_handles
: 1;
91 unsigned is_lazy_shading
: 1;
92 unsigned is_setup
: 1;
93 unsigned is_shading
: 1;
94 unsigned was_moved
: 1;
96 /* used during the animation */
97 int next_titlebar_compression
;
98 rectangle next_sidebar_g
;
102 int minimal_w_offset
;
103 int minimal_h_offset
;
106 /* cleared before each step */
107 unsigned do_hide_parent
: 1;
108 unsigned do_unhide_parent
: 1;
109 unsigned is_hidden
: 1;
110 unsigned was_hidden
: 1;
114 /* ---------------------------- forward declarations ----------------------- */
116 /* ---------------------------- local variables ---------------------------- */
118 /* windows used to hide animation steps */
125 /* ---------------------------- exported variables (globals) --------------- */
127 /* ---------------------------- local functions ---------------------------- */
130 static void print_g(char *text
, rectangle
*g
)
134 fprintf(stderr
, "%s: (null)", (text
== NULL
) ? "" : text
);
138 fprintf(stderr
, "%s: %4d %4d %4dx%4d (%4d - %4d %4d - %4d)\n",
139 (text
== NULL
) ? "" : text
,
140 g
->x
, g
->y
, g
->width
, g
->height
,
141 g
->x
, g
->x
+ g
->width
- 1, g
->y
, g
->y
+ g
->height
- 1);
146 static void combine_gravities(
147 frame_decor_gravities_type
*ret_grav
,
148 frame_decor_gravities_type
*grav_x
,
149 frame_decor_gravities_type
*grav_y
)
151 ret_grav
->decor_grav
= gravity_combine_xy_grav(
152 grav_x
->decor_grav
, grav_y
->decor_grav
);
153 ret_grav
->title_grav
= gravity_combine_xy_grav(
154 grav_x
->title_grav
, grav_y
->title_grav
);
155 ret_grav
->lbutton_grav
= gravity_combine_xy_grav(
156 grav_x
->lbutton_grav
, grav_y
->lbutton_grav
);
157 ret_grav
->rbutton_grav
= gravity_combine_xy_grav(
158 grav_x
->rbutton_grav
, grav_y
->rbutton_grav
);
159 ret_grav
->parent_grav
= gravity_combine_xy_grav(
160 grav_x
->parent_grav
, grav_y
->parent_grav
);
161 ret_grav
->client_grav
= gravity_combine_xy_grav(
162 grav_x
->client_grav
, grav_y
->client_grav
);
167 static void get_resize_decor_gravities_one_axis(
168 frame_decor_gravities_type
*ret_grav
, direction_t title_dir
,
169 frame_move_resize_mode axis_mode
, direction_t neg_dir
,
170 direction_t pos_dir
, int is_moving
)
177 title_grav
= gravity_dir_to_grav(title_dir
);
178 neg_grav
= gravity_dir_to_grav(neg_dir
);
179 pos_grav
= gravity_dir_to_grav(pos_dir
);
180 if (title_dir
!= DIR_NONE
)
182 ret_grav
->decor_grav
= title_grav
;
183 ret_grav
->lbutton_grav
= title_grav
;
184 ret_grav
->title_grav
= title_grav
;
185 ret_grav
->rbutton_grav
= title_grav
;
189 ret_grav
->decor_grav
= neg_grav
;
190 ret_grav
->lbutton_grav
= neg_grav
;
191 ret_grav
->title_grav
= neg_grav
;
192 ret_grav
->rbutton_grav
= pos_grav
;
196 case FRAME_MR_SCROLL
:
197 ret_grav
->client_grav
= (is_moving
) ? neg_grav
: pos_grav
;
199 case FRAME_MR_SHRINK
:
200 ret_grav
->client_grav
= (is_moving
) ? pos_grav
: neg_grav
;
202 case FRAME_MR_OPAQUE
:
203 case FRAME_MR_FORCE_SETUP
:
204 case FRAME_MR_FORCE_SETUP_NO_W
:
206 case FRAME_MR_SETUP_BY_APP
:
207 ret_grav
->client_grav
= neg_grav
;
209 case FRAME_MR_DONT_DRAW
:
210 /* can not happen, just a dummy to keep -Wall happy */
213 ret_grav
->parent_grav
= ret_grav
->client_grav
;
218 static void frame_get_titlebar_dimensions_only(
219 FvwmWindow
*fw
, rectangle
*frame_g
, size_borders
*bs
,
220 rectangle
*ret_titlebar_g
)
226 switch (GET_TITLE_DIR(fw
))
230 ret_titlebar_g
->x
= (GET_TITLE_DIR(fw
) == DIR_W
) ?
232 frame_g
->width
- bs
->bottom_right
.width
-
234 ret_titlebar_g
->y
= bs
->top_left
.height
;
235 ret_titlebar_g
->width
= fw
->title_thickness
;
236 ret_titlebar_g
->height
=
237 frame_g
->height
- bs
->total_size
.height
;
241 default: /* default makes gcc4 happy */
242 ret_titlebar_g
->y
= (GET_TITLE_DIR(fw
) == DIR_N
) ?
243 bs
->top_left
.height
:
244 frame_g
->height
- bs
->bottom_right
.height
-
246 ret_titlebar_g
->x
= bs
->top_left
.width
;
247 ret_titlebar_g
->width
= frame_g
->width
- bs
->total_size
.width
;
248 ret_titlebar_g
->height
= fw
->title_thickness
;
255 static void frame_setup_border(
256 FvwmWindow
*fw
, rectangle
*frame_g
, window_parts setup_parts
,
266 if (HAS_NO_BORDER(fw
))
270 frame_get_sidebar_geometry(
271 fw
, NULL
, frame_g
, &sidebar_g
, &dummy
, &dummy
);
272 for (part
= PART_BORDER_N
; (part
& PART_FRAME
);
275 if ((part
& PART_FRAME
& setup_parts
) == PART_NONE
)
279 border_get_part_geometry(fw
, part
, &sidebar_g
, &part_g
, &w
);
280 if (part_g
.width
<= 0 || part_g
.height
<= 0)
291 xwc
.width
= part_g
.width
;
292 xwc
.height
= part_g
.height
;
296 if (part
== PART_BORDER_NE
|| part
== PART_BORDER_E
||
297 part
== PART_BORDER_SE
)
299 xwc
.x
-= diff_g
->width
;
301 if (part
== PART_BORDER_SW
|| part
== PART_BORDER_S
||
302 part
== PART_BORDER_SE
)
304 xwc
.y
-= diff_g
->height
;
307 XConfigureWindow(dpy
, w
, CWWidth
| CWHeight
| CWX
| CWY
, &xwc
);
313 static void frame_setup_titlebar(
314 FvwmWindow
*fw
, rectangle
*frame_g
, window_parts setup_parts
,
317 frame_title_layout_t title_layout
;
324 frame_get_titlebar_dimensions(fw
, frame_g
, diff_g
, &title_layout
);
325 /* configure buttons */
326 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
328 if (FW_W_BUTTON(fw
, i
) != None
&& (setup_parts
& PART_BUTTONS
))
331 dpy
, FW_W_BUTTON(fw
, i
),
332 title_layout
.button_g
[i
].x
,
333 title_layout
.button_g
[i
].y
,
334 title_layout
.button_g
[i
].width
,
335 title_layout
.button_g
[i
].height
);
338 /* configure title */
339 if (setup_parts
& PART_TITLE
)
343 title_layout
.title_g
.x
, title_layout
.title_g
.y
,
344 title_layout
.title_g
.width
,
345 title_layout
.title_g
.height
);
351 static void __frame_setup_window(
352 FvwmWindow
*fw
, rectangle
*frame_g
, Bool do_send_configure_notify
,
353 Bool do_force
, Bool is_application_request
)
355 frame_move_resize_args mr_args
;
356 Bool is_resized
= False
;
357 Bool is_moved
= False
;
366 if (new_g
.height
< 1)
371 if (new_g
.width
!= fw
->g
.frame
.width
||
372 new_g
.height
!= fw
->g
.frame
.height
)
376 if (new_g
.x
!= fw
->g
.frame
.x
|| new_g
.y
!= fw
->g
.frame
.y
)
380 /* setup the window */
381 if (is_resized
|| do_force
)
383 frame_move_resize_mode mode
;
385 if (is_application_request
)
387 mode
= FRAME_MR_SETUP_BY_APP
;
391 mode
= FRAME_MR_FORCE_SETUP
;
395 mode
= FRAME_MR_SETUP
;
397 mr_args
= frame_create_move_resize_args(
398 fw
, mode
, NULL
, &new_g
, 0, DIR_NONE
);
399 frame_move_resize(fw
, mr_args
);
400 ((mr_args_internal
*)mr_args
)->flags
.was_moved
= 0;
401 frame_free_move_resize_args(fw
, mr_args
);
402 fw
->g
.frame
= *frame_g
;
406 unsigned int draw_parts
= PART_NONE
;
408 /* inform the application of the change
410 * According to the July 27, 1988 ICCCM draft, we should send a
411 * synthetic ConfigureNotify event to the client if the window
412 * was moved but not resized. */
413 XMoveWindow(dpy
, FW_W_FRAME(fw
), frame_g
->x
, frame_g
->y
);
414 fw
->g
.frame
= *frame_g
;
415 if ((draw_parts
= border_get_transparent_decorations_part(fw
))
418 border_draw_decorations(
420 ((fw
== get_focus_window())) ? True
: False
,
421 True
, CLEAR_ALL
, NULL
, NULL
);
423 fw
->g
.frame
= *frame_g
;
424 do_send_configure_notify
= True
;
426 /* must not send events to shaded windows because this might cause them
427 * to look at their current geometry */
428 if (do_send_configure_notify
&& !IS_SHADED(fw
))
431 fw
, new_g
.x
, new_g
.y
, new_g
.width
, new_g
.height
, 0,
434 /* get things updated */
436 /* inform the modules of the change */
437 BroadcastConfig(M_CONFIGURE_WINDOW
,fw
);
442 static void frame_reparent_hide_windows(
447 hide_wins
.parent
= w
;
448 for (i
= 0; i
< 4 ; i
++)
452 XUnmapWindow(dpy
, hide_wins
.w
[i
]);
454 XReparentWindow(dpy
, hide_wins
.w
[i
], w
, -1, -1);
458 XRaiseWindow(dpy
, hide_wins
.w
[0]);
459 XRestackWindows(dpy
, hide_wins
.w
, 4);
465 /* Returns True if the frame is so small that the parent window would have a
466 * width or height smaller than one pixel. */
467 static Bool
frame_is_parent_hidden(
468 FvwmWindow
*fw
, rectangle
*frame_g
)
472 get_window_borders(fw
, &b
);
473 if (frame_g
->width
<= b
.total_size
.width
||
474 frame_g
->height
<= b
.total_size
.height
)
482 /* Returns the number of pixels that the title bar is too short to accomodate
483 * all the title buttons and a title window that has at least a length of one
485 static int frame_get_titlebar_compression(
486 FvwmWindow
*fw
, rectangle
*frame_g
)
496 get_window_borders(fw
, &b
);
497 if (HAS_VERTICAL_TITLE(fw
))
499 space
= frame_g
->height
- b
.total_size
.height
;
503 space
= frame_g
->width
- b
.total_size
.width
;
505 need_space
= (fw
->nr_left_buttons
+ fw
->nr_right_buttons
) *
506 fw
->title_thickness
+ MIN_WINDOW_TITLE_LENGTH
;
507 if (space
< need_space
)
509 return need_space
- space
;
515 /* Calculates the gravities for the various parts of the decor through ret_grav.
516 * This can be passed to frame_set_decor_gravities.
519 * The direction of the title in the frame.
521 * The mode for the resize operation
523 static void frame_get_resize_decor_gravities(
524 frame_decor_gravities_type
*ret_grav
, direction_t title_dir
,
525 frame_move_resize_mode rmode
, rectangle
*delta_g
)
527 frame_decor_gravities_type grav_x
;
528 frame_decor_gravities_type grav_y
;
529 direction_t title_dir_x
;
530 direction_t title_dir_y
;
532 gravity_split_xy_dir(&title_dir_x
, &title_dir_y
, title_dir
);
533 get_resize_decor_gravities_one_axis(
534 &grav_x
, title_dir_x
, rmode
, DIR_W
, DIR_E
, (delta_g
->x
!= 0));
535 get_resize_decor_gravities_one_axis(
536 &grav_y
, title_dir_y
, rmode
, DIR_N
, DIR_S
, (delta_g
->y
!= 0));
537 combine_gravities(ret_grav
, &grav_x
, &grav_y
);
542 /* sets the gravity for the various parts of the window */
543 static void frame_set_decor_gravities(
544 FvwmWindow
*fw
, frame_decor_gravities_type
*grav
,
545 int do_set1_restore2_bit_gravity
)
548 XSetWindowAttributes xcwa
;
550 Bool button_reverted
= False
;
552 /* using bit gravity can reduce redrawing dramatically */
553 valuemask
= CWWinGravity
;
554 xcwa
.win_gravity
= grav
->client_grav
;
555 if (do_set1_restore2_bit_gravity
== 1)
557 XWindowAttributes xwa
;
559 if (!fw
->attr_backup
.is_bit_gravity_stored
&&
560 XGetWindowAttributes(dpy
, FW_W(fw
), &xwa
))
562 fw
->attr_backup
.bit_gravity
= xwa
.bit_gravity
;
564 fw
->attr_backup
.is_bit_gravity_stored
= 1;
565 valuemask
|= CWBitGravity
;
566 xcwa
.bit_gravity
= grav
->client_grav
;
568 else if (do_set1_restore2_bit_gravity
== 2)
570 fw
->attr_backup
.is_bit_gravity_stored
= 0;
571 valuemask
|= CWBitGravity
;
572 xcwa
.bit_gravity
= fw
->attr_backup
.bit_gravity
;
574 XChangeWindowAttributes(dpy
, FW_W(fw
), valuemask
, &xcwa
);
575 xcwa
.win_gravity
= grav
->parent_grav
;
576 valuemask
= CWWinGravity
;
577 XChangeWindowAttributes(dpy
, FW_W_PARENT(fw
), valuemask
, &xcwa
);
582 xcwa
.win_gravity
= grav
->title_grav
;
583 XChangeWindowAttributes(dpy
, FW_W_TITLE(fw
), valuemask
, &xcwa
);
584 if (fw
->title_text_rotation
== ROTATION_270
||
585 fw
->title_text_rotation
== ROTATION_180
)
587 button_reverted
= True
;
591 xcwa
.win_gravity
= grav
->rbutton_grav
;
595 xcwa
.win_gravity
= grav
->lbutton_grav
;
597 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
+= 2)
599 if (FW_W_BUTTON(fw
, i
))
601 XChangeWindowAttributes(
602 dpy
, FW_W_BUTTON(fw
, i
), valuemask
, &xcwa
);
607 xcwa
.win_gravity
= grav
->lbutton_grav
;
611 xcwa
.win_gravity
= grav
->rbutton_grav
;
613 for (i
= 1; i
< NUMBER_OF_TITLE_BUTTONS
; i
+= 2)
615 if (FW_W_BUTTON(fw
, i
))
617 XChangeWindowAttributes(
618 dpy
, FW_W_BUTTON(fw
, i
), valuemask
, &xcwa
);
625 /* Just restore the win and bit gravities on the client window. */
626 static void frame_restore_client_gravities(FvwmWindow
*fw
)
628 XSetWindowAttributes xcwa
;
631 valuemask
= CWWinGravity
;
632 if (fw
->attr_backup
.is_bit_gravity_stored
)
634 fw
->attr_backup
.is_bit_gravity_stored
= 0;
635 xcwa
.bit_gravity
= fw
->attr_backup
.bit_gravity
;
636 valuemask
|= CWBitGravity
;
638 xcwa
.win_gravity
= fw
->hints
.win_gravity
;
639 XChangeWindowAttributes(dpy
, FW_W(fw
), valuemask
, &xcwa
);
644 /* Prepares the structure for the next animation step. */
645 static void frame_next_move_resize_args(
646 frame_move_resize_args mr_args
)
648 mr_args_internal
*mra
;
650 mra
= (mr_args_internal
*)mr_args
;
651 mra
->curr_sidebar_g
= mra
->next_sidebar_g
;
652 mra
->current_g
= mra
->next_g
;
653 mra
->step_flags
.was_hidden
= mra
->step_flags
.is_hidden
;
654 mra
->curr_titlebar_compression
= mra
->next_titlebar_compression
;
659 static rectangle
*frame_get_hidden_pos(
660 FvwmWindow
*fw
, mr_args_internal
*mra
, Bool do_unhide
,
661 rectangle
*ret_hidden_g
)
667 if (do_unhide
== False
)
669 gravity_split_xy_dir(&dir_x
, &dir_y
, mra
->shade_dir
);
670 ret_hidden_g
->x
= (dir_x
== DIR_E
) ?
671 -mra
->client_g
.width
+ mra
->parent_s
.width
: 0;
672 ret_hidden_g
->y
= (dir_y
== DIR_S
) ?
673 -mra
->client_g
.height
+ mra
->parent_s
.height
: 0;
674 target_g
= &mra
->next_g
;
678 gravity_split_xy_dir(&dir_x
, &dir_y
, SHADED_DIR(fw
));
679 if (mra
->mode
== FRAME_MR_SCROLL
)
681 ret_hidden_g
->x
= (dir_x
== DIR_W
) ?
682 -mra
->client_g
.width
+ mra
->parent_s
.width
: 0;
683 ret_hidden_g
->y
= (dir_y
== DIR_N
) ?
684 -mra
->client_g
.height
+ mra
->parent_s
.height
:
689 ret_hidden_g
->x
= (dir_x
== DIR_E
) ?
690 -mra
->client_g
.width
+ mra
->parent_s
.width
: 0;
691 ret_hidden_g
->y
= (dir_y
== DIR_S
) ?
692 -mra
->client_g
.height
+ mra
->parent_s
.height
:
695 target_g
= &mra
->next_g
;
701 static void frame_update_hidden_window_pos(
702 FvwmWindow
*fw
, mr_args_internal
*mra
, Bool do_unhide
)
707 target_g
= frame_get_hidden_pos(fw
, mra
, do_unhide
, &hidden_g
);
709 dpy
, FW_W_PARENT(fw
), mra
->b_g
.top_left
.width
,
710 mra
->b_g
.top_left
.height
,
711 max(1, target_g
->width
- mra
->b_g
.total_size
.width
),
712 max(1, target_g
->height
- mra
->b_g
.total_size
.height
));
714 dpy
, FW_W(fw
), hidden_g
.x
, hidden_g
.y
, mra
->client_g
.width
,
715 mra
->client_g
.height
);
716 mra
->flags
.was_moved
= 1;
721 static void frame_prepare_animation_shape(
722 FvwmWindow
*fw
, mr_args_internal
*mra
, int parent_x
, int parent_y
)
727 if (!FShapesSupported
)
731 parent_g
.x
= parent_x
;
732 parent_g
.y
= parent_y
;
733 parent_g
.width
= mra
->parent_s
.width
;
734 parent_g
.height
= mra
->parent_s
.height
;
735 gravity_move_resize_parent_child(
736 mra
->grav
.parent_grav
, &mra
->dstep_g
, &parent_g
);
737 client_g
= mra
->client_g
;
738 frame_get_hidden_pos(fw
, mra
, True
, &client_g
);
739 client_g
.x
+= parent_g
.x
;
740 client_g
.y
+= parent_g
.y
;
742 dpy
, Scr
.NoFocusWin
, FShapeBounding
, client_g
.x
, client_g
.y
,
743 FW_W(fw
), FShapeBounding
, FShapeSet
);
749 frame_get_titlebar_dimensions_only(
750 fw
, &mra
->next_g
, &mra
->b_no_title_g
, &tb_g
);
751 /* windows w/ titles */
754 rect
.width
= tb_g
.width
;
755 rect
.height
= tb_g
.height
;
756 FShapeCombineRectangles(
757 dpy
, Scr
.NoFocusWin
, FShapeBounding
, 0, 0, &rect
, 1,
758 FShapeUnion
, Unsorted
);
764 static void frame_mrs_prepare_vars(
765 FvwmWindow
*fw
, mr_args_internal
*mra
)
771 i
= mra
->current_step
;
772 mra
->next_g
= mra
->start_g
;
773 mra
->next_g
.x
+= (mra
->delta_g
.x
* i
) / mra
->anim_steps
;
774 mra
->next_g
.y
+= (mra
->delta_g
.y
* i
) / mra
->anim_steps
;
775 mra
->next_g
.width
+= (mra
->delta_g
.width
* i
) / mra
->anim_steps
;
776 mra
->next_g
.height
+= (mra
->delta_g
.height
* i
) / mra
->anim_steps
;
777 frame_get_sidebar_geometry(
778 fw
, NULL
, &mra
->next_g
, &mra
->next_sidebar_g
, &dummy
, &dummy
);
779 fvwmrect_subtract_rectangles(
780 &mra
->dstep_g
, &mra
->next_g
, &mra
->current_g
);
781 mra
->next_titlebar_compression
=
782 frame_get_titlebar_compression(fw
, &mra
->next_g
);
783 mra
->step_flags
.is_hidden
=
784 (frame_is_parent_hidden(fw
, &mra
->next_g
) == True
);
785 mra
->step_flags
.do_hide_parent
=
786 ((!mra
->step_flags
.was_hidden
|| mra
->flags
.do_force
) &&
787 mra
->step_flags
.is_hidden
);
788 mra
->step_flags
.do_unhide_parent
=
789 ((mra
->step_flags
.was_hidden
|| mra
->flags
.do_force
) &&
790 !mra
->step_flags
.is_hidden
);
791 /* get the parent's dimensions */
792 mra
->parent_s
.width
= mra
->next_g
.width
- mra
->b_g
.total_size
.width
;
793 if (mra
->parent_s
.width
< 1)
795 mra
->minimal_w_offset
= 1 - mra
->parent_s
.width
;
796 mra
->parent_s
.width
= 1;
800 mra
->minimal_w_offset
= 0;
802 mra
->parent_s
.height
= mra
->next_g
.height
- mra
->b_g
.total_size
.height
;
803 if (mra
->parent_s
.height
< 1)
805 mra
->minimal_h_offset
= 1 - mra
->parent_s
.height
;
806 mra
->parent_s
.height
= 1;
810 mra
->minimal_h_offset
= 0;
816 static void frame_mrs_hide_changing_parts(
817 mr_args_internal
*mra
)
830 if (mra
->mode
== FRAME_MR_SHRINK
)
832 if (mra
->dstep_g
.x
> 0)
834 l_add
= mra
->dstep_g
.x
;
836 if (mra
->dstep_g
.y
> 0)
838 t_add
= mra
->dstep_g
.y
;
841 else if (mra
->mode
== FRAME_MR_SCROLL
)
843 if (mra
->dstep_g
.x
== 0 && mra
->dstep_g
.width
< 0)
845 l_add
= -mra
->dstep_g
.width
;
847 if (mra
->dstep_g
.y
== 0 && mra
->dstep_g
.height
< 0)
849 t_add
= -mra
->dstep_g
.height
;
854 l_add
-= mra
->minimal_w_offset
;
858 r_add
= (mra
->dstep_g
.width
< 0) ? -mra
->dstep_g
.width
: 0;
859 r_add
-= mra
->minimal_w_offset
;
863 t_add
-= mra
->minimal_h_offset
;
867 b_add
= (mra
->dstep_g
.height
< 0) ? -mra
->dstep_g
.height
: 0;
868 b_add
-= mra
->minimal_h_offset
;
870 /* cover top border */
871 w
= mra
->current_g
.width
;
872 h
= mra
->b_g
.top_left
.height
+ t_add
;
875 XMoveResizeWindow(dpy
, hide_wins
.w
[0], 0, 0, w
, h
);
876 XMapWindow(dpy
, hide_wins
.w
[0]);
878 /* cover left border */
879 w
= mra
->b_g
.top_left
.width
+ l_add
;
880 h
= mra
->current_g
.height
;
883 XMoveResizeWindow(dpy
, hide_wins
.w
[1], 0, 0, w
, h
);
884 XMapWindow(dpy
, hide_wins
.w
[1]);
886 /* cover bottom border and possibly part of the client */
887 w
= mra
->current_g
.width
;
888 h
= mra
->b_g
.bottom_right
.height
+ b_add
;
892 dpy
, hide_wins
.w
[2], 0, mra
->current_g
.height
-
893 mra
->b_g
.bottom_right
.height
- b_add
, w
, h
);
894 XMapWindow(dpy
, hide_wins
.w
[2]);
896 /* cover right border and possibly part of the client */
897 w
= mra
->b_g
.bottom_right
.width
+ r_add
;
898 h
= mra
->current_g
.height
;
902 dpy
, hide_wins
.w
[3], mra
->current_g
.width
-
903 mra
->b_g
.bottom_right
.width
- r_add
, 0, w
, h
);
904 XMapWindow(dpy
, hide_wins
.w
[3]);
910 static void frame_mrs_hide_unhide_parent(
911 FvwmWindow
*fw
, mr_args_internal
*mra
)
913 XSetWindowAttributes xswa
;
915 if (mra
->step_flags
.do_unhide_parent
)
919 /* update the hidden position of the client */
920 frame_update_hidden_window_pos(fw
, mra
, True
);
921 w
[0] = hide_wins
.w
[3];
922 w
[1] = FW_W_PARENT(fw
);
923 XRestackWindows(dpy
, w
, 2);
925 else if (mra
->step_flags
.do_hide_parent
)
927 /* When the parent gets hidden, unmap it automatically, lower
928 * it while hidden, then remap it. Necessary to eliminate
930 xswa
.win_gravity
= UnmapGravity
;
931 XChangeWindowAttributes(
932 dpy
, FW_W_PARENT(fw
), CWWinGravity
, &xswa
);
938 static void frame_mrs_hide_unhide_parent2(
939 FvwmWindow
*fw
, mr_args_internal
*mra
)
941 XSetWindowAttributes xswa
;
943 /* finish hiding the parent */
944 if (mra
->step_flags
.do_hide_parent
)
946 xswa
.win_gravity
= mra
->grav
.parent_grav
;
947 XChangeWindowAttributes(
948 dpy
, FW_W_PARENT(fw
), CWWinGravity
, &xswa
);
949 /* update the hidden position of the client */
950 frame_update_hidden_window_pos(fw
, mra
, False
);
951 XLowerWindow(dpy
, FW_W_PARENT(fw
));
952 XMapWindow(dpy
, FW_W_PARENT(fw
));
958 static void frame_mrs_setup_draw_decorations(
959 FvwmWindow
*fw
, mr_args_internal
*mra
)
961 window_parts setup_parts
;
963 /* setup the title bar and the border */
964 setup_parts
= PART_TITLE
;
965 if (mra
->curr_titlebar_compression
!= mra
->next_titlebar_compression
||
966 mra
->mode
== FRAME_MR_FORCE_SETUP
)
968 setup_parts
|= PART_BUTTONS
;
970 frame_setup_titlebar(fw
, &mra
->next_g
, setup_parts
, &mra
->dstep_g
);
971 frame_setup_border(fw
, &mra
->next_g
, PART_ALL
, &mra
->dstep_g
);
972 /* draw the border and the titlebar */
973 if (mra
->flags
.do_not_draw
== 1)
977 else if (!mra
->flags
.is_shading
|| !mra
->flags
.is_lazy_shading
)
980 border_draw_decorations(
982 (mra
->w_with_focus
!= None
) ? True
: False
,
983 (mra
->flags
.do_force
) ? True
: False
, CLEAR_ALL
,
984 &mra
->current_g
, &mra
->next_g
);
986 else /* lazy shading */
988 /* Lazy shading relies on the proper window gravities and does
989 * not redraw the decorations during the animation. Only draw
990 * on the first step. */
991 if (mra
->current_step
== 1)
995 /* Use the larger width and height values from the
996 * current and the final geometry to get proper
998 lazy_g
.x
= mra
->current_g
.x
;
999 lazy_g
.y
= mra
->current_g
.y
;
1001 mra
->current_g
.width
, mra
->end_g
.width
);
1002 lazy_g
.height
= max(
1003 mra
->current_g
.height
, mra
->end_g
.height
);
1004 border_draw_decorations(
1006 (mra
->w_with_focus
!= None
) ? True
: False
,
1007 True
, CLEAR_ALL
, &mra
->current_g
, &lazy_g
);
1014 static void frame_mrs_resize_move_windows(
1015 FvwmWindow
*fw
, mr_args_internal
*mra
)
1017 /* setup the parent, the frame and the client window */
1018 if (!mra
->flags
.is_shading
)
1020 if (!mra
->step_flags
.is_hidden
&&
1021 !mra
->flags
.do_not_configure_client
)
1024 dpy
, FW_W(fw
), 0, 0, mra
->parent_s
.width
,
1025 mra
->parent_s
.height
);
1026 mra
->client_g
.width
= mra
->parent_s
.width
;
1027 mra
->client_g
.height
= mra
->parent_s
.height
;
1031 XMoveWindow(dpy
, FW_W(fw
), 0, 0);
1033 mra
->flags
.was_moved
= 1;
1035 /* reduces flickering */
1036 /* dv (11-Aug-2002): ... and slows down large scripts
1037 * dramatically. Rather let it flicker */
1038 if (mra
->flags
.is_setup
)
1045 dpy
, FW_W_PARENT(fw
), mra
->b_g
.top_left
.width
,
1046 mra
->b_g
.top_left
.height
, mra
->parent_s
.width
,
1047 mra
->parent_s
.height
);
1054 x
= mra
->b_g
.top_left
.width
;
1055 y
= mra
->b_g
.top_left
.height
;
1056 if (mra
->mode
== FRAME_MR_SCROLL
)
1058 if (mra
->dstep_g
.x
== 0)
1060 x
-= mra
->dstep_g
.width
-
1061 mra
->minimal_w_offset
;
1063 if (mra
->dstep_g
.y
== 0)
1065 y
-= mra
->dstep_g
.height
-
1066 mra
->minimal_h_offset
;;
1069 else if (mra
->mode
== FRAME_MR_SHRINK
)
1071 x
+= mra
->dstep_g
.x
;
1072 y
+= mra
->dstep_g
.y
;
1076 x
-= mra
->minimal_w_offset
;
1080 x
+= mra
->minimal_w_offset
;
1084 y
-= mra
->minimal_h_offset
;
1088 y
+= mra
->minimal_h_offset
;
1091 dpy
, FW_W_PARENT(fw
), x
, y
, mra
->parent_s
.width
,
1092 mra
->parent_s
.height
);
1093 if (mra
->flags
.do_update_shape
)
1095 /* Step 1: apply the union of the old and new shapes.
1096 * This way so that the client stays visible - rather
1097 * let the background show through than force an
1099 frame_prepare_animation_shape(fw
, mra
, x
, y
);
1101 dpy
, FW_W_FRAME(fw
), FShapeBounding
, 0, 0,
1102 Scr
.NoFocusWin
, FShapeBounding
, FShapeUnion
);
1106 dpy
, FW_W_FRAME(fw
), mra
->next_g
.x
, mra
->next_g
.y
,
1107 mra
->next_g
.width
, mra
->next_g
.height
);
1108 if (mra
->flags
.do_update_shape
)
1110 /* Step 2: clip the previous shape. */
1112 dpy
, FW_W_FRAME(fw
), FShapeBounding
, 0, 0,
1113 Scr
.NoFocusWin
, FShapeBounding
, FShapeSet
);
1119 static void frame_move_resize_step(
1120 FvwmWindow
*fw
, mr_args_internal
*mra
)
1122 frame_mrs_prepare_vars(fw
, mra
);
1123 frame_mrs_hide_changing_parts(mra
);
1124 frame_mrs_hide_unhide_parent(fw
, mra
);
1125 frame_mrs_setup_draw_decorations(fw
, mra
);
1126 frame_mrs_resize_move_windows(fw
, mra
);
1127 frame_mrs_hide_unhide_parent2(fw
, mra
);
1128 fw
->g
.frame
= mra
->next_g
;
1134 static void frame_has_handles_and_tiled_border(
1135 FvwmWindow
*fw
, int *ret_has_handles
, int *ret_has_tiled_border
)
1139 *ret_has_handles
= 1;
1140 if (!HAS_HANDLES(fw
))
1142 *ret_has_handles
= 0;
1144 df
= border_get_border_style(fw
, (fw
== Scr
.Hilite
) ? True
: False
);
1145 if (DFS_HAS_HIDDEN_HANDLES(df
->style
))
1147 *ret_has_handles
= 0;
1149 *ret_has_tiled_border
=
1150 (DFS_FACE_TYPE(df
->style
) == TiledPixmapButton
) ||
1151 (DFS_FACE_TYPE(df
->style
) == ColorsetButton
&&
1152 !CSET_IS_TRANSPARENT_PR(df
->u
.acs
.cs
) &&
1153 CSET_HAS_PIXMAP(df
->u
.acs
.cs
));
1158 static int frame_get_shading_laziness(
1159 FvwmWindow
*fw
, mr_args_internal
*mra
)
1162 int has_tiled_pixmap_border
;
1163 int using_border_style
;
1165 if (!mra
->flags
.is_shading
|| mra
->anim_steps
<= 2)
1169 frame_has_handles_and_tiled_border(
1170 fw
, &has_handles
, &has_tiled_pixmap_border
);
1171 if (HAS_TITLE(fw
) && has_tiled_pixmap_border
)
1173 using_border_style
= border_is_using_border_style(
1174 fw
, (fw
== Scr
.Hilite
) ? True
: False
);
1178 using_border_style
= 0;
1180 switch (WINDOWSHADE_LAZINESS(fw
))
1182 case WINDOWSHADE_ALWAYS_LAZY
:
1184 case WINDOWSHADE_BUSY
:
1190 case WINDOWSHADE_LAZY
:
1192 if (has_tiled_pixmap_border
&& !HAS_NO_BORDER(fw
))
1196 else if (has_tiled_pixmap_border
&& HAS_TITLE(fw
) &&
1205 void frame_reshape_border(FvwmWindow
*fw
)
1213 /* calculate the new offsets */
1214 if (!IS_MAXIMIZED(fw
))
1216 grav
= fw
->hints
.win_gravity
;
1217 new_g
= &fw
->g
.normal
;
1221 /* maximized windows are always considered to have
1222 * NorthWestGravity */
1223 grav
= NorthWestGravity
;
1225 off_x
= fw
->g
.normal
.x
- fw
->g
.max
.x
;
1226 off_y
= fw
->g
.normal
.y
- fw
->g
.max
.y
;
1228 gravity_get_naked_geometry(grav
, fw
, &naked_g
, new_g
);
1229 gravity_translate_to_northwest_geometry_no_bw(
1230 grav
, fw
, &naked_g
, &naked_g
);
1231 set_window_border_size(fw
, fw
->unshaped_boundary_width
);
1232 gravity_add_decoration(grav
, fw
, new_g
, &naked_g
);
1233 if (IS_MAXIMIZED(fw
))
1235 /* prevent random paging when unmaximizing after the border
1236 * width has changed */
1237 fw
->g
.max_offset
.x
+= fw
->g
.normal
.x
- fw
->g
.max
.x
- off_x
;
1238 fw
->g
.max_offset
.y
+= fw
->g
.normal
.y
- fw
->g
.max
.y
- off_y
;
1242 get_unshaded_geometry(fw
, new_g
);
1243 if (USED_TITLE_DIR_FOR_SHADING(fw
))
1245 SET_SHADED_DIR(fw
, GET_TITLE_DIR(fw
));
1247 get_shaded_geometry(fw
, &fw
->g
.frame
, new_g
);
1248 frame_force_setup_window(
1249 fw
, fw
->g
.frame
.x
, fw
->g
.frame
.y
, fw
->g
.frame
.width
,
1250 fw
->g
.frame
.height
, False
);
1254 get_relative_geometry(new_g
, new_g
);
1255 frame_force_setup_window(
1256 fw
, new_g
->x
, new_g
->y
, new_g
->width
, new_g
->height
,
1263 /* ---------------------------- interface functions ------------------------ */
1265 /* Initialise structures local to frame.c */
1266 void frame_init(void)
1268 XSetWindowAttributes xswa
;
1269 unsigned long valuemask
;
1272 xswa
.override_redirect
= True
;
1273 xswa
.backing_store
= NotUseful
;
1274 xswa
.save_under
= False
;
1275 xswa
.win_gravity
= UnmapGravity
;
1276 xswa
.background_pixmap
= None
;
1277 valuemask
= CWOverrideRedirect
| CWSaveUnder
| CWBackingStore
|
1278 CWBackPixmap
| CWWinGravity
;
1279 hide_wins
.parent
= Scr
.Root
;
1280 for (i
= 0; i
< 4; i
++)
1282 hide_wins
.w
[i
] = XCreateWindow(
1283 dpy
, Scr
.Root
, -1, -1, 1, 1, 0, CopyFromParent
,
1284 InputOutput
, CopyFromParent
, valuemask
, &xswa
);
1285 if (hide_wins
.w
[i
] == None
)
1287 fvwm_msg(ERR
, "frame_init",
1288 "Could not create internal windows. Exiting");
1289 MyXUngrabServer(dpy
);
1297 Bool
is_frame_hide_window(
1306 for (i
= 0; i
< 4; i
++)
1308 if (w
== hide_wins
.w
[i
])
1317 void frame_destroyed_frame(
1320 if (hide_wins
.parent
== frame_w
)
1322 /* Oops, the window containing the hide windows was destroyed!
1323 * Let it die and create them from scratch. */
1330 void frame_get_titlebar_dimensions(
1331 FvwmWindow
*fw
, rectangle
*frame_g
, rectangle
*diff_g
,
1332 frame_title_layout_t
*title_layout
)
1353 Bool revert_button
= False
;
1359 get_window_borders_no_title(fw
, &b
);
1360 if (HAS_VERTICAL_TITLE(fw
))
1362 tb_length
= frame_g
->height
- b
.total_size
.height
;
1366 tb_length
= frame_g
->width
- b
.total_size
.width
;
1368 /* find out the length of the title and the buttons */
1369 tb_thick
= fw
->title_thickness
;
1370 nbuttons
= fw
->nr_left_buttons
+ fw
->nr_right_buttons
;
1372 b_length
= tb_thick
;
1373 t_length
= tb_length
- nbuttons
* b_length
;
1374 if (nbuttons
> 0 && t_length
< MIN_WINDOW_TITLE_LENGTH
)
1376 int diff
= MIN_WINDOW_TITLE_LENGTH
- t_length
;
1377 int pixels
= diff
/ nbuttons
;
1380 t_length
+= nbuttons
* pixels
;
1381 nbuttons_big
= nbuttons
- (MIN_WINDOW_TITLE_LENGTH
- t_length
);
1382 t_length
= MIN_WINDOW_TITLE_LENGTH
;
1384 if (b_length
< MIN_WINDOW_TITLEBUTTON_LENGTH
)
1386 /* don't draw the buttons */
1390 t_length
= tb_length
;
1396 fw
->title_length
= t_length
;
1397 /* prepare variables */
1398 if (HAS_VERTICAL_TITLE(fw
))
1400 tb_y
= b
.top_left
.height
;
1401 br_sub
= (diff_g
!= NULL
) ? diff_g
->height
: 0;
1402 if (GET_TITLE_DIR(fw
) == DIR_W
)
1404 tb_x
= b
.top_left
.width
;
1408 tb_x
= frame_g
->width
- b
.bottom_right
.width
-
1412 tb_x
-= diff_g
->width
;
1426 tb_x
= b
.top_left
.width
;
1427 br_sub
= (diff_g
!= NULL
) ? diff_g
->width
: 0;
1428 if (GET_TITLE_DIR(fw
) == DIR_N
)
1430 tb_y
= b
.top_left
.height
;
1434 tb_y
= frame_g
->height
- b
.bottom_right
.height
-
1438 tb_y
-= diff_g
->height
;
1450 if (fw
->title_text_rotation
== ROTATION_270
||
1451 fw
->title_text_rotation
== ROTATION_180
)
1453 revert_button
= True
;
1456 /* configure left buttons */
1457 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
1459 if ((revert_button
&& !(i
& 1)) ||
1460 (!revert_button
&& (i
& 1)) || FW_W_BUTTON(fw
, i
) == None
)
1466 title_layout
->button_g
[i
].x
= -1;
1467 title_layout
->button_g
[i
].y
= -1;
1468 title_layout
->button_g
[i
].width
= 1;
1469 title_layout
->button_g
[i
].height
= 1;
1473 title_layout
->button_g
[i
].x
= tb_x
;
1474 title_layout
->button_g
[i
].y
= tb_y
;
1475 title_layout
->button_g
[i
].width
= b_w
;
1476 title_layout
->button_g
[i
].height
= b_h
;
1478 *padd_coord
+= b_length
;
1480 if (nbuttons_big
== 0)
1486 /* configure title */
1489 title_layout
->title_g
.x
= -1;
1490 title_layout
->title_g
.y
= -1;
1491 title_layout
->title_g
.width
= 1;
1492 title_layout
->title_g
.height
= 1;
1496 title_layout
->title_g
.x
= tb_x
;
1497 title_layout
->title_g
.y
= tb_y
;
1498 title_layout
->title_g
.width
= t_w
;
1499 title_layout
->title_g
.height
= t_h
;
1501 *padd_coord
+= t_length
;
1502 /* configure right buttons */
1503 *padd_coord
-= br_sub
;
1504 for (i
= NUMBER_OF_TITLE_BUTTONS
-1; i
> -1; i
--)
1506 if ((revert_button
&& (i
& 1)) ||
1507 (!revert_button
&& !(i
& 1)) || FW_W_BUTTON(fw
, i
) == None
)
1513 title_layout
->button_g
[i
].x
= -1;
1514 title_layout
->button_g
[i
].y
= -1;
1515 title_layout
->button_g
[i
].width
= 1;
1516 title_layout
->button_g
[i
].height
= 1;
1520 title_layout
->button_g
[i
].x
= tb_x
;
1521 title_layout
->button_g
[i
].y
= tb_y
;
1522 title_layout
->button_g
[i
].width
= b_w
;
1523 title_layout
->button_g
[i
].height
= b_h
;
1525 *padd_coord
+= b_length
;
1527 if (nbuttons_big
== 0)
1537 void frame_get_sidebar_geometry(
1538 FvwmWindow
*fw
, DecorFaceStyle
*borderstyle
, rectangle
*frame_g
,
1539 rectangle
*ret_g
, Bool
*ret_has_x_marks
, Bool
*ret_has_y_marks
)
1548 *ret_has_x_marks
= False
;
1549 *ret_has_y_marks
= False
;
1550 if (HAS_NO_BORDER(fw
))
1554 /* get the corner size */
1555 if (!HAS_HANDLES(fw
))
1557 *ret_has_x_marks
= False
;
1558 *ret_has_y_marks
= False
;
1560 else if (borderstyle
== NULL
)
1562 if (fw
->decor_state
.parts_drawn
& PART_X_HANDLES
)
1564 *ret_has_x_marks
= True
;
1566 if (fw
->decor_state
.parts_drawn
& PART_Y_HANDLES
)
1568 *ret_has_y_marks
= True
;
1571 else if (!DFS_HAS_HIDDEN_HANDLES(*borderstyle
))
1573 *ret_has_x_marks
= True
;
1574 *ret_has_y_marks
= True
;
1576 ret_g
->x
= fw
->corner_width
;
1577 ret_g
->y
= fw
->corner_width
;
1578 min_w
= 2 * fw
->corner_width
+ 4;
1579 /* limit by available space, remove handle marks if necessary */
1580 if (frame_g
->width
< min_w
)
1582 ret_g
->x
= frame_g
->width
/ 3;
1583 *ret_has_y_marks
= False
;
1585 if (frame_g
->height
< min_w
)
1587 ret_g
->y
= frame_g
->height
/ 3;
1588 *ret_has_x_marks
= False
;
1590 get_window_borders_no_title(fw
, &b
);
1591 if (ret_g
->x
< b
.top_left
.width
)
1593 ret_g
->x
= b
.top_left
.width
;
1595 if (ret_g
->y
< b
.top_left
.height
)
1597 ret_g
->y
= b
.top_left
.height
;
1599 /* length of the side bars */
1600 ret_g
->width
= frame_g
->width
- 2 * ret_g
->x
;
1601 ret_g
->height
= frame_g
->height
- 2 * ret_g
->y
;
1606 int frame_window_id_to_context(
1607 FvwmWindow
*fw
, Window w
, int *ret_num
)
1609 int context
= C_ROOT
;
1612 if (fw
== NULL
|| w
== None
)
1616 if (w
== FW_W_TITLE(fw
))
1620 else if (Scr
.EwmhDesktop
&&
1621 (w
== FW_W(Scr
.EwmhDesktop
) ||
1622 w
== FW_W_PARENT(Scr
.EwmhDesktop
) ||
1623 w
== FW_W_FRAME(Scr
.EwmhDesktop
)))
1625 context
= C_EWMH_DESKTOP
;
1627 else if (w
== FW_W(fw
) || w
== FW_W_PARENT(fw
) || w
== FW_W_FRAME(fw
))
1631 else if (w
== FW_W_ICON_TITLE(fw
) || w
== FW_W_ICON_PIXMAP(fw
))
1635 else if (w
== FW_W_CORNER(fw
, 0))
1638 context
= C_F_TOPLEFT
;
1640 else if (w
== FW_W_CORNER(fw
, 1))
1643 context
= C_F_TOPRIGHT
;
1645 else if (w
== FW_W_CORNER(fw
, 2))
1648 context
= C_F_BOTTOMLEFT
;
1650 else if (w
== FW_W_CORNER(fw
, 3))
1653 context
= C_F_BOTTOMRIGHT
;
1655 else if (w
== FW_W_SIDE(fw
, 0))
1660 else if (w
== FW_W_SIDE(fw
, 1))
1663 context
= C_SB_RIGHT
;
1665 else if (w
== FW_W_SIDE(fw
, 2))
1668 context
= C_SB_BOTTOM
;
1670 else if (w
== FW_W_SIDE(fw
, 3))
1673 context
= C_SB_LEFT
;
1679 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
1681 if (w
== FW_W_BUTTON(fw
, i
) &&
1682 ((!(i
& 1) && i
/ 2 < Scr
.nr_left_buttons
) ||
1683 ( (i
& 1) && i
/ 2 < Scr
.nr_right_buttons
)))
1685 context
= (1 << i
) * C_L1
;
1691 if (!HAS_HANDLES(fw
) && (context
& (C_SIDEBAR
| C_FRAME
)))
1693 context
= C_SIDEBAR
;
1699 /* Creates a structure that must be passed to frame_move_resize(). The
1700 * structure *must* be deleted with frame_free_move_resize_args() as soon as the
1701 * move or resize operation is finished. Prepares the window for a move/resize
1706 * The window to move or resize.
1708 * The mode of operation:
1709 * FRAME_MR_SETUP: setup the frame
1710 * FRAME_MR_FORCE_SETUP: same, but forces all updates
1711 * FRAME_MR_OPAQUE: resize the frame in an opaque fashion
1712 * FRAME_MR_SHRINK: shrink the client window (useful for shading only)
1713 * FRAME_MR_SCROLL: scroll the client window (useful for shading only)
1715 * The initial geometry of the frame. If a NULL pointer is passed, the
1716 * frame_g member of the window is used instead.
1718 * The desired new geometry of the frame.
1720 * The number of animation steps in between
1721 * = 0: The operation is finished in a single step.
1722 * > 0: The given number of steps are drawn in between.
1723 * < 0: Each step resizes the window by the given number of pixels.
1724 * (the sign of the number is flipped first).
1725 * This argument is used only with FRAME_MR_SHRINK and FRAME_MR_SCROLL.
1727 frame_move_resize_args
frame_create_move_resize_args(
1728 FvwmWindow
*fw
, frame_move_resize_mode mr_mode
,
1729 rectangle
*start_g
, rectangle
*end_g
, int anim_steps
, int shade_dir
)
1731 mr_args_internal
*mra
;
1738 /* set some variables */
1739 mra
= (mr_args_internal
*)safecalloc(1, sizeof(mr_args_internal
));
1740 memset(mra
, 0, sizeof(*mra
));
1741 if (mr_mode
& FRAME_MR_DONT_DRAW
)
1743 mr_mode
&= ~FRAME_MR_DONT_DRAW
;
1744 mra
->flags
.do_not_draw
= 1;
1748 mra
->flags
.do_not_draw
= 0;
1750 if (mr_mode
== FRAME_MR_SETUP_BY_APP
)
1752 mr_mode
= FRAME_MR_SETUP
;
1753 mra
->flags
.do_set_bit_gravity
= 0;
1757 mra
->flags
.do_set_bit_gravity
= 1;
1759 if (mr_mode
== FRAME_MR_FORCE_SETUP_NO_W
)
1761 mr_mode
= FRAME_MR_FORCE_SETUP
;
1762 mra
->flags
.do_not_configure_client
= 1;
1764 mra
->mode
= mr_mode
;
1765 mra
->shade_dir
= (direction_t
)shade_dir
;
1766 mra
->w_with_focus
= (fw
== get_focus_window()) ? FW_W(fw
) : None
;
1768 /* calculate various geometries */
1772 dpy
, FW_W(fw
), &JunkRoot
, &mra
->client_g
.x
,
1773 &mra
->client_g
.y
, (unsigned int*)&mra
->client_g
.width
,
1774 (unsigned int*)&mra
->client_g
.height
,
1775 (unsigned int*)&JunkBW
, (unsigned int*)&JunkDepth
);
1778 rc
= XTranslateCoordinates(
1779 dpy
, FW_W_PARENT(fw
), Scr
.Root
,
1780 mra
->client_g
.x
, mra
->client_g
.y
,
1781 &mra
->client_g
.x
, &mra
->client_g
.y
,
1786 /* Can only happen if the window died */
1787 get_client_geometry(fw
, &mra
->client_g
);
1792 /* If the window was reisez while shaded the client window
1793 * will not have been resized. Use the frame to get the
1795 get_client_geometry(fw
, &mra
->client_g
);
1797 get_window_borders(fw
, &mra
->b_g
);
1798 get_window_borders_no_title(fw
, &mra
->b_no_title_g
);
1799 mra
->start_g
= (start_g
!= NULL
) ? *start_g
: fw
->g
.frame
;
1800 frame_get_sidebar_geometry(
1801 fw
, NULL
, &mra
->start_g
, &mra
->curr_sidebar_g
, &dummy
, &dummy
);
1802 mra
->end_g
= *end_g
;
1803 mra
->current_g
= mra
->start_g
;
1804 mra
->next_g
= mra
->end_g
;
1805 mra
->curr_titlebar_compression
=
1806 frame_get_titlebar_compression(fw
, &mra
->start_g
);
1807 fvwmrect_subtract_rectangles(
1808 &mra
->delta_g
, &mra
->end_g
, &mra
->start_g
);
1810 /* calcuate the number of animation steps */
1813 case FRAME_MR_SHRINK
:
1814 case FRAME_MR_SCROLL
:
1815 whdiff
= max(abs(mra
->delta_g
.width
), abs(mra
->delta_g
.height
));
1816 xydiff
= max(abs(mra
->delta_g
.x
), abs(mra
->delta_g
.y
));
1817 diff
= max(whdiff
, xydiff
);
1820 mra
->anim_steps
= 0;
1822 else if (anim_steps
< 0)
1824 mra
->anim_steps
= -(diff
- 1) / anim_steps
;
1826 else if (anim_steps
> 0 && anim_steps
>= diff
)
1828 mra
->anim_steps
= diff
- 1;
1832 mra
->anim_steps
= anim_steps
;
1836 case FRAME_MR_FORCE_SETUP
:
1837 case FRAME_MR_SETUP
:
1838 case FRAME_MR_OPAQUE
:
1840 mra
->anim_steps
= 1;
1845 mra
->flags
.was_moved
= 0;
1846 mra
->step_flags
.was_hidden
=
1847 (frame_is_parent_hidden(fw
, &mra
->start_g
) == True
);
1848 mra
->flags
.is_setup
=
1849 (mra
->mode
== FRAME_MR_FORCE_SETUP
||
1850 mra
->mode
== FRAME_MR_SETUP
);
1851 mra
->flags
.do_force
= (mra
->mode
== FRAME_MR_FORCE_SETUP
);
1852 mra
->flags
.is_shading
=
1853 !(mra
->flags
.is_setup
|| mra
->mode
== FRAME_MR_OPAQUE
);
1854 mra
->flags
.do_update_shape
=
1855 (FShapesSupported
&& mra
->flags
.is_shading
&& fw
->wShaped
);
1856 /* Lazy shading does not draw the hadle marks. Disable them in the
1857 * window flags if necessary. Restores the marks when mr_args are
1858 * freed. Lazy shading is considerably faster but causes funny looks
1859 * if either the border uses a tiled pixmap background. */
1860 mra
->flags
.had_handles
= HAS_HANDLES(fw
);
1861 mra
->flags
.is_lazy_shading
= frame_get_shading_laziness(fw
, mra
);
1862 mra
->trans_parts
= border_get_transparent_decorations_part(fw
);
1863 if (mra
->flags
.is_lazy_shading
)
1865 SET_HAS_HANDLES(fw
, 0);
1868 /* Set gravities for the window parts. */
1869 frame_get_resize_decor_gravities(
1870 &mra
->grav
, GET_TITLE_DIR(fw
), mra
->mode
, &mra
->delta_g
);
1871 if (mra
->flags
.is_setup
&& mra
->delta_g
.x
== 0 && mra
->delta_g
.y
== 0 &&
1872 mra
->delta_g
.width
== 0 && mra
->delta_g
.height
== 0)
1874 frame_decor_gravities_type grav
;
1876 /* The caller has already set the frame geometry. Use
1877 * StaticGravity so the sub windows are not moved to funny
1879 grav
.decor_grav
= StaticGravity
;
1880 grav
.title_grav
= StaticGravity
;
1881 grav
.lbutton_grav
= StaticGravity
;
1882 grav
.rbutton_grav
= StaticGravity
;
1883 grav
.parent_grav
= StaticGravity
;
1884 grav
.client_grav
= StaticGravity
;
1885 frame_set_decor_gravities(
1886 fw
, &grav
, (mra
->flags
.do_set_bit_gravity
) ? 1 : 0);
1887 mra
->flags
.do_restore_gravity
= 1;
1888 mra
->flags
.do_force
= 1;
1892 frame_set_decor_gravities(
1894 (mra
->flags
.do_set_bit_gravity
) ? 1 : 0);
1896 frame_reparent_hide_windows(FW_W_FRAME(fw
));
1898 return (frame_move_resize_args
)mra
;
1901 /* Changes the final_geometry in a frame_move_resize_args structure. This is
1902 * useful during opaque resize operations to avoid creating and destroying the
1903 * args for each animation step.
1905 * If FRAME_MR_SHRINK or FRAME_MR_SCROLL was used to greate the mr_args, the
1906 * function does nothing.
1908 void frame_update_move_resize_args(
1909 frame_move_resize_args mr_args
, rectangle
*end_g
)
1911 mr_args_internal
*mra
;
1913 mra
= (mr_args_internal
*)mr_args
;
1914 mra
->end_g
= *end_g
;
1915 fvwmrect_subtract_rectangles(
1916 &mra
->delta_g
, &mra
->end_g
, &mra
->start_g
);
1921 /* Destroys the structure allocated with frame_create_move_resize_args(). Does
1922 * some clean up operations on the modified window first. */
1923 void frame_free_move_resize_args(
1924 FvwmWindow
*fw
, frame_move_resize_args mr_args
)
1926 mr_args_internal
*mra
;
1928 mra
= (mr_args_internal
*)mr_args
;
1929 SET_HAS_HANDLES(fw
, mra
->flags
.had_handles
);
1930 fw
->g
.frame
= mra
->end_g
;
1931 if (mra
->flags
.is_lazy_shading
)
1933 border_draw_decorations(
1935 (mra
->w_with_focus
!= None
) ? True
: False
, True
,
1936 CLEAR_ALL
, &mra
->current_g
, &mra
->end_g
);
1938 else if (mra
->trans_parts
!= PART_NONE
)
1940 border_draw_decorations(
1941 fw
, mra
->trans_parts
,
1942 (mra
->w_with_focus
!= None
) ? True
: False
, True
,
1943 CLEAR_ALL
, &mra
->current_g
, &mra
->end_g
);
1945 update_absolute_geometry(fw
);
1946 frame_reparent_hide_windows(Scr
.NoFocusWin
);
1947 if (mra
->w_with_focus
!= None
)
1949 /* domivogt (28-Dec-1999): For some reason the XMoveResize() on
1950 * the frame window removes the input focus from the client
1951 * window. I have no idea why, but if we explicitly restore
1952 * the focus here everything works fine. */
1953 FOCUS_SET(mra
->w_with_focus
);
1955 if (mra
->flags
.do_update_shape
)
1959 dpy
, FW_W_FRAME(fw
), FShapeBounding
, 0, 0, None
,
1962 frame_setup_shape(fw
, mra
->end_g
.width
, mra
->end_g
.height
, fw
->wShaped
);
1963 if (mra
->flags
.do_restore_gravity
)
1965 mra
->grav
.client_grav
= fw
->hints
.win_gravity
;
1966 frame_set_decor_gravities(
1968 (mra
->flags
.do_set_bit_gravity
) ? 2 : 0);
1972 frame_restore_client_gravities(fw
);
1974 if (!IS_SHADED(fw
) && mra
->flags
.was_moved
)
1976 SendConfigureNotify(
1977 fw
, fw
->g
.frame
.x
, fw
->g
.frame
.y
, fw
->g
.frame
.width
,
1978 fw
->g
.frame
.height
, 0, True
);
1979 mra
->flags
.was_moved
= 0;
1981 focus_grab_buttons_on_layer(fw
->layer
);
1982 /* free the memory */
1988 void frame_move_resize(
1989 FvwmWindow
*fw
, frame_move_resize_args mr_args
)
1991 mr_args_internal
*mra
;
1992 Bool is_grabbed
= False
;
1995 mra
= (mr_args_internal
*)mr_args
;
1996 /* freeze the cursor shape; otherwise it may flash to a different shape
1997 * during the animation */
1998 if (mra
->anim_steps
> 1)
2000 is_grabbed
= GrabEm(None
, GRAB_FREEZE_CURSOR
);
2003 for (i
= 1; i
<= mra
->anim_steps
; i
++, frame_next_move_resize_args(mra
))
2005 mra
->current_step
= i
;
2006 frame_move_resize_step(fw
, mra
);
2008 if (is_grabbed
== True
)
2010 UngrabEm(GRAB_FREEZE_CURSOR
);
2016 /***********************************************************************
2019 * frame_setup_window - set window sizes
2022 * fw - the FvwmWindow pointer
2023 * x - the x coordinate of the upper-left outer corner of the frame
2024 * y - the y coordinate of the upper-left outer corner of the frame
2025 * w - the width of the frame window w/o border
2026 * h - the height of the frame window w/o border
2028 * Special Considerations:
2029 * This routine will check to make sure the window is not completely
2030 * off the display, if it is, it'll bring some of it back on.
2032 * The fw->frame_XXX variables should NOT be updated with the
2033 * values of x,y,w,h prior to calling this routine, since the new
2034 * values are compared against the old to see whether a synthetic
2035 * ConfigureNotify event should be sent. (It should be sent if the
2036 * window was moved but not resized.)
2038 ************************************************************************/
2039 void frame_setup_window(
2040 FvwmWindow
*fw
, int x
, int y
, int w
, int h
,
2041 Bool do_send_configure_notify
)
2049 __frame_setup_window(fw
, &g
, do_send_configure_notify
, False
, False
);
2054 void frame_setup_window_app_request(
2055 FvwmWindow
*fw
, int x
, int y
, int w
, int h
,
2056 Bool do_send_configure_notify
)
2064 __frame_setup_window(fw
, &g
, do_send_configure_notify
, False
, True
);
2069 void frame_force_setup_window(
2070 FvwmWindow
*fw
, int x
, int y
, int w
, int h
,
2071 Bool do_send_configure_notify
)
2079 __frame_setup_window(fw
, &g
, do_send_configure_notify
, True
, False
);
2084 /****************************************************************************
2086 * Sets up the shaped window borders
2088 ****************************************************************************/
2089 void frame_setup_shape(FvwmWindow
*fw
, int w
, int h
, int shape_mode
)
2095 if (!FShapesSupported
)
2099 if (fw
->wShaped
!= shape_mode
)
2101 fw
->wShaped
= shape_mode
;
2102 frame_reshape_border(fw
);
2108 dpy
, FW_W_FRAME(fw
), FShapeBounding
, 0, 0, None
,
2113 /* shape the window */
2114 get_window_borders(fw
, &b
);
2116 dpy
, FW_W_FRAME(fw
), FShapeBounding
, b
.top_left
.width
,
2117 b
.top_left
.height
, FW_W(fw
), FShapeBounding
, FShapeSet
);
2120 /* windows w/ titles */
2123 get_title_geometry(fw
, &r
);
2126 rect
.width
= r
.width
;
2127 rect
.height
= r
.height
;
2128 FShapeCombineRectangles(
2129 dpy
, FW_W_FRAME(fw
), FShapeBounding
, 0, 0,
2130 &rect
, 1, FShapeUnion
, Unsorted
);
2137 /* ---------------------------- builtin commands --------------------------- */